diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..783078b --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,43 @@ +--- +Checks: >- + bugprone-*, + clang-analyzer-*, + clang-diagnostic-*, + google-*, + modernize-*, + performance-*, + -readability-identifier-naming, + -modernize-use-trailing-return-type +WarningsAsErrors: '' +HeaderFilterRegex: '.*' +#AnalyzeTemporaryDtors: false +FormatStyle: Google +CheckOptions: + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: readability-identifier-naming.ClassCase + value: CamelCase + - key: readability-identifier-naming.FunctionCase + value: camelBack + - key: readability-identifier-naming.GlobalConstantCase + value: UPPER_CASE + - key: readability-identifier-naming.NamespaceCase + value: lower_case + - key: readability-identifier-naming.NamespacePrefix + value: '' + - key: readability-identifier-naming.NamespaceSuffix + value: '' + - key: readability-identifier-naming.StructCase + value: lower_case + - key: readability-identifier-naming.StructPrefix + value: '' + - key: readability-identifier-naming.StructSuffix + value: '_t' + - key: readability-identifier-naming.VariableCase + value: lower_case + - key: readability-identifier-naming.VariablePrefix + value: '' + - key: readability-identifier-naming.VariableSuffix + value: '' +... + diff --git a/.clang-tidy-ignore b/.clang-tidy-ignore new file mode 100644 index 0000000..ea32994 --- /dev/null +++ b/.clang-tidy-ignore @@ -0,0 +1 @@ +3rdparty/**/* diff --git a/3rdparty/packagefiles/armadillo-code/meson.build b/3rdparty/packagefiles/armadillo-code/meson.build index 061ecf5..8800da3 100644 --- a/3rdparty/packagefiles/armadillo-code/meson.build +++ b/3rdparty/packagefiles/armadillo-code/meson.build @@ -1,5 +1,5 @@ project('armadillo', 'cpp', - version: '10.1.x', + version: '14.1.x', ) # Header-only library diff --git a/besselj_armadillo_support/inc/besselj_support.hpp b/besselj_armadillo_support/inc/armadillo_besselj_support.hpp similarity index 98% rename from besselj_armadillo_support/inc/besselj_support.hpp rename to besselj_armadillo_support/inc/armadillo_besselj_support.hpp index daa07ef..c047fc9 100644 --- a/besselj_armadillo_support/inc/besselj_support.hpp +++ b/besselj_armadillo_support/inc/armadillo_besselj_support.hpp @@ -6,6 +6,8 @@ #include #include +#include + namespace arma { // Enable OpenMP multithreading support. diff --git a/besselj_armadillo_support/tests/test-armadillo-support.cpp b/besselj_armadillo_support/tests/test-armadillo-support.cpp index 1e35000..e4e2028 100644 --- a/besselj_armadillo_support/tests/test-armadillo-support.cpp +++ b/besselj_armadillo_support/tests/test-armadillo-support.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include diff --git a/examples/generate-psf.cpp b/examples/generate-psf.cpp index f1c9928..bd79b46 100644 --- a/examples/generate-psf.cpp +++ b/examples/generate-psf.cpp @@ -3,17 +3,27 @@ #include "make_psf.h" int main() { - using microscPSF::makePSF; - using microscPSF::microscope_params_t; - using microscPSF::precision_li2017_t; using arma::hdf5_name; + using microsc_psf::makePSF; + using microsc_psf::microscope_params_t; + using microsc_psf::precision_li2017_t; namespace hdf5_opts = arma::hdf5_opts; using namespace ::units::literals; const auto psf = makePSF(microscope_params_t{}, {0.1_um, 0.25_um}, {120, 63}, 0.530_um, precision_li2017_t{}); #ifdef ARMA_USE_HDF5 + std::cout << "Saving volume to HDF5...\n"; psf.save(hdf5_name("psf.h5", "psf", hdf5_opts::trans)); + std::cout << R"(Done. +Import to Matlab: h5read("psf.h5", "psf"); + +Import to Python: + import h5py + with h5py.File("psf.h5", "r") as h5file: + psf = h5file["psf"][()] + +)"; #endif { @@ -21,12 +31,14 @@ int main() { mat xy_plane = sqrt(psf.slice(32)); xy_plane *= 255 / max(xy_plane.as_col()); xy_plane.save("psf_xy.pgm", pgm_binary); + std::cout << "PSF XY plane saved to 'psf_xy.pgm'.\n"; } { using namespace arma; mat xz_plane = sqrt(psf.col(60)); mat(xz_plane.t() * 255 / max(xz_plane.as_col())).save("psf_xz.pgm", pgm_binary); + std::cout << "PSF XZ plane saved to 'psf_xz.pgm'.\n"; } return 0; } \ No newline at end of file diff --git a/meson.build b/meson.build index d68cab2..132c243 100644 --- a/meson.build +++ b/meson.build @@ -2,7 +2,7 @@ project('MicroscPSF', 'cpp', license: 'MIT', license_files: [ 'LICENSE.txt', - '3rdparty/armadillo-code/LICENSE.txt', + #'3rdparty/armadillo-code/LICENSE.txt', ], subproject_dir: '3rdparty', default_options: [ diff --git a/meson.options b/meson.options new file mode 100644 index 0000000..99e00db --- /dev/null +++ b/meson.options @@ -0,0 +1 @@ +option('install_examples', type: 'boolean', value: false) \ No newline at end of file diff --git a/microsc-psf/inc/make_psf.h b/microsc-psf/inc/make_psf.h index 60dbae2..e61ef6f 100644 --- a/microsc-psf/inc/make_psf.h +++ b/microsc-psf/inc/make_psf.h @@ -4,7 +4,7 @@ #include "units.h" -namespace microscPSF { +namespace microsc_psf { using Micron = ::units::Micrometer; using Meter = ::units::Meter; @@ -25,7 +25,7 @@ struct microscope_params_t { }; /** Solver of linear equations */ -enum linear_solver_option_t { +enum linear_solver_option_t : uint8_t { // Sanderson and Curtin 2020, an adaptive solver for systems of linear equations. // https://arma.sourceforge.net/armadillo_solver_2020.pdf SandersonAndCurtin2020, @@ -35,7 +35,7 @@ enum linear_solver_option_t { }; struct precision_li2017_t { - int over_sampling = 2; //!< Oversample factor + uint32_t over_sampling = 2; //!< Oversample factor uint32_t rho_samples = 1000; uint32_t num_basis = 100; Micron min_wavelength = 0.436_um; @@ -48,6 +48,6 @@ struct pair_t { T z{}; }; -arma::Cube makePSF(microscope_params_t, pair_t voxel, pair_t volume, +arma::Cube makePSF(microscope_params_t, pair_t voxel, pair_t volume, Micron wavelength = 0.530_um, precision_li2017_t = {}); -} // namespace microscPSF \ No newline at end of file +} // namespace microsc_psf \ No newline at end of file diff --git a/microsc-psf/src/main.cpp b/microsc-psf/src/main.cpp index f82c25e..88f2e44 100644 --- a/microsc-psf/src/main.cpp +++ b/microsc-psf/src/main.cpp @@ -3,7 +3,7 @@ #include "make_psf.h" // This must come after header file . -#include +#include namespace { // Return the range [0, N), excluding N. @@ -22,13 +22,14 @@ iota(uint32_t N) { /** Piecewise linear interpolation. */ arma::Cube -cylToRectTransform(const arma::mat& PSF0, const arma::vec& R, microscPSF::pair_t volume) { +cylToRectTransform(const arma::mat& PSF0, const arma::vec& R, + microsc_psf::pair_t volume) { using namespace arma; assert(PSF0.n_cols == uint32_t(volume.z)); vec rPixel; { - const double x0 = (volume.x - 1) / 2; + const double x0 = (volume.x - 1) / 2.0; // meshgrid(0:nx - x0, 0:ny - y0) mat X(volume.x, volume.x); @@ -40,9 +41,9 @@ cylToRectTransform(const arma::mat& PSF0, const arma::vec& R, microscPSF::pair_t Cube PSF(volume.x, volume.x, volume.z); #pragma omp parallel for - for (uint32_t zi = 0; zi < uint32_t(volume.z); zi++) { + for (uint32_t zi = 0; zi < volume.z; zi++) { // Memory map the PSF slice to an 1D vector without memory copy. - vec interpolated{&(PSF(0, 0, zi)), uint32_t(volume.x * volume.x), false, true}; + vec interpolated{&(PSF(0, 0, zi)), static_cast(volume.x) * volume.x, false, true}; interp1(R, PSF0.col(zi), rPixel, interpolated, "linear", 0.0); } @@ -51,16 +52,16 @@ cylToRectTransform(const arma::mat& PSF0, const arma::vec& R, microscPSF::pair_t } } // namespace -namespace microscPSF { +namespace microsc_psf { arma::Cube -makePSF(microscope_params_t params, pair_t voxel, pair_t volume, Micron wavelength, - precision_li2017_t precision) { +makePSF(microscope_params_t params, pair_t voxel, pair_t volume, + Micron wavelength, precision_li2017_t precision) { using ::units::literals::operator""_m; - const double x0 = (volume.x - 1) / 2; + const double x0 = (volume.x - 1) / 2.0; const double y0 = x0; - const double z0 = (volume.z - 1) / 2; + const double z0 = (volume.z - 1) / 2.0; using namespace arma; @@ -108,7 +109,7 @@ makePSF(microscope_params_t params, pair_t voxel, pair_t volume } // Radius coordinates in the PSF RZ plane. - const vec R = iota(precision.over_sampling * max_radius) / precision.over_sampling; + const vec R = iota(static_cast(precision.over_sampling * max_radius)) / precision.over_sampling; // Approximate function exp(j omega) as Bessel series // See equation 5 in Li, Xue, and Blu 2017. @@ -153,12 +154,6 @@ makePSF(microscope_params_t params, pair_t voxel, pair_t volume PSF0 = real(ciEle % conj(ciEle)); } - //{ - // const Mat PSF0_normalized = - // conv_to>::from(PSF0 * 255 / max(max(PSF0))).t(); - // PSF0_normalized.save("psf.pgm", pgm_binary); - //} - auto PSF = cylToRectTransform(PSF0, R, volume); // Normalize the intensity. @@ -167,4 +162,4 @@ makePSF(microscope_params_t params, pair_t voxel, pair_t volume return PSF; } -} // namespace microscPSF \ No newline at end of file +} // namespace microsc_psf \ No newline at end of file