diff --git a/.github/workflows/conda-build.yml b/.github/workflows/conda-build.yml new file mode 100644 index 0000000..a9b294a --- /dev/null +++ b/.github/workflows/conda-build.yml @@ -0,0 +1,43 @@ +name: Build Conda Recipe + +on: + push: + branches: + - development # You can change this to the branch you want to trigger on + +jobs: + build-linux: + name: CondaBuild (${{ matrix.python-version }}, ${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest", "macos-latest", "windows-latest"] + python-version: ["3.8", "3.11"] + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + + - name: Set up Conda + uses: conda-incubator/setup-miniconda@v3 + with: + auto-update-conda: true + python-version: ${{ matrix.python-version }} + mamba-version: "*" + channels: conda-forge,defaults + channel-priority: true + + - name: Display Conda Settings + shell: bash -el {0} + run: | + conda info + conda list + conda config --show-sources + conda config --show + printenv | sort + + - name: Build Conda Package + shell: bash -el {0} + run: | + mamba install conda-build boa + conda mambabuild conda-recipe diff --git a/.github/workflows/gitlab-sync.yml b/.github/workflows/gitlab-sync.yml new file mode 100644 index 0000000..6a9d8d2 --- /dev/null +++ b/.github/workflows/gitlab-sync.yml @@ -0,0 +1,22 @@ +name: GitlabSync + +on: + - push + - delete + +jobs: + sync: + runs-on: ubuntu-latest + name: Git Repo Sync + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - uses: wangchucheng/git-repo-sync@v0.1.0 + with: + # Such as https://github.com/wangchucheng/git-repo-sync.git + target-url: ${{ secrets.TARGET_URL }} + # Such as wangchucheng + target-username: ${{ secrets.TARGET_USERNAME }} + # You can store token in your project's 'Setting > Secrets' and reference the name here. Such as ${{ secrets.ACCESS\_TOKEN }} + target-token: ${{ secrets.TARGET_TOKEN }} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e0a9dd..f9b3f51 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,8 @@ -set (CMAKE_CXX_STANDARD 14) -set(CMAKE_OSX_ARCHITECTURES "x86_64") # Are we running cmake from this directory (out of tree build) ? if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + set (CMAKE_CXX_STANDARD 14) + set(CMAKE_OSX_ARCHITECTURES "x86_64") + cmake_minimum_required(VERSION 2.8.12) project(imp_module) diff --git a/Setup.cmake b/Setup.cmake index 8861bd3..bff712e 100644 --- a/Setup.cmake +++ b/Setup.cmake @@ -6,13 +6,13 @@ IF(NOT APPLE) INCLUDE(simd) IF(${AVX_FOUND}) MESSAGE("BUILD WITH SIMD") - add_compile_definitions(WITH_AVX) + ADD_DEFINITIONS(-DWITH_AVX) IF (MSVC) # https://devblogs.microsoft.com/cppblog/simd-extension-to-c-openmp-in-visual-studio/ # /Oi is for intrinsics - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX -openmp:experimental /Oi") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX /Oi") ELSE(MSVC) - STRING(APPEND CMAKE_CXX_FLAGS " -Ofast -mavx -mfma -ffast-math -funroll-loops") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx -mfma") ENDIF (MSVC) ELSE(${AVX_FOUND}) UNSET(WITH_AVX) diff --git a/conda-recipe/meta.yaml b/conda-recipe/meta.yaml index c4a69d8..6c759f0 100644 --- a/conda-recipe/meta.yaml +++ b/conda-recipe/meta.yaml @@ -1,4 +1,4 @@ -{% set version = "0.14.0" %} +{% set version = "0.14.2" %} package: name: imp.bff @@ -32,7 +32,6 @@ requirements: - cereal - mpir # [win] - msmpi # [win] -# - libmongoc - imp run: - {{ pin_compatible('numpy') }} diff --git a/dependency/mongoc.description b/dependency/mongoc.description deleted file mode 100644 index 0583d80..0000000 --- a/dependency/mongoc.description +++ /dev/null @@ -1,3 +0,0 @@ -pkg_config_name="libmongoc-1.0" -libraries="mongoc-1.0:bson-1.0" -headers="mongoc.h:bson.h" diff --git a/include/AV.h b/include/AV.h index 27a2fcb..92b580d 100644 --- a/include/AV.h +++ b/include/AV.h @@ -329,7 +329,7 @@ class IMPBFFEXPORT AV : public IMP::core::Gaussian { * @brief Get the mean position of the AV object. * @return The mean position as a Vector3D. */ - IMP::algebra::Vector3D get_mean_position() const; + IMP::algebra::Vector3D get_mean_position(bool include_source=true) const; /** * @brief Get the source coordinates of the AV object. diff --git a/include/DecayRoutines.h b/include/DecayRoutines.h index 9459de0..cfd2bd9 100644 --- a/include/DecayRoutines.h +++ b/include/DecayRoutines.h @@ -19,20 +19,18 @@ #include /* std::max */ #include /* strcmp */ -#if defined(_MSC_VER) -/* Microsoft C/C++-compatible compiler */ - #include - #include -#endif - #if defined(__AVX__) -#if (defined(__GNUC__) || defined(__clang__)) -#include -#include -#endif -#if !defined(__FMA__) -#define __FMA__ 1 -#endif + #if defined(_MSC_VER) + /* Microsoft C/C++-compatible compiler */ + #include + #include + #endif + #if (defined(__GNUC__) || defined(__clang__)) + #include + #endif + #if !defined(__FMA__) + #define __FMA__ 1 + #endif #endif //__AVX__ IMPBFF_BEGIN_NAMESPACE diff --git a/pyext/swig.i-in b/pyext/swig.i-in index 1b12a73..28fd89e 100644 --- a/pyext/swig.i-in +++ b/pyext/swig.i-in @@ -5,20 +5,6 @@ %include "numpy.i" -//%{ -// #include -// void cleanup() -// { -//// printf("cleanup!\n"); -// mongoc_cleanup(); -// } -//%} -//%init %{ -// import_array(); -// mongoc_init(); -// atexit(cleanup); -//%} - %pythoncode %{ import numpy as np %} diff --git a/src/AV.cpp b/src/AV.cpp index 01166ff..17ab639 100644 --- a/src/AV.cpp +++ b/src/AV.cpp @@ -31,17 +31,15 @@ std::string AVPairDistanceMeasurement::get_json(){ double AVPairDistanceMeasurement::score_model(double model){ - auto ev = [](auto f, auto m, auto en, auto ep){ - auto dev = m - f; - auto w = (dev < 0) ? 1. / en : 1. / ep; + auto ev = [](double f, double m, double en, double ep){ + double dev = m - f; + double w = (dev < 0) ? 1. / en : 1. / ep; return .5 * algebra::get_squared(dev * w); }; if(std::isnan(model)){ return std::numeric_limits::infinity(); } - else{ - return 0.5 * ev(model, distance, error_neg, error_pos); - } + return 0.5 * ev(model, distance, error_neg, error_pos); } @@ -114,9 +112,13 @@ IMP::bff::PathMap* AV::get_map() const{ return av_map_; } -IMP::algebra::Vector3D AV::get_mean_position() const{ +IMP::algebra::Vector3D AV::get_mean_position(bool include_source) const{ IMP::algebra::Vector3D r = {0.0, 0.0, 0.0}; - double sum = 0.0; + double sum = 1.0; + if(include_source){ + r += get_source_coordinates(); + sum += 1.0; + } auto xyzd = get_map()->get_xyz_density(); for(auto &a: xyzd){ if(a[3] <= 0.0f) continue; diff --git a/src/AVNetworkRestraint.cpp b/src/AVNetworkRestraint.cpp index fc46f74..0a18594 100644 --- a/src/AVNetworkRestraint.cpp +++ b/src/AVNetworkRestraint.cpp @@ -103,7 +103,7 @@ double AVNetworkRestraint::unprotected_evaluate( distance.position_2, distance.forster_radius, distance.distance_type - ); + ); score += distance.score_model(model); } return score; diff --git a/test/test_AVNetworkRestraint.py b/test/test_AVNetworkRestraint.py index f475371..67b555f 100644 --- a/test/test_AVNetworkRestraint.py +++ b/test/test_AVNetworkRestraint.py @@ -60,8 +60,6 @@ def test_decorate_particle(self): # fps.json files can contain multiple sets of distances for scoring # structures. fps_json_path = IMP.bff.get_example_path("structure/T4L/fret.fps.json") - with open(fps_json_path) as fp: - fps_json = json.load(fp) score_set_c1 = "chi2_C2_33p" fret_restraint = IMP.bff.AVNetworkRestraint( hier, str(fps_json_path), @@ -74,8 +72,8 @@ def test_decorate_particle(self): model_ref = np.array( [ - 49. , 38. , 41.7, 52.6, 38.8, 38.7, 44.3, 52. , 60.3, 50.3, 52.7, - 30. , 49.7, 46. , 46.7, 61.5, 56.2, 51.6, 35.4, 57.2, 53.5, 43.2, + 49.0, 38.0, 41.7, 52.6, 38.8, 38.7, 44.3, 52.0, 60.3, 50.3, 52.7, + 30.0, 49.7, 46.0, 46.7, 61.5, 56.2, 51.6, 35.4, 57.2, 53.5, 43.2, 52.2, 43.4, 47.5, 47.4, 35.3, 37.9, 41.3, 50.8, 45.9, 33.1, 47.4 ] ) diff --git a/test/test_DecayConvolution.py b/test/test_DecayConvolution.py index d5f485a..7dbcf1d 100644 --- a/test/test_DecayConvolution.py +++ b/test/test_DecayConvolution.py @@ -1,16 +1,26 @@ from __future__ import division import unittest -from sys import platform +import platform import numpy as np import numpy.testing -import scipy.stats import IMP.bff x = np.linspace(0, 20, 32) irf_position = 2.0 irf_width = 0.1 -irf_y = scipy.stats.norm.pdf(x, loc=irf_position, scale=irf_width) + + +def norm_pdf(x, mu, sigma): + variance = sigma**2 + num = x - mu + denom = 2*variance + pdf = ((1/(np.sqrt(2*np.pi)*sigma))*np.exp(-(num**2)/denom)) + return pdf + + + +irf_y = norm_pdf(x, irf_position, irf_width) class Tests(unittest.TestCase): @@ -39,7 +49,7 @@ def test_DecayConvolution_init(self): 6.68957600e-02, 5.69312992e-02, 4.84510951e-02, 4.12340602e-02, 3.50920390e-02, 2.98649029e-02, 2.54163750e-02, 2.16304778e-02, 1.84085090e-02, 1.56664688e-02, 1.33328693e-02, 1.13468712e-02]) - self.assertEqual(np.allclose(decay.y, ref), True) + np.testing.assert_allclose(decay.y, ref) ref = np.array([ 0. , 0.64516129, 1.29032258, 1.93548387, 2.58064516, 3.22580645, 3.87096774, 4.51612903, 5.16129032, 5.80645161, 6.4516129 , 7.09677419, 7.74193548, 8.38709677, 9.03225806, @@ -47,7 +57,7 @@ def test_DecayConvolution_init(self): 12.90322581, 13.5483871 , 14.19354839, 14.83870968, 15.48387097, 16.12903226, 16.77419355, 17.41935484, 18.06451613, 18.70967742, 19.35483871, 20. ]) - self.assertEqual(np.allclose(decay.x, ref), True) + np.testing.assert_allclose(decay.x, ref) def test_DecayConvolution_init(self): irf = IMP.bff.DecayCurve(x, irf_y) @@ -80,18 +90,12 @@ def test_DecayConvolution_init(self): IMP.bff.DecayConvolution.FAST_AVX, IMP.bff.DecayConvolution.FAST_PERIODIC_AVX ] - - if platform == "linux" or platform == "linux2": - # linux - conv_methods += conv_methods_fast - elif platform == "win32": - # Windows... - conv_methods += conv_methods_fast - elif platform == "darwin": - # OS X - conv_methods = conv_methods + if "AMD64" in platform.machine(): + if platform.system() == "Linux": + conv_methods += conv_methods_fast + elif platform.system() == "Windows": + conv_methods += conv_methods_fast for i in conv_methods: - print(i) settings["convolution_method"] = i dc = IMP.bff.DecayConvolution(**settings) decay = IMP.bff.DecayCurve(x) diff --git a/test/test_DecayCurve.py b/test/test_DecayCurve.py index 2a2a3de..6e3b877 100644 --- a/test/test_DecayCurve.py +++ b/test/test_DecayCurve.py @@ -3,18 +3,25 @@ import numpy as np import numpy.testing -import scipy.stats import math import IMP.bff +def norm_pdf(x, mu, sigma): + variance = sigma**2 + num = x - mu + denom = 2*variance + pdf = ((1/(np.sqrt(2*np.pi)*sigma))*np.exp(-(num**2)/denom)) + return pdf + + class Tests(unittest.TestCase): def test_shift(self): time_axis = np.linspace(0, 12, 25) irf_position = 6.0 irf_width = 1.0 - irf = scipy.stats.norm.pdf(time_axis, loc=irf_position, scale=irf_width) + irf = norm_pdf(time_axis, irf_position, irf_width) shifts = [2.1, 1.1, 0.5, 0.0, -0.5, -1.1, -2.1, 26.0, -26.2] for shift in shifts: shifted_irf_ip = IMP.bff.DecayCurve.shift_array( diff --git a/test/test_DecayLifetimeHandler.py b/test/test_DecayLifetimeHandler.py index aadc656..c77801a 100644 --- a/test/test_DecayLifetimeHandler.py +++ b/test/test_DecayLifetimeHandler.py @@ -2,7 +2,6 @@ import unittest import numpy as np -import scipy.stats import IMP.bff diff --git a/test/test_DecayLinearization.py b/test/test_DecayLinearization.py index 32af22f..f81f1e9 100644 --- a/test/test_DecayLinearization.py +++ b/test/test_DecayLinearization.py @@ -2,7 +2,6 @@ import unittest import numpy as np -import pandas as pd import IMP.bff @@ -11,14 +10,14 @@ class Tests(unittest.TestCase): def test_lin(self): dt = 0.0141 - df = pd.read_csv( + x, y = np.genfromtxt( IMP.bff.get_example_path("spectroscopy/hgbp1/eTCSPC_whitelight.txt"), - skiprows=6, - sep='\t' - ) - lin_data = IMP.bff.DecayCurve(x=df['Chan'] * dt, y=df['Data']) + skip_header=9, + delimiter='\t' + ).T + lin_data = IMP.bff.DecayCurve(x * dt, y) model = IMP.bff.DecayCurve( - x=df['Chan'] * dt, + x=x * dt, y=np.ones_like(lin_data.y) ) dl = IMP.bff.DecayLinearization( diff --git a/test/test_DecayRoutines.py b/test/test_DecayRoutines.py index 8fa4399..63dcdfc 100644 --- a/test/test_DecayRoutines.py +++ b/test/test_DecayRoutines.py @@ -2,12 +2,19 @@ import unittest import numpy as np -from sys import platform -import scipy.stats +import platform import IMP.bff +def norm_pdf(x, mu, sigma): + variance = sigma**2 + num = x - mu + denom = 2*variance + pdf = ((1/(np.sqrt(2*np.pi)*sigma))*np.exp(-(num**2)/denom)) + return pdf + + def model_irf( n_channels: int = 256, period: float = 32, @@ -16,10 +23,7 @@ def model_irf( irf_width: float = 0.25 ): time_axis = np.linspace(0, period, n_channels * 2) - irf_np = scipy.stats.norm.pdf(time_axis, loc=irf_position_p, - scale=irf_width) + \ - scipy.stats.norm.pdf(time_axis, loc=irf_position_s, - scale=irf_width) + irf_np = norm_pdf(time_axis, irf_position_p, irf_width) + norm_pdf(time_axis, irf_position_s, irf_width) return irf_np, time_axis @@ -142,8 +146,7 @@ def test_fconv(self): np.testing.assert_array_almost_equal(model_ref, model_fconv) - # AVX won't be supported on Apple -> M1 - if platform != "darwin": + if "AMD64" in platform.machine(): model_fconv_avx = np.zeros_like(irf) IMP.bff.decay_fconv_avx( fit=model_fconv_avx, @@ -192,7 +195,7 @@ def test_fconv_per(self): np.testing.assert_array_almost_equal(model_fconv_per, ref) # AVX won't be supported on Apple -> M1 - if platform != "darwin": + if "AMD64" in platform.machine(): model_fconv_avx = np.zeros_like(irf) IMP.bff.decay_fconv_per_avx( fit=model_fconv_avx, @@ -301,7 +304,7 @@ def test_lamp_shift(self): time_axis = np.linspace(4.5, 5.5, 16) irf_position = 5.0 irf_width = 0.25 - irf = scipy.stats.norm.pdf(time_axis, loc=irf_position, scale=irf_width) + irf = norm_pdf(time_axis, irf_position, irf_width) irf_shift = np.empty_like(irf) time_shift = 0.5 IMP.bff.decay_shift_lamp(irf, irf_shift, time_shift)