dclab 0.62.6__tar.gz → 0.62.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of dclab might be problematic. Click here for more details.

Files changed (322) hide show
  1. {dclab-0.62.6 → dclab-0.62.8}/CHANGELOG +13 -1
  2. {dclab-0.62.6 → dclab-0.62.8}/PKG-INFO +1 -1
  3. {dclab-0.62.6 → dclab-0.62.8}/dclab/_version.py +2 -2
  4. {dclab-0.62.6 → dclab-0.62.8}/dclab/definitions/meta_const.py +11 -1
  5. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/check.py +15 -4
  6. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/copier.py +64 -19
  7. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/export.py +1 -0
  8. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/feat_basin.py +18 -2
  9. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_hdf5/base.py +7 -2
  10. {dclab-0.62.6 → dclab-0.62.8}/dclab.egg-info/PKG-INFO +1 -1
  11. {dclab-0.62.6 → dclab-0.62.8}/tests/test_cli_condense.py +13 -6
  12. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_check_dataset.py +8 -2
  13. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_copier.py +112 -0
  14. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_feat_anc_plugin.py +6 -13
  15. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_fmt_hdf5_basins_internal.py +105 -0
  16. {dclab-0.62.6 → dclab-0.62.8}/.gitignore +0 -0
  17. {dclab-0.62.6 → dclab-0.62.8}/.readthedocs.yml +0 -0
  18. {dclab-0.62.6 → dclab-0.62.8}/LICENSE +0 -0
  19. {dclab-0.62.6 → dclab-0.62.8}/MANIFEST.in +0 -0
  20. {dclab-0.62.6 → dclab-0.62.8}/README.rst +0 -0
  21. {dclab-0.62.6 → dclab-0.62.8}/dclab/__init__.py +0 -0
  22. {dclab-0.62.6 → dclab-0.62.8}/dclab/cached.py +0 -0
  23. {dclab-0.62.6 → dclab-0.62.8}/dclab/cli/__init__.py +0 -0
  24. {dclab-0.62.6 → dclab-0.62.8}/dclab/cli/common.py +0 -0
  25. {dclab-0.62.6 → dclab-0.62.8}/dclab/cli/task_compress.py +0 -0
  26. {dclab-0.62.6 → dclab-0.62.8}/dclab/cli/task_condense.py +0 -0
  27. {dclab-0.62.6 → dclab-0.62.8}/dclab/cli/task_join.py +0 -0
  28. {dclab-0.62.6 → dclab-0.62.8}/dclab/cli/task_repack.py +0 -0
  29. {dclab-0.62.6 → dclab-0.62.8}/dclab/cli/task_split.py +0 -0
  30. {dclab-0.62.6 → dclab-0.62.8}/dclab/cli/task_tdms2rtdc.py +0 -0
  31. {dclab-0.62.6 → dclab-0.62.8}/dclab/cli/task_verify_dataset.py +0 -0
  32. {dclab-0.62.6 → dclab-0.62.8}/dclab/definitions/__init__.py +0 -0
  33. {dclab-0.62.6 → dclab-0.62.8}/dclab/definitions/feat_const.py +0 -0
  34. {dclab-0.62.6 → dclab-0.62.8}/dclab/definitions/feat_logic.py +0 -0
  35. {dclab-0.62.6 → dclab-0.62.8}/dclab/definitions/meta_logic.py +0 -0
  36. {dclab-0.62.6 → dclab-0.62.8}/dclab/definitions/meta_parse.py +0 -0
  37. {dclab-0.62.6 → dclab-0.62.8}/dclab/downsampling.pyx +0 -0
  38. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/__init__.py +0 -0
  39. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/packaging/LICENSE +0 -0
  40. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/packaging/LICENSE.APACHE +0 -0
  41. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/packaging/LICENSE.BSD +0 -0
  42. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/packaging/__init__.py +0 -0
  43. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/packaging/_structures.py +0 -0
  44. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/packaging/version.py +0 -0
  45. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/skimage/LICENSE +0 -0
  46. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/skimage/__init__.py +0 -0
  47. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/skimage/_find_contours.py +0 -0
  48. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/skimage/_find_contours_cy.pyx +0 -0
  49. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/skimage/_pnpoly.pyx +0 -0
  50. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/skimage/_shared/__init__.py +0 -0
  51. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/skimage/_shared/geometry.pxd +0 -0
  52. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/skimage/_shared/geometry.pyx +0 -0
  53. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/skimage/measure.py +0 -0
  54. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/skimage/pnpoly.py +0 -0
  55. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/statsmodels/LICENSE +0 -0
  56. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/statsmodels/__init__.py +0 -0
  57. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/statsmodels/nonparametric/__init__.py +0 -0
  58. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/statsmodels/nonparametric/_kernel_base.py +0 -0
  59. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/statsmodels/nonparametric/kernel_density.py +0 -0
  60. {dclab-0.62.6 → dclab-0.62.8}/dclab/external/statsmodels/nonparametric/kernels.py +0 -0
  61. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/__init__.py +0 -0
  62. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/bright.py +0 -0
  63. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/bright_bc.py +0 -0
  64. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/bright_perc.py +0 -0
  65. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/contour.py +0 -0
  66. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/emodulus/__init__.py +0 -0
  67. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/emodulus/load.py +0 -0
  68. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/emodulus/lut_HE-2D-FEM-22.txt +0 -0
  69. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/emodulus/lut_HE-3D-FEM-22.txt +0 -0
  70. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/emodulus/lut_LE-2D-FEM-19.txt +0 -0
  71. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/emodulus/pxcorr.py +0 -0
  72. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/emodulus/scale_linear.py +0 -0
  73. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/emodulus/viscosity.py +0 -0
  74. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/fl_crosstalk.py +0 -0
  75. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/inert_ratio.py +0 -0
  76. {dclab-0.62.6 → dclab-0.62.8}/dclab/features/volume.py +0 -0
  77. {dclab-0.62.6 → dclab-0.62.8}/dclab/http_utils.py +0 -0
  78. {dclab-0.62.6 → dclab-0.62.8}/dclab/isoelastics/__init__.py +0 -0
  79. {dclab-0.62.6 → dclab-0.62.8}/dclab/isoelastics/iso_HE-2D-FEM-22-area_um-deform.txt +0 -0
  80. {dclab-0.62.6 → dclab-0.62.8}/dclab/isoelastics/iso_HE-2D-FEM-22-volume-deform.txt +0 -0
  81. {dclab-0.62.6 → dclab-0.62.8}/dclab/isoelastics/iso_HE-3D-FEM-22-area_um-deform.txt +0 -0
  82. {dclab-0.62.6 → dclab-0.62.8}/dclab/isoelastics/iso_HE-3D-FEM-22-volume-deform.txt +0 -0
  83. {dclab-0.62.6 → dclab-0.62.8}/dclab/isoelastics/iso_LE-2D-FEM-19-area_um-deform.txt +0 -0
  84. {dclab-0.62.6 → dclab-0.62.8}/dclab/isoelastics/iso_LE-2D-FEM-19-volume-deform.txt +0 -0
  85. {dclab-0.62.6 → dclab-0.62.8}/dclab/isoelastics/iso_LE-2D-ana-18-area_um-deform.txt +0 -0
  86. {dclab-0.62.6 → dclab-0.62.8}/dclab/kde_contours.py +0 -0
  87. {dclab-0.62.6 → dclab-0.62.8}/dclab/kde_methods.py +0 -0
  88. {dclab-0.62.6 → dclab-0.62.8}/dclab/lme4/__init__.py +0 -0
  89. {dclab-0.62.6 → dclab-0.62.8}/dclab/lme4/lme4_template.R +0 -0
  90. {dclab-0.62.6 → dclab-0.62.8}/dclab/lme4/rsetup.py +0 -0
  91. {dclab-0.62.6 → dclab-0.62.8}/dclab/lme4/wrapr.py +0 -0
  92. {dclab-0.62.6 → dclab-0.62.8}/dclab/polygon_filter.py +0 -0
  93. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/__init__.py +0 -0
  94. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/config.py +0 -0
  95. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/core.py +0 -0
  96. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/feat_anc_core/__init__.py +0 -0
  97. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/feat_anc_core/af_basic.py +0 -0
  98. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/feat_anc_core/af_emodulus.py +0 -0
  99. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/feat_anc_core/af_fl_max_ctc.py +0 -0
  100. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/feat_anc_core/af_image_contour.py +0 -0
  101. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/feat_anc_core/af_ml_class.py +0 -0
  102. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/feat_anc_core/ancillary_feature.py +0 -0
  103. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/feat_anc_ml/__init__.py +0 -0
  104. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/feat_anc_plugin/__init__.py +0 -0
  105. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/feat_anc_plugin/plugin_feature.py +0 -0
  106. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/feat_temp.py +0 -0
  107. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/filter.py +0 -0
  108. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_dcor/__init__.py +0 -0
  109. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_dcor/access_token.py +0 -0
  110. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_dcor/api.py +0 -0
  111. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_dcor/base.py +0 -0
  112. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_dcor/basin.py +0 -0
  113. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_dcor/logs.py +0 -0
  114. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_dcor/tables.py +0 -0
  115. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_dict.py +0 -0
  116. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_hdf5/__init__.py +0 -0
  117. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_hdf5/basin.py +0 -0
  118. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_hdf5/events.py +0 -0
  119. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_hdf5/feat_defect.py +0 -0
  120. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_hdf5/logs.py +0 -0
  121. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_hdf5/tables.py +0 -0
  122. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_hierarchy/__init__.py +0 -0
  123. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_hierarchy/base.py +0 -0
  124. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_hierarchy/events.py +0 -0
  125. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_hierarchy/hfilter.py +0 -0
  126. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_hierarchy/mapper.py +0 -0
  127. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_http.py +0 -0
  128. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_s3.py +0 -0
  129. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_tdms/__init__.py +0 -0
  130. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_tdms/event_contour.py +0 -0
  131. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_tdms/event_image.py +0 -0
  132. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_tdms/event_mask.py +0 -0
  133. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_tdms/event_trace.py +0 -0
  134. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_tdms/exc.py +0 -0
  135. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/fmt_tdms/naming.py +0 -0
  136. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/load.py +0 -0
  137. {dclab-0.62.6 → dclab-0.62.8}/dclab/rtdc_dataset/writer.py +0 -0
  138. {dclab-0.62.6 → dclab-0.62.8}/dclab/statistics.py +0 -0
  139. {dclab-0.62.6 → dclab-0.62.8}/dclab/util.py +0 -0
  140. {dclab-0.62.6 → dclab-0.62.8}/dclab/warn.py +0 -0
  141. {dclab-0.62.6 → dclab-0.62.8}/dclab.egg-info/SOURCES.txt +0 -0
  142. {dclab-0.62.6 → dclab-0.62.8}/dclab.egg-info/dependency_links.txt +0 -0
  143. {dclab-0.62.6 → dclab-0.62.8}/dclab.egg-info/entry_points.txt +0 -0
  144. {dclab-0.62.6 → dclab-0.62.8}/dclab.egg-info/requires.txt +0 -0
  145. {dclab-0.62.6 → dclab-0.62.8}/dclab.egg-info/top_level.txt +0 -0
  146. {dclab-0.62.6 → dclab-0.62.8}/docs/.gitignore +0 -0
  147. {dclab-0.62.6 → dclab-0.62.8}/docs/README.md +0 -0
  148. {dclab-0.62.6 → dclab-0.62.8}/docs/conf.py +0 -0
  149. {dclab-0.62.6 → dclab-0.62.8}/docs/data/example.poly +0 -0
  150. {dclab-0.62.6 → dclab-0.62.8}/docs/data/example.rtdc +0 -0
  151. {dclab-0.62.6 → dclab-0.62.8}/docs/data/example_plugin.py +0 -0
  152. {dclab-0.62.6 → dclab-0.62.8}/docs/data/example_plugin_metadata.py +0 -0
  153. {dclab-0.62.6 → dclab-0.62.8}/docs/data/example_traces.rtdc +0 -0
  154. {dclab-0.62.6 → dclab-0.62.8}/docs/data/example_video.rtdc +0 -0
  155. {dclab-0.62.6 → dclab-0.62.8}/docs/dclab.bib +0 -0
  156. {dclab-0.62.6 → dclab-0.62.8}/docs/extensions/dclab_defs.py +0 -0
  157. {dclab-0.62.6 → dclab-0.62.8}/docs/extensions/fancy_include.py +0 -0
  158. {dclab-0.62.6 → dclab-0.62.8}/docs/extensions/github_changelog.py +0 -0
  159. {dclab-0.62.6 → dclab-0.62.8}/docs/extensions/simple_argparse.py +0 -0
  160. {dclab-0.62.6 → dclab-0.62.8}/docs/figures/DCOR_API_Token_website.png +0 -0
  161. {dclab-0.62.6 → dclab-0.62.8}/docs/index.rst +0 -0
  162. {dclab-0.62.6 → dclab-0.62.8}/docs/logo/dc_logo.png +0 -0
  163. {dclab-0.62.6 → dclab-0.62.8}/docs/logo/dc_logo.svg +0 -0
  164. {dclab-0.62.6 → dclab-0.62.8}/docs/logo/dclab.png +0 -0
  165. {dclab-0.62.6 → dclab-0.62.8}/docs/logo/dclab.svg +0 -0
  166. {dclab-0.62.6 → dclab-0.62.8}/docs/logo/dclab_large_white.png +0 -0
  167. {dclab-0.62.6 → dclab-0.62.8}/docs/logo/dclab_large_white.svg +0 -0
  168. {dclab-0.62.6 → dclab-0.62.8}/docs/logo/favicon.ico +0 -0
  169. {dclab-0.62.6 → dclab-0.62.8}/docs/logo/favicon.svg +0 -0
  170. {dclab-0.62.6 → dclab-0.62.8}/docs/requirements.txt +0 -0
  171. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_advanced_usage.rst +0 -0
  172. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_basins/index.rst +0 -0
  173. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_dc_io.rst +0 -0
  174. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_dc_usage.rst +0 -0
  175. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_dcor.rst +0 -0
  176. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_emodulus/figures_emodulus/.gitignore +0 -0
  177. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_emodulus/figures_emodulus/emodulus_20um_HE-2D-FEM-22.png +0 -0
  178. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_emodulus/figures_emodulus/emodulus_20um_HE-3D-FEM-22.png +0 -0
  179. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_emodulus/figures_emodulus/emodulus_20um_LE-2D-FEM-19.png +0 -0
  180. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_emodulus/figures_emodulus/plot_emodulus_lut.py +0 -0
  181. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_emodulus/figures_emodulus/requirements.txt +0 -0
  182. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_emodulus/figures_viscosity/LICENSE +0 -0
  183. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_emodulus/figures_viscosity/buyukurganci_22_fig3a.jpg +0 -0
  184. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_emodulus/figures_viscosity/buyukurganci_22_fig3a.pdf +0 -0
  185. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_emodulus/index.rst +0 -0
  186. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_feat_plugin.rst +0 -0
  187. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_feat_temp.rst +0 -0
  188. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_fluorescence.rst +0 -0
  189. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_lme4.rst +0 -0
  190. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_notation.rst +0 -0
  191. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_s3.rst +0 -0
  192. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_av_scatter.rst +0 -0
  193. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_changelog.rst +0 -0
  194. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_cli.rst +0 -0
  195. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_code_reference.rst +0 -0
  196. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_examples.rst +0 -0
  197. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_getting_started.rst +0 -0
  198. {dclab-0.62.6 → dclab-0.62.8}/docs/sec_z_bib.rst +0 -0
  199. {dclab-0.62.6 → dclab-0.62.8}/examples/emodulus_dcor.jpg +0 -0
  200. {dclab-0.62.6 → dclab-0.62.8}/examples/emodulus_dcor.py +0 -0
  201. {dclab-0.62.6 → dclab-0.62.8}/examples/generate_example_images.py +0 -0
  202. {dclab-0.62.6 → dclab-0.62.8}/examples/isoelastics.jpg +0 -0
  203. {dclab-0.62.6 → dclab-0.62.8}/examples/isoelastics.py +0 -0
  204. {dclab-0.62.6 → dclab-0.62.8}/examples/isoelastics_custom.jpg +0 -0
  205. {dclab-0.62.6 → dclab-0.62.8}/examples/isoelastics_custom.py +0 -0
  206. {dclab-0.62.6 → dclab-0.62.8}/examples/lme4_glmer_diff.py +0 -0
  207. {dclab-0.62.6 → dclab-0.62.8}/examples/lme4_lmer.jpg +0 -0
  208. {dclab-0.62.6 → dclab-0.62.8}/examples/lme4_lmer.py +0 -0
  209. {dclab-0.62.6 → dclab-0.62.8}/examples/overview_plot.jpg +0 -0
  210. {dclab-0.62.6 → dclab-0.62.8}/examples/overview_plot.py +0 -0
  211. {dclab-0.62.6 → dclab-0.62.8}/examples/plugin_example.py +0 -0
  212. {dclab-0.62.6 → dclab-0.62.8}/examples/plugin_usage.jpg +0 -0
  213. {dclab-0.62.6 → dclab-0.62.8}/examples/plugin_usage.py +0 -0
  214. {dclab-0.62.6 → dclab-0.62.8}/examples/viscosity_models.jpg +0 -0
  215. {dclab-0.62.6 → dclab-0.62.8}/examples/viscosity_models.py +0 -0
  216. {dclab-0.62.6 → dclab-0.62.8}/pyproject.toml +0 -0
  217. {dclab-0.62.6 → dclab-0.62.8}/scripts/.gitignore +0 -0
  218. {dclab-0.62.6 → dclab-0.62.8}/scripts/README.md +0 -0
  219. {dclab-0.62.6 → dclab-0.62.8}/scripts/fem2iso_volume.py +0 -0
  220. {dclab-0.62.6 → dclab-0.62.8}/scripts/fem2lutiso_std.py +0 -0
  221. {dclab-0.62.6 → dclab-0.62.8}/scripts/fem2rtdc.py +0 -0
  222. {dclab-0.62.6 → dclab-0.62.8}/scripts/lut_recipes/__init__.py +0 -0
  223. {dclab-0.62.6 → dclab-0.62.8}/scripts/lut_recipes/hooks/LUT_analytical_linear-elastic_2Daxis.txt +0 -0
  224. {dclab-0.62.6 → dclab-0.62.8}/scripts/lut_recipes/hooks/README.md +0 -0
  225. {dclab-0.62.6 → dclab-0.62.8}/scripts/lut_recipes/hooks/__init__.py +0 -0
  226. {dclab-0.62.6 → dclab-0.62.8}/scripts/lut_recipes/hooks/common.py +0 -0
  227. {dclab-0.62.6 → dclab-0.62.8}/scripts/lut_recipes/hooks/he_2d_fem_22.py +0 -0
  228. {dclab-0.62.6 → dclab-0.62.8}/scripts/lut_recipes/hooks/he_3d_fem_22.py +0 -0
  229. {dclab-0.62.6 → dclab-0.62.8}/scripts/lut_recipes/hooks/le_2d_fem_19.py +0 -0
  230. {dclab-0.62.6 → dclab-0.62.8}/scripts/lut_recipes/lut_processor.py +0 -0
  231. {dclab-0.62.6 → dclab-0.62.8}/scripts/pixelation_correction.py +0 -0
  232. {dclab-0.62.6 → dclab-0.62.8}/scripts/pixelation_correction_2020.png +0 -0
  233. {dclab-0.62.6 → dclab-0.62.8}/scripts/pixelation_correction_2022.png +0 -0
  234. {dclab-0.62.6 → dclab-0.62.8}/scripts/requirements.txt +0 -0
  235. {dclab-0.62.6 → dclab-0.62.8}/setup.cfg +0 -0
  236. {dclab-0.62.6 → dclab-0.62.8}/setup.py +0 -0
  237. {dclab-0.62.6 → dclab-0.62.8}/tests/README.md +0 -0
  238. {dclab-0.62.6 → dclab-0.62.8}/tests/conftest.py +0 -0
  239. {dclab-0.62.6 → dclab-0.62.8}/tests/data/README.md +0 -0
  240. {dclab-0.62.6 → dclab-0.62.8}/tests/data/example_access_token.dcor-access +0 -0
  241. {dclab-0.62.6 → dclab-0.62.8}/tests/data/example_isoelastics.txt +0 -0
  242. {dclab-0.62.6 → dclab-0.62.8}/tests/data/feat_anc_plugin_creative.py +0 -0
  243. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-hdf5_fl-no-contour_2019.zip +0 -0
  244. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-hdf5_fl_2017.zip +0 -0
  245. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-hdf5_fl_2018.zip +0 -0
  246. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-hdf5_fl_wide-channel_2023.zip +0 -0
  247. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-hdf5_image-bg_2020.zip +0 -0
  248. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-hdf5_image-mask-blood_2021.zip +0 -0
  249. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-hdf5_mask-contour_2018.zip +0 -0
  250. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-hdf5_polygon_gate_2021.zip +0 -0
  251. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-hdf5_raw-cytoshot-exported.zip +0 -0
  252. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-hdf5_segfault-compound_2023.zip +0 -0
  253. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-hdf5_wide-channel_2023.zip +0 -0
  254. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-tdms_2fl-no-image_2017.zip +0 -0
  255. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-tdms_fl-image-bright_2017.zip +0 -0
  256. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-tdms_fl-image-large-fov_2017.zip +0 -0
  257. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-tdms_fl-image_2016.zip +0 -0
  258. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-tdms_fl_2015.zip +0 -0
  259. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-tdms_minimal_2016.zip +0 -0
  260. {dclab-0.62.6 → dclab-0.62.8}/tests/data/fmt-tdms_shapein-2.0.1-no-image_2017.zip +0 -0
  261. {dclab-0.62.6 → dclab-0.62.8}/tests/helper_methods.py +0 -0
  262. {dclab-0.62.6 → dclab-0.62.8}/tests/requirements.txt +0 -0
  263. {dclab-0.62.6 → dclab-0.62.8}/tests/test_cache.py +0 -0
  264. {dclab-0.62.6 → dclab-0.62.8}/tests/test_cli.py +0 -0
  265. {dclab-0.62.6 → dclab-0.62.8}/tests/test_cli_argparse.py +0 -0
  266. {dclab-0.62.6 → dclab-0.62.8}/tests/test_cli_compress.py +0 -0
  267. {dclab-0.62.6 → dclab-0.62.8}/tests/test_cli_join.py +0 -0
  268. {dclab-0.62.6 → dclab-0.62.8}/tests/test_cli_repack.py +0 -0
  269. {dclab-0.62.6 → dclab-0.62.8}/tests/test_cli_split.py +0 -0
  270. {dclab-0.62.6 → dclab-0.62.8}/tests/test_config_value_mapping.py +0 -0
  271. {dclab-0.62.6 → dclab-0.62.8}/tests/test_dfn.py +0 -0
  272. {dclab-0.62.6 → dclab-0.62.8}/tests/test_downsampling.py +0 -0
  273. {dclab-0.62.6 → dclab-0.62.8}/tests/test_feat_bright.py +0 -0
  274. {dclab-0.62.6 → dclab-0.62.8}/tests/test_feat_bright_bc.py +0 -0
  275. {dclab-0.62.6 → dclab-0.62.8}/tests/test_feat_bright_perc.py +0 -0
  276. {dclab-0.62.6 → dclab-0.62.8}/tests/test_feat_contour.py +0 -0
  277. {dclab-0.62.6 → dclab-0.62.8}/tests/test_feat_emodulus.py +0 -0
  278. {dclab-0.62.6 → dclab-0.62.8}/tests/test_feat_emodulus_viscosity.py +0 -0
  279. {dclab-0.62.6 → dclab-0.62.8}/tests/test_feat_fl_crosstalk.py +0 -0
  280. {dclab-0.62.6 → dclab-0.62.8}/tests/test_feat_inert_ratio.py +0 -0
  281. {dclab-0.62.6 → dclab-0.62.8}/tests/test_feat_volume.py +0 -0
  282. {dclab-0.62.6 → dclab-0.62.8}/tests/test_http_utils.py +0 -0
  283. {dclab-0.62.6 → dclab-0.62.8}/tests/test_isoelastics.py +0 -0
  284. {dclab-0.62.6 → dclab-0.62.8}/tests/test_kde_contours.py +0 -0
  285. {dclab-0.62.6 → dclab-0.62.8}/tests/test_kde_methods.py +0 -0
  286. {dclab-0.62.6 → dclab-0.62.8}/tests/test_lme4.py +0 -0
  287. {dclab-0.62.6 → dclab-0.62.8}/tests/test_lut_he_2d_fem_22.py +0 -0
  288. {dclab-0.62.6 → dclab-0.62.8}/tests/test_lut_he_3d_fem_22.py +0 -0
  289. {dclab-0.62.6 → dclab-0.62.8}/tests/test_polygon_contains.py +0 -0
  290. {dclab-0.62.6 → dclab-0.62.8}/tests/test_polygon_filter.py +0 -0
  291. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_config.py +0 -0
  292. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_core_feat.py +0 -0
  293. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_downsampling.py +0 -0
  294. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_export.py +0 -0
  295. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_export_avi.py +0 -0
  296. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_export_fcs.py +0 -0
  297. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_export_hdf5.py +0 -0
  298. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_export_tsv.py +0 -0
  299. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_feat_anc_core.py +0 -0
  300. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_feat_anc_ml.py +0 -0
  301. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_feat_basin.py +0 -0
  302. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_feat_basin_mapped.py +0 -0
  303. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_feat_temp.py +0 -0
  304. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_filter.py +0 -0
  305. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_fmt_dcor.py +0 -0
  306. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_fmt_dcor_access_token.py +0 -0
  307. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_fmt_dcor_basin.py +0 -0
  308. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_fmt_dict.py +0 -0
  309. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_fmt_hdf5.py +0 -0
  310. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_fmt_hdf5_basins.py +0 -0
  311. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_fmt_hierarchy.py +0 -0
  312. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_fmt_http.py +0 -0
  313. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_fmt_http_basin.py +0 -0
  314. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_fmt_s3.py +0 -0
  315. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_fmt_s3_basin.py +0 -0
  316. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_fmt_tdms.py +0 -0
  317. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_hash.py +0 -0
  318. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_kde.py +0 -0
  319. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_limit_events.py +0 -0
  320. {dclab-0.62.6 → dclab-0.62.8}/tests/test_rtdc_writer.py +0 -0
  321. {dclab-0.62.6 → dclab-0.62.8}/tests/test_statistics.py +0 -0
  322. {dclab-0.62.6 → dclab-0.62.8}/tests/test_util.py +0 -0
@@ -1,3 +1,14 @@
1
+ 0.62.8
2
+ - fix: metadata of tables not copied by `copier.py`
3
+ - docs: formatting typo (#270)
4
+ 0.62.7
5
+ - fix: IntegrityChecker must not load basins
6
+ - fix: KeyError in IntegrityChecker when "basin_events" group missing (#268)
7
+ - fix: warn user about missing internal basin features while still loading
8
+ those that are available (#268)
9
+ - fix: do not copy internal basin definitions for non-existent features (#269)
10
+ - docs: clarify interpretation of [qpi]: "filter size" metadata (#267)
11
+ - tests: avoid architecture and Python-version dependent test
1
12
  0.62.6
2
13
  - enh: support passing pathlib.Path to lme4.rsetup.set_*_path methods
3
14
  - docs: correct keyword arguments for advanced section on S3
@@ -17,7 +28,8 @@
17
28
  0.62.0
18
29
  - BREAKING: removed the `rtdc_dataset.linker` module, because it is not
19
30
  used by any other piece of software and because combining file-like
20
- objects external links are quirky and their combination finally broke with h5py 3.12
31
+ objects external links are quirky and their combination finally broke
32
+ with h5py 3.12
21
33
  - enh: added integrity check for external links
22
34
  - tests: reduce warnings
23
35
  0.61.5
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dclab
3
- Version: 0.62.6
3
+ Version: 0.62.8
4
4
  Summary: Library for real-time deformability cytometry (RT-DC)
5
5
  Author: Benedikt Hartmann, Eoghan O'Connell, Maik Herbig, Maximilian Schlögel, Nadia Sbaa, Paul Müller, Philipp Rosendahl, Raghava Alajangi
6
6
  Maintainer-email: Paul Müller <dev@craban.de>
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.62.6'
16
- __version_tuple__ = version_tuple = (0, 62, 6)
15
+ __version__ = version = '0.62.8'
16
+ __version_tuple__ = version_tuple = (0, 62, 8)
@@ -161,7 +161,17 @@ CFG_METADATA = {
161
161
  ["subtract mean", fbool, "Subtract mean before processing"],
162
162
  # pipeline_kws
163
163
  ["filter name", str, "Fourier filter used"],
164
- # Corresponds to `filter_size_interpretation="frequency index"`
164
+ # qpretrieve defines the keyword argument `filter_size_interpretation`
165
+ # for determining the filter size in Fourier space. In DC, we
166
+ # need a well-defined value for the filter size. The most logical
167
+ # choice is to interpret the filter size as "frequency index", which
168
+ # is independent of the image shape and yields a good approximation
169
+ # of the actual resolution one can expect. The default value
170
+ # ("sideband distance") is a good choice for general QPI analysis,
171
+ # but there is no meaningful information one could extract from it
172
+ # by just looking at the number. Thus, the "filter size" that we
173
+ # see here corresponds to a filter size set in qpretrieve where
174
+ # `filter_size_interpretation="frequency index"`.
165
175
  ["filter size", float, "Fourier filter size [1/pix]"],
166
176
  ["scale to filter", fboolorfloat, "Scale QPI data to filter size"],
167
177
  # x, y coordinates, don't set if you wish None to be the default
@@ -193,7 +193,7 @@ class IntegrityChecker(object):
193
193
  else:
194
194
  with warnings.catch_warnings(record=True) as ws:
195
195
  warnings.simplefilter("always")
196
- self.ds = load_file(path_or_ds)
196
+ self.ds = load_file(path_or_ds, enable_basins=False)
197
197
  for ww in ws:
198
198
  self.warn_cues.append(ICue(
199
199
  msg=f"{ww.category.__name__}: {ww.message}",
@@ -260,13 +260,24 @@ class IntegrityChecker(object):
260
260
  level="alert",
261
261
  category="basin data",
262
262
  ))
263
- for feat in bn["features"]:
264
- if feat not in self.ds.h5file[bpaths[0]]:
263
+ else:
264
+ if "basin_events" not in self.ds.h5file:
265
265
  cues.append(
266
- ICue(msg=f"Missing internal basin feature {feat}",
266
+ ICue(msg="Missing internal basin group "
267
+ "'basin_events', although an internal "
268
+ "basin is defined",
267
269
  level="violation",
268
270
  category="basin data",
269
271
  ))
272
+ else:
273
+ for feat in bn["features"]:
274
+ if feat not in self.ds.h5file["basin_events"]:
275
+ cues.append(
276
+ ICue(msg=f"Missing internal basin "
277
+ f"feature {feat}",
278
+ level="violation",
279
+ category="basin data",
280
+ ))
270
281
  return cues
271
282
 
272
283
  def check_compression(self, **kwargs):
@@ -1,6 +1,7 @@
1
1
  """Helper methods for copying .rtdc data"""
2
2
  from __future__ import annotations
3
3
 
4
+ import json
4
5
  import re
5
6
  from typing import List, Literal
6
7
 
@@ -10,8 +11,10 @@ import hdf5plugin
10
11
  import numpy as np
11
12
 
12
13
  from ..definitions import feature_exists, scalar_feature_exists
14
+ from ..util import hashobj
13
15
 
14
- from .fmt_hdf5 import DEFECTIVE_FEATURES
16
+ from .fmt_hdf5 import DEFECTIVE_FEATURES, RTDC_HDF5
17
+ from .writer import RTDCWriter
15
18
 
16
19
 
17
20
  def rtdc_copy(src_h5file: h5py.Group,
@@ -44,8 +47,7 @@ def rtdc_copy(src_h5file: h5py.Group,
44
47
  Add this prefix to the name of the logs and tables in `dst_h5file`.
45
48
  """
46
49
  # metadata
47
- for akey in src_h5file.attrs:
48
- dst_h5file.attrs[akey] = src_h5file.attrs[akey]
50
+ dst_h5file.attrs.update(src_h5file.attrs)
49
51
 
50
52
  # events in source file
51
53
  if "events" in src_h5file:
@@ -57,19 +59,6 @@ def rtdc_copy(src_h5file: h5py.Group,
57
59
  events_src += list(src_h5file["basin_events"].keys())
58
60
  events_src = sorted(set(events_src))
59
61
 
60
- # basins
61
- if include_basins and "basins" in src_h5file:
62
- dst_h5file.require_group("basins")
63
- for b_key in src_h5file["basins"]:
64
- if b_key in dst_h5file["basins"]:
65
- # This basin already exists.
66
- continue
67
- h5ds_copy(src_loc=src_h5file["basins"],
68
- src_name=b_key,
69
- dst_loc=dst_h5file["basins"],
70
- dst_name=b_key,
71
- recursive=False)
72
-
73
62
  # logs
74
63
  if include_logs and "logs" in src_h5file:
75
64
  dst_h5file.require_group("logs")
@@ -94,11 +83,12 @@ def rtdc_copy(src_h5file: h5py.Group,
94
83
  # dst_loc=dst_h5file["tables"],
95
84
  # dst_name=meta_prefix + tkey,
96
85
  # recursive=False)
97
- dst_h5file["tables"].create_dataset(
86
+ copy_table = dst_h5file["tables"].create_dataset(
98
87
  name=tkey,
99
88
  data=src_h5file["tables"][tkey][:],
100
89
  fletcher32=True,
101
90
  **hdf5plugin.Zstd(clevel=5))
91
+ copy_table.attrs.update(src_h5file["tables"][tkey].attrs)
102
92
 
103
93
  # events
104
94
  if isinstance(features, list):
@@ -130,6 +120,12 @@ def rtdc_copy(src_h5file: h5py.Group,
130
120
  if feat in feature_iter:
131
121
  feature_iter.remove(feat)
132
122
 
123
+ # copy basin definitions
124
+ if include_basins and "basins" in src_h5file:
125
+ basin_definition_copy(src_h5file=src_h5file,
126
+ dst_h5file=dst_h5file,
127
+ features_iter=feature_iter)
128
+
133
129
  if feature_iter:
134
130
  dst_h5file.require_group("events")
135
131
  for feat in feature_iter:
@@ -170,6 +166,56 @@ def rtdc_copy(src_h5file: h5py.Group,
170
166
  )
171
167
 
172
168
 
169
+ def basin_definition_copy(src_h5file, dst_h5file, features_iter):
170
+ """Copy basin definitions `src_h5file["basins"]` to the new file
171
+
172
+ Normally, we would just use :func:`h5ds_copy` to copy basins from
173
+ one dataset to another. However, if we are e.g. only copying scalar
174
+ features, and there are non-scalar features in the internal basin,
175
+ then we must rewrite the basin definition of the internal basin.
176
+
177
+ The `features_iter` list of features defines which features are
178
+ relevant for the internal basin.
179
+ """
180
+ dst_h5file.require_group("basins")
181
+ for b_key in src_h5file["basins"]:
182
+ if b_key in dst_h5file["basins"]:
183
+ # This basin already exists.
184
+ continue
185
+ # Load the basin information
186
+ basin_dicts = RTDC_HDF5.basin_get_dicts_from_h5file(src_h5file)
187
+ for bn in basin_dicts:
188
+ if bn["type"] == "internal":
189
+ # Make sure we define the internal features selected
190
+ feat_used = [f for f in bn["features"] if f in features_iter]
191
+ if len(feat_used) == 0:
192
+ # We don't have any internal features, don't write anything
193
+ continue
194
+ elif feat_used != bn["features"]:
195
+ bn["features"] = feat_used
196
+ rewrite = True
197
+ else:
198
+ rewrite = False
199
+ else:
200
+ # We do not have an internal basin, just copy everything
201
+ rewrite = False
202
+
203
+ if rewrite:
204
+ # Convert edited `bn` to JSON and write feature data
205
+ b_lines = json.dumps(bn, indent=2).split("\n")
206
+ key = hashobj(b_lines)
207
+ if key not in dst_h5file["basins"]:
208
+ with RTDCWriter(dst_h5file) as hw:
209
+ hw.write_text(dst_h5file["basins"], key, b_lines)
210
+ else:
211
+ # copy only
212
+ h5ds_copy(src_loc=src_h5file["basins"],
213
+ src_name=b_key,
214
+ dst_loc=dst_h5file["basins"],
215
+ dst_name=b_key,
216
+ recursive=False)
217
+
218
+
173
219
  def h5ds_copy(src_loc, src_name, dst_loc, dst_name=None,
174
220
  ensure_compression=True, recursive=True):
175
221
  """Copy an HDF5 Dataset from one group to another
@@ -257,8 +303,7 @@ def h5ds_copy(src_loc, src_name, dst_loc, dst_name=None,
257
303
  for chunk in src.iter_chunks():
258
304
  dst[chunk] = src[chunk]
259
305
  # Also write all the attributes
260
- for key in src.attrs:
261
- dst.attrs[key] = src.attrs[key]
306
+ dst.attrs.update(src.attrs)
262
307
  else:
263
308
  # Copy the Dataset to the destination as-is.
264
309
  h5py.h5o.copy(src_loc=src_loc.id,
@@ -224,6 +224,7 @@ class Export(object):
224
224
  skip_checks: bool
225
225
  Disable checking whether all features have the same length.
226
226
 
227
+
227
228
  .. versionchanged:: 0.58.0
228
229
 
229
230
  The ``basins`` keyword argument was added, and it is now possible
@@ -17,6 +17,10 @@ import numpy as np
17
17
  from ..util import copy_if_needed
18
18
 
19
19
 
20
+ class BasinFeatureMissingWarning(UserWarning):
21
+ """Used when a badin feature is defined but not stored"""
22
+
23
+
20
24
  class CyclicBasinDependencyFoundWarning(UserWarning):
21
25
  """Used when a basin is defined in one of its sub-basins"""
22
26
 
@@ -498,6 +502,19 @@ class InternalH5DatasetBasin(Basin):
498
502
  if self._features is None:
499
503
  raise ValueError("You must specify features when defining "
500
504
  "internal basins.")
505
+ # Redefine the features if necessary
506
+ h5root = self._basinmap_referrer().h5file
507
+ available_features = []
508
+ for feat in self._features:
509
+ if self.location in h5root and feat in h5root[self.location]:
510
+ available_features.append(feat)
511
+ else:
512
+ warnings.warn(
513
+ f"Feature '{feat}' is defined as an internal basin, "
514
+ f"but it cannot be found in '{self.location}'.",
515
+ BasinFeatureMissingWarning)
516
+ self._features.clear()
517
+ self._features += available_features
501
518
 
502
519
  def _load_dataset(self, location, **kwargs):
503
520
  from .fmt_dict import RTDC_Dict
@@ -509,8 +526,7 @@ class InternalH5DatasetBasin(Basin):
509
526
  return RTDC_Dict(ds_dict)
510
527
 
511
528
  def is_available(self):
512
- h5root = self._basinmap_referrer().h5file
513
- return self.location in h5root
529
+ return bool(self._features)
514
530
 
515
531
  def verify_basin(self, *args, **kwargs):
516
532
  """It's not necessary to verify internal basins"""
@@ -175,10 +175,15 @@ class RTDC_HDF5(RTDCBase):
175
175
 
176
176
  def basins_get_dicts(self):
177
177
  """Return list of dicts for all basins defined in `self.h5file`"""
178
+ return self.basin_get_dicts_from_h5file(self.h5file)
179
+
180
+ @staticmethod
181
+ def basin_get_dicts_from_h5file(h5file):
182
+ """Return list of dicts for all basins defined in `h5file`"""
178
183
  basins = []
179
184
  # Do not sort anything here, sorting is done in `RTDCBase`.
180
- for bk in self.h5file.get("basins", []):
181
- bdat = list(self.h5file["basins"][bk])
185
+ for bk in h5file.get("basins", []):
186
+ bdat = list(h5file["basins"][bk])
182
187
  if isinstance(bdat[0], bytes):
183
188
  bdat = [bi.decode("utf") for bi in bdat]
184
189
  bdict = json.loads(" ".join(bdat))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dclab
3
- Version: 0.62.6
3
+ Version: 0.62.8
4
4
  Summary: Library for real-time deformability cytometry (RT-DC)
5
5
  Author: Benedikt Hartmann, Eoghan O'Connell, Maik Herbig, Maximilian Schlögel, Nadia Sbaa, Paul Müller, Philipp Rosendahl, Raghava Alajangi
6
6
  Maintainer-email: Paul Müller <dev@craban.de>
@@ -134,10 +134,12 @@ def test_condense_basins_include_no_data_from_basins():
134
134
  @pytest.mark.parametrize("store_basins", [True, False])
135
135
  def test_condense_basins_internal(store_basins):
136
136
  """
137
- Internal basins should just be copied to the new file
137
+ Internal basins should just be copied to the new file.
138
+ However, image data are not scalar data, so they should not
139
+ show up in the condensed file.
138
140
  """
139
141
  h5path = retrieve_data("fmt-hdf5_fl_wide-channel_2023.zip")
140
- h5path_small = h5path.with_name("smaller.rtdc")
142
+ h5path_small = h5path.with_name("input_file.rtdc")
141
143
  h5path_out = h5path.with_name("condensed.rtdc")
142
144
 
143
145
  # Dataset creation
@@ -146,7 +148,9 @@ def test_condense_basins_internal(store_basins):
146
148
  rtdc_dataset.rtdc_copy(src_h5file=src,
147
149
  dst_h5file=hw.h5file,
148
150
  features="scalar")
149
- hw.store_basin(basin_name="example basin",
151
+ assert "basins" not in hw.h5file, "no basins in input file"
152
+ # store scalar and non-scalar internal basins in the input file
153
+ hw.store_basin(basin_name="scalar and non-scalar basin data",
150
154
  basin_type="internal",
151
155
  basin_format="h5dataset",
152
156
  basin_locs=["basin_events"],
@@ -165,8 +169,9 @@ def test_condense_basins_internal(store_basins):
165
169
  assert "image_bg" in ds.features_basin
166
170
  assert "image_bg" not in ds.features_innate
167
171
 
168
- # compress the basin-based dataset
169
- cli.condense(path_in=h5path_small, path_out=h5path_out,
172
+ # condense the basin-based dataset
173
+ cli.condense(path_in=h5path_small,
174
+ path_out=h5path_out,
170
175
  store_basin_features=store_basins)
171
176
 
172
177
  with h5py.File(h5path_out) as h5:
@@ -182,8 +187,10 @@ def test_condense_basins_internal(store_basins):
182
187
  assert "image_bg" not in h5["basin_events"]
183
188
 
184
189
  with new_dataset(h5path_out) as ds:
190
+ # userdef1 is an internal, scalar basin
185
191
  assert "userdef1" in ds.features_basin
186
- assert "image_bg" in ds.features_basin
192
+ # image_bg is not scalar, so it should not be here
193
+ assert "image_bg" not in ds.features_basin
187
194
 
188
195
 
189
196
  @pytest.mark.filterwarnings(
@@ -48,7 +48,13 @@ def test_basic():
48
48
  assert "Compression: None" in info
49
49
 
50
50
 
51
- def test_basin_features_internal_missing_feature():
51
+ @pytest.mark.parametrize("h5_obj_delete", [
52
+ # delete the entire basin_events directory
53
+ "basin_events",
54
+ # delete only the feature data
55
+ "basin_events/userdef1"
56
+ ])
57
+ def test_basin_features_internal_missing_feature(h5_obj_delete):
52
58
  path = retrieve_data("fmt-hdf5_polygon_gate_2021.zip")
53
59
  with RTDCWriter(path) as hw:
54
60
  size = hw.h5file["events/deform"].shape[0]
@@ -61,7 +67,7 @@ def test_basin_features_internal_missing_feature():
61
67
  basin_locs=["basin_events"],
62
68
  internal_data={"userdef1": np.arange(2)},
63
69
  )
64
- del hw.h5file["basin_events/userdef1"]
70
+ del hw.h5file[h5_obj_delete]
65
71
 
66
72
  # see if we can open the file without any error
67
73
  with check.IntegrityChecker(path) as ic:
@@ -67,6 +67,113 @@ def test_copy_basins():
67
67
  assert is_properly_compressed(hc[f"basins/{bn_hash}"])
68
68
 
69
69
 
70
+ def test_copy_basins_internal_none():
71
+ """Store an internal basin and only export scalar features"""
72
+ h5path = retrieve_data("fmt-hdf5_fl_wide-channel_2023.zip")
73
+ h5path_small = h5path.with_name("input_file.rtdc")
74
+ h5path_out = h5path.with_name("condensed.rtdc")
75
+
76
+ # Dataset creation
77
+ with h5py.File(h5path) as src, RTDCWriter(h5path_small) as hw:
78
+ # first, copy all the scalar features to the new file
79
+ rtdc_copy(src_h5file=src,
80
+ dst_h5file=hw.h5file,
81
+ features="scalar")
82
+ assert "basins" not in hw.h5file, "no basins in input file"
83
+ # store scalar and non-scalar internal basins in the input file
84
+ hw.store_basin(basin_name="scalar and non-scalar basin data",
85
+ basin_type="internal",
86
+ basin_format="h5dataset",
87
+ basin_locs=["basin_events"],
88
+ basin_descr="an example test basin",
89
+ internal_data={"image_bg": np.zeros((2, 80, 320))},
90
+ basin_map=np.zeros(src["events/deform"].shape[0]),
91
+ basin_feats=["image_bg"],
92
+ )
93
+
94
+ # sanity check
95
+ with new_dataset(h5path_small) as ds:
96
+ assert "image_bg" in ds.features_basin
97
+ assert "image_bg" not in ds.features_innate
98
+
99
+ # Now the actual tests starts.
100
+ with h5py.File(h5path_small) as src, h5py.File(h5path_out, "a") as dst:
101
+ rtdc_copy(src_h5file=src,
102
+ dst_h5file=dst,
103
+ features="scalar",
104
+ include_basins=True,
105
+ include_logs=True,
106
+ include_tables=True,
107
+ meta_prefix="")
108
+
109
+ with h5py.File(h5path_out) as h5:
110
+ # The output file should not contain the "image_bg" data.
111
+ assert "basin_events" not in h5
112
+
113
+ # When we load the basin data, "image_bg" should also not be there.
114
+ with dclab.new_dataset(h5path_out) as ds:
115
+ basin_dicts = ds.basins_get_dicts()
116
+ assert len(basin_dicts) == 0
117
+
118
+
119
+ def test_copy_basins_internal_no_scalar():
120
+ """Store an internal basin and only export scalar features"""
121
+ h5path = retrieve_data("fmt-hdf5_fl_wide-channel_2023.zip")
122
+ h5path_small = h5path.with_name("input_file.rtdc")
123
+ h5path_out = h5path.with_name("condensed.rtdc")
124
+
125
+ # Dataset creation
126
+ with h5py.File(h5path) as src, RTDCWriter(h5path_small) as hw:
127
+ # first, copy all the scalar features to the new file
128
+ rtdc_copy(src_h5file=src,
129
+ dst_h5file=hw.h5file,
130
+ features="scalar")
131
+ assert "basins" not in hw.h5file, "no basins in input file"
132
+ # store scalar and non-scalar internal basins in the input file
133
+ hw.store_basin(basin_name="scalar and non-scalar basin data",
134
+ basin_type="internal",
135
+ basin_format="h5dataset",
136
+ basin_locs=["basin_events"],
137
+ basin_descr="an example test basin",
138
+ internal_data={"userdef1": np.arange(2),
139
+ "image_bg": np.zeros((2, 80, 320)),
140
+ },
141
+ basin_map=np.zeros(src["events/deform"].shape[0]),
142
+ basin_feats=["image_bg", "userdef1"],
143
+ )
144
+
145
+ # sanity check
146
+ with new_dataset(h5path_small) as ds:
147
+ assert "userdef1" in ds.features_basin
148
+ assert "userdef1" not in ds.features_innate
149
+ assert "image_bg" in ds.features_basin
150
+ assert "image_bg" not in ds.features_innate
151
+
152
+ # Now the actual tests starts.
153
+ with h5py.File(h5path_small) as src, h5py.File(h5path_out, "a") as dst:
154
+ rtdc_copy(src_h5file=src,
155
+ dst_h5file=dst,
156
+ features="scalar",
157
+ include_basins=True,
158
+ include_logs=True,
159
+ include_tables=True,
160
+ meta_prefix="")
161
+
162
+ with h5py.File(h5path_out) as h5:
163
+ # The output file should not contain the "image_bg" data.
164
+ assert "userdef1" in h5["basin_events"]
165
+ assert "image_bg" not in h5["basin_events"]
166
+
167
+ # When we load the basin data, "image_bg" should also not be there.
168
+ with dclab.new_dataset(h5path_out) as ds:
169
+ basin_dicts = ds.basins_get_dicts()
170
+ assert len(basin_dicts) == 1
171
+ bn = basin_dicts[0]
172
+ assert bn["type"] == "internal"
173
+ assert bn["mapping"] != "same"
174
+ assert bn["features"] == ["userdef1"], "image_bg feature must be gone"
175
+
176
+
70
177
  def test_copy_basins_mapped():
71
178
  path = retrieve_data("fmt-hdf5_image-bg_2020.zip")
72
179
  path_copy = path.with_name("test_copy.rtdc")
@@ -326,6 +433,11 @@ def test_copy_tables_hdf5_issue_3214():
326
433
  rtdc_copy(src_h5file=h5,
327
434
  dst_h5file=hc)
328
435
 
436
+ # Also make sure metadata are copied
437
+ with h5py.File(path_copy) as hc:
438
+ assert hc["tables"]["cytoshot_monitor"].attrs["COLOR_shift"]\
439
+ == "#0e8f69"
440
+
329
441
 
330
442
  def test_copy_with_compression():
331
443
  path = retrieve_data("fmt-hdf5_image-bg_2020.zip")
@@ -1,5 +1,4 @@
1
1
  import pathlib
2
- import sys
3
2
  import tempfile
4
3
  import traceback
5
4
 
@@ -134,21 +133,15 @@ def test_pf_attribute_ancill_info():
134
133
  def test_pf_attribute_plugin_feature_info():
135
134
  """Check the plugin feature info attribute"""
136
135
  info = example_plugin_info_single_feature()
137
- # The identifier is dependent on the compiled byte code of the
138
- # function code (__code__.co_code), which can be different between
139
- # python versions (normally, the content of the plugin file would be used).
140
- if tuple(sys.version_info)[:3] < (3, 11, 0):
141
- identifier = "3a3e72c4cb015424ebbe6d4af63f2170"
142
- elif tuple(sys.version_info)[:3] < (3, 12, 0):
143
- # bytecode changed in Python 3.11
144
- identifier = "322e9a30665c8603ed2dd6fb9d7b18da"
145
- else:
146
- # bytecode changed in Python 3.12
147
- identifier = "447e1ae998c716140f31614a4da2581f"
148
136
  # comparing lambda functions fails due to differing memory locations
149
137
  info.pop("method check required")
150
138
  pf = PlugInFeature("circ_per_area", info)
151
139
  pf.plugin_feature_info.pop("method check required")
140
+ # The identifier is dependent on the compiled byte code of the
141
+ # function code (__code__.co_code), which can be different between
142
+ # python versions and architectures.
143
+ identifier = pf.plugin_feature_info.pop("identifier")
144
+ assert len(identifier) == 32
152
145
  plugin_feature_info = {
153
146
  "method": compute_single_plugin_feature,
154
147
  "description": "This plugin will compute a feature",
@@ -162,8 +155,8 @@ def test_pf_attribute_plugin_feature_info():
162
155
  "scalar feature": True,
163
156
  "version": "0.1.0",
164
157
  "plugin path": None,
165
- "identifier": identifier,
166
158
  }
159
+
167
160
  assert pf.plugin_feature_info == plugin_feature_info
168
161
 
169
162