dclab 0.64.0__tar.gz → 0.64.2__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 (333) hide show
  1. {dclab-0.64.0 → dclab-0.64.2}/CHANGELOG +13 -0
  2. {dclab-0.64.0 → dclab-0.64.2}/PKG-INFO +2 -2
  3. {dclab-0.64.0 → dclab-0.64.2}/dclab/_version.py +2 -2
  4. {dclab-0.64.0 → dclab-0.64.2}/dclab/definitions/feat_logic.py +27 -28
  5. {dclab-0.64.0 → dclab-0.64.2}/dclab/kde/base.py +84 -1
  6. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/core.py +3 -3
  7. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/feat_basin.py +27 -15
  8. {dclab-0.64.0 → dclab-0.64.2}/dclab/statistics.py +27 -4
  9. {dclab-0.64.0 → dclab-0.64.2}/dclab.egg-info/PKG-INFO +2 -2
  10. {dclab-0.64.0 → dclab-0.64.2}/dclab.egg-info/SOURCES.txt +2 -1
  11. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_basins/index.rst +1 -1
  12. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_code_reference.rst +2 -2
  13. {dclab-0.64.0 → dclab-0.64.2}/pyproject.toml +3 -3
  14. dclab-0.64.2/tests/test_dfn_feat.py +27 -0
  15. {dclab-0.64.0 → dclab-0.64.2}/tests/test_kde.py +70 -0
  16. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_feat_basin.py +42 -0
  17. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_fmt_http_basin.py +1 -1
  18. {dclab-0.64.0 → dclab-0.64.2}/tests/test_statistics.py +15 -0
  19. {dclab-0.64.0 → dclab-0.64.2}/.gitignore +0 -0
  20. {dclab-0.64.0 → dclab-0.64.2}/.readthedocs.yml +0 -0
  21. {dclab-0.64.0 → dclab-0.64.2}/LICENSE +0 -0
  22. {dclab-0.64.0 → dclab-0.64.2}/MANIFEST.in +0 -0
  23. {dclab-0.64.0 → dclab-0.64.2}/README.rst +0 -0
  24. {dclab-0.64.0 → dclab-0.64.2}/dclab/__init__.py +0 -0
  25. {dclab-0.64.0 → dclab-0.64.2}/dclab/cached.py +0 -0
  26. {dclab-0.64.0 → dclab-0.64.2}/dclab/cli/__init__.py +0 -0
  27. {dclab-0.64.0 → dclab-0.64.2}/dclab/cli/common.py +0 -0
  28. {dclab-0.64.0 → dclab-0.64.2}/dclab/cli/task_compress.py +0 -0
  29. {dclab-0.64.0 → dclab-0.64.2}/dclab/cli/task_condense.py +0 -0
  30. {dclab-0.64.0 → dclab-0.64.2}/dclab/cli/task_join.py +0 -0
  31. {dclab-0.64.0 → dclab-0.64.2}/dclab/cli/task_repack.py +0 -0
  32. {dclab-0.64.0 → dclab-0.64.2}/dclab/cli/task_split.py +0 -0
  33. {dclab-0.64.0 → dclab-0.64.2}/dclab/cli/task_tdms2rtdc.py +0 -0
  34. {dclab-0.64.0 → dclab-0.64.2}/dclab/cli/task_verify_dataset.py +0 -0
  35. {dclab-0.64.0 → dclab-0.64.2}/dclab/definitions/__init__.py +0 -0
  36. {dclab-0.64.0 → dclab-0.64.2}/dclab/definitions/feat_const.py +0 -0
  37. {dclab-0.64.0 → dclab-0.64.2}/dclab/definitions/meta_const.py +0 -0
  38. {dclab-0.64.0 → dclab-0.64.2}/dclab/definitions/meta_logic.py +0 -0
  39. {dclab-0.64.0 → dclab-0.64.2}/dclab/definitions/meta_parse.py +0 -0
  40. {dclab-0.64.0 → dclab-0.64.2}/dclab/downsampling.pyx +0 -0
  41. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/__init__.py +0 -0
  42. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/packaging/LICENSE +0 -0
  43. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/packaging/LICENSE.APACHE +0 -0
  44. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/packaging/LICENSE.BSD +0 -0
  45. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/packaging/__init__.py +0 -0
  46. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/packaging/_structures.py +0 -0
  47. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/packaging/version.py +0 -0
  48. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/skimage/LICENSE +0 -0
  49. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/skimage/__init__.py +0 -0
  50. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/skimage/_find_contours.py +0 -0
  51. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/skimage/_find_contours_cy.pyx +0 -0
  52. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/skimage/_pnpoly.pyx +0 -0
  53. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/skimage/_shared/__init__.py +0 -0
  54. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/skimage/_shared/geometry.pxd +0 -0
  55. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/skimage/_shared/geometry.pyx +0 -0
  56. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/skimage/measure.py +0 -0
  57. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/skimage/pnpoly.py +0 -0
  58. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/statsmodels/LICENSE +0 -0
  59. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/statsmodels/__init__.py +0 -0
  60. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/statsmodels/nonparametric/__init__.py +0 -0
  61. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/statsmodels/nonparametric/_kernel_base.py +0 -0
  62. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/statsmodels/nonparametric/kernel_density.py +0 -0
  63. {dclab-0.64.0 → dclab-0.64.2}/dclab/external/statsmodels/nonparametric/kernels.py +0 -0
  64. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/__init__.py +0 -0
  65. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/bright.py +0 -0
  66. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/bright_bc.py +0 -0
  67. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/bright_perc.py +0 -0
  68. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/contour.py +0 -0
  69. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/emodulus/__init__.py +0 -0
  70. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/emodulus/load.py +0 -0
  71. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/emodulus/lut_HE-2D-FEM-22.txt +0 -0
  72. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/emodulus/lut_HE-3D-FEM-22.txt +0 -0
  73. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/emodulus/lut_LE-2D-FEM-19.txt +0 -0
  74. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/emodulus/pxcorr.py +0 -0
  75. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/emodulus/scale_linear.py +0 -0
  76. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/emodulus/viscosity.py +0 -0
  77. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/fl_crosstalk.py +0 -0
  78. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/inert_ratio.py +0 -0
  79. {dclab-0.64.0 → dclab-0.64.2}/dclab/features/volume.py +0 -0
  80. {dclab-0.64.0 → dclab-0.64.2}/dclab/http_utils.py +0 -0
  81. {dclab-0.64.0 → dclab-0.64.2}/dclab/isoelastics/__init__.py +0 -0
  82. {dclab-0.64.0 → dclab-0.64.2}/dclab/isoelastics/iso_HE-2D-FEM-22-area_um-deform.txt +0 -0
  83. {dclab-0.64.0 → dclab-0.64.2}/dclab/isoelastics/iso_HE-2D-FEM-22-volume-deform.txt +0 -0
  84. {dclab-0.64.0 → dclab-0.64.2}/dclab/isoelastics/iso_HE-3D-FEM-22-area_um-deform.txt +0 -0
  85. {dclab-0.64.0 → dclab-0.64.2}/dclab/isoelastics/iso_HE-3D-FEM-22-volume-deform.txt +0 -0
  86. {dclab-0.64.0 → dclab-0.64.2}/dclab/isoelastics/iso_LE-2D-FEM-19-area_um-deform.txt +0 -0
  87. {dclab-0.64.0 → dclab-0.64.2}/dclab/isoelastics/iso_LE-2D-FEM-19-volume-deform.txt +0 -0
  88. {dclab-0.64.0 → dclab-0.64.2}/dclab/isoelastics/iso_LE-2D-ana-18-area_um-deform.txt +0 -0
  89. {dclab-0.64.0 → dclab-0.64.2}/dclab/kde/__init__.py +0 -0
  90. {dclab-0.64.0 → dclab-0.64.2}/dclab/kde/contours.py +0 -0
  91. {dclab-0.64.0 → dclab-0.64.2}/dclab/kde/methods.py +0 -0
  92. {dclab-0.64.0 → dclab-0.64.2}/dclab/kde_contours.py +0 -0
  93. {dclab-0.64.0 → dclab-0.64.2}/dclab/kde_methods.py +0 -0
  94. {dclab-0.64.0 → dclab-0.64.2}/dclab/lme4/__init__.py +0 -0
  95. {dclab-0.64.0 → dclab-0.64.2}/dclab/lme4/lme4_template.R +0 -0
  96. {dclab-0.64.0 → dclab-0.64.2}/dclab/lme4/rsetup.py +0 -0
  97. {dclab-0.64.0 → dclab-0.64.2}/dclab/lme4/wrapr.py +0 -0
  98. {dclab-0.64.0 → dclab-0.64.2}/dclab/polygon_filter.py +0 -0
  99. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/__init__.py +0 -0
  100. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/check.py +0 -0
  101. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/config.py +0 -0
  102. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/copier.py +0 -0
  103. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/export.py +0 -0
  104. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/feat_anc_core/__init__.py +0 -0
  105. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/feat_anc_core/af_basic.py +0 -0
  106. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/feat_anc_core/af_emodulus.py +0 -0
  107. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/feat_anc_core/af_fl_max_ctc.py +0 -0
  108. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/feat_anc_core/af_image_contour.py +0 -0
  109. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/feat_anc_core/af_ml_class.py +0 -0
  110. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/feat_anc_core/ancillary_feature.py +0 -0
  111. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/feat_anc_ml/__init__.py +0 -0
  112. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/feat_anc_plugin/__init__.py +0 -0
  113. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/feat_anc_plugin/plugin_feature.py +0 -0
  114. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/feat_temp.py +0 -0
  115. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/filter.py +0 -0
  116. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_dcor/__init__.py +0 -0
  117. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_dcor/access_token.py +0 -0
  118. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_dcor/api.py +0 -0
  119. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_dcor/base.py +0 -0
  120. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_dcor/basin.py +0 -0
  121. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_dcor/logs.py +0 -0
  122. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_dcor/tables.py +0 -0
  123. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_dict.py +0 -0
  124. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_hdf5/__init__.py +0 -0
  125. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_hdf5/base.py +0 -0
  126. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_hdf5/basin.py +0 -0
  127. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_hdf5/events.py +0 -0
  128. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_hdf5/feat_defect.py +0 -0
  129. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_hdf5/logs.py +0 -0
  130. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_hdf5/tables.py +0 -0
  131. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_hierarchy/__init__.py +0 -0
  132. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_hierarchy/base.py +0 -0
  133. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_hierarchy/events.py +0 -0
  134. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_hierarchy/hfilter.py +0 -0
  135. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_hierarchy/mapper.py +0 -0
  136. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_http.py +0 -0
  137. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_s3.py +0 -0
  138. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_tdms/__init__.py +0 -0
  139. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_tdms/event_contour.py +0 -0
  140. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_tdms/event_image.py +0 -0
  141. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_tdms/event_mask.py +0 -0
  142. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_tdms/event_trace.py +0 -0
  143. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_tdms/exc.py +0 -0
  144. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/fmt_tdms/naming.py +0 -0
  145. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/load.py +0 -0
  146. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/meta_table.py +0 -0
  147. {dclab-0.64.0 → dclab-0.64.2}/dclab/rtdc_dataset/writer.py +0 -0
  148. {dclab-0.64.0 → dclab-0.64.2}/dclab/util.py +0 -0
  149. {dclab-0.64.0 → dclab-0.64.2}/dclab/warn.py +0 -0
  150. {dclab-0.64.0 → dclab-0.64.2}/dclab.egg-info/dependency_links.txt +0 -0
  151. {dclab-0.64.0 → dclab-0.64.2}/dclab.egg-info/entry_points.txt +0 -0
  152. {dclab-0.64.0 → dclab-0.64.2}/dclab.egg-info/requires.txt +0 -0
  153. {dclab-0.64.0 → dclab-0.64.2}/dclab.egg-info/top_level.txt +0 -0
  154. {dclab-0.64.0 → dclab-0.64.2}/docs/.gitignore +0 -0
  155. {dclab-0.64.0 → dclab-0.64.2}/docs/README.md +0 -0
  156. {dclab-0.64.0 → dclab-0.64.2}/docs/conf.py +0 -0
  157. {dclab-0.64.0 → dclab-0.64.2}/docs/data/example.poly +0 -0
  158. {dclab-0.64.0 → dclab-0.64.2}/docs/data/example.rtdc +0 -0
  159. {dclab-0.64.0 → dclab-0.64.2}/docs/data/example_plugin.py +0 -0
  160. {dclab-0.64.0 → dclab-0.64.2}/docs/data/example_plugin_metadata.py +0 -0
  161. {dclab-0.64.0 → dclab-0.64.2}/docs/data/example_traces.rtdc +0 -0
  162. {dclab-0.64.0 → dclab-0.64.2}/docs/data/example_video.rtdc +0 -0
  163. {dclab-0.64.0 → dclab-0.64.2}/docs/dclab.bib +0 -0
  164. {dclab-0.64.0 → dclab-0.64.2}/docs/extensions/dclab_defs.py +0 -0
  165. {dclab-0.64.0 → dclab-0.64.2}/docs/extensions/fancy_include.py +0 -0
  166. {dclab-0.64.0 → dclab-0.64.2}/docs/extensions/github_changelog.py +0 -0
  167. {dclab-0.64.0 → dclab-0.64.2}/docs/extensions/simple_argparse.py +0 -0
  168. {dclab-0.64.0 → dclab-0.64.2}/docs/figures/DCOR_API_Token_website.png +0 -0
  169. {dclab-0.64.0 → dclab-0.64.2}/docs/index.rst +0 -0
  170. {dclab-0.64.0 → dclab-0.64.2}/docs/logo/dc_logo.png +0 -0
  171. {dclab-0.64.0 → dclab-0.64.2}/docs/logo/dc_logo.svg +0 -0
  172. {dclab-0.64.0 → dclab-0.64.2}/docs/logo/dclab.png +0 -0
  173. {dclab-0.64.0 → dclab-0.64.2}/docs/logo/dclab.svg +0 -0
  174. {dclab-0.64.0 → dclab-0.64.2}/docs/logo/dclab_large_white.png +0 -0
  175. {dclab-0.64.0 → dclab-0.64.2}/docs/logo/dclab_large_white.svg +0 -0
  176. {dclab-0.64.0 → dclab-0.64.2}/docs/logo/favicon.ico +0 -0
  177. {dclab-0.64.0 → dclab-0.64.2}/docs/logo/favicon.svg +0 -0
  178. {dclab-0.64.0 → dclab-0.64.2}/docs/requirements.txt +0 -0
  179. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_advanced_usage.rst +0 -0
  180. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_basins/basin_example_workflows.svg +0 -0
  181. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_dc_io.rst +0 -0
  182. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_dc_usage.rst +0 -0
  183. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_dcor.rst +0 -0
  184. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_emodulus/figures_emodulus/.gitignore +0 -0
  185. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_emodulus/figures_emodulus/emodulus_20um_HE-2D-FEM-22.png +0 -0
  186. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_emodulus/figures_emodulus/emodulus_20um_HE-3D-FEM-22.png +0 -0
  187. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_emodulus/figures_emodulus/emodulus_20um_LE-2D-FEM-19.png +0 -0
  188. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_emodulus/figures_emodulus/plot_emodulus_lut.py +0 -0
  189. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_emodulus/figures_emodulus/requirements.txt +0 -0
  190. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_emodulus/figures_viscosity/LICENSE +0 -0
  191. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_emodulus/figures_viscosity/buyukurganci_22_fig3a.jpg +0 -0
  192. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_emodulus/figures_viscosity/buyukurganci_22_fig3a.pdf +0 -0
  193. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_emodulus/index.rst +0 -0
  194. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_feat_plugin.rst +0 -0
  195. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_feat_temp.rst +0 -0
  196. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_fluorescence.rst +0 -0
  197. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_lme4.rst +0 -0
  198. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_notation.rst +0 -0
  199. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_s3.rst +0 -0
  200. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_av_scatter.rst +0 -0
  201. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_changelog.rst +0 -0
  202. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_cli.rst +0 -0
  203. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_examples.rst +0 -0
  204. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_getting_started.rst +0 -0
  205. {dclab-0.64.0 → dclab-0.64.2}/docs/sec_z_bib.rst +0 -0
  206. {dclab-0.64.0 → dclab-0.64.2}/examples/emodulus_dcor.jpg +0 -0
  207. {dclab-0.64.0 → dclab-0.64.2}/examples/emodulus_dcor.py +0 -0
  208. {dclab-0.64.0 → dclab-0.64.2}/examples/generate_example_images.py +0 -0
  209. {dclab-0.64.0 → dclab-0.64.2}/examples/isoelastics.jpg +0 -0
  210. {dclab-0.64.0 → dclab-0.64.2}/examples/isoelastics.py +0 -0
  211. {dclab-0.64.0 → dclab-0.64.2}/examples/isoelastics_custom.jpg +0 -0
  212. {dclab-0.64.0 → dclab-0.64.2}/examples/isoelastics_custom.py +0 -0
  213. {dclab-0.64.0 → dclab-0.64.2}/examples/lme4_glmer_diff.py +0 -0
  214. {dclab-0.64.0 → dclab-0.64.2}/examples/lme4_lmer.jpg +0 -0
  215. {dclab-0.64.0 → dclab-0.64.2}/examples/lme4_lmer.py +0 -0
  216. {dclab-0.64.0 → dclab-0.64.2}/examples/overview_plot.jpg +0 -0
  217. {dclab-0.64.0 → dclab-0.64.2}/examples/overview_plot.py +0 -0
  218. {dclab-0.64.0 → dclab-0.64.2}/examples/plugin_example.py +0 -0
  219. {dclab-0.64.0 → dclab-0.64.2}/examples/plugin_usage.jpg +0 -0
  220. {dclab-0.64.0 → dclab-0.64.2}/examples/plugin_usage.py +0 -0
  221. {dclab-0.64.0 → dclab-0.64.2}/examples/viscosity_models.jpg +0 -0
  222. {dclab-0.64.0 → dclab-0.64.2}/examples/viscosity_models.py +0 -0
  223. {dclab-0.64.0 → dclab-0.64.2}/scripts/.gitignore +0 -0
  224. {dclab-0.64.0 → dclab-0.64.2}/scripts/README.md +0 -0
  225. {dclab-0.64.0 → dclab-0.64.2}/scripts/fem2iso_volume.py +0 -0
  226. {dclab-0.64.0 → dclab-0.64.2}/scripts/fem2lutiso_std.py +0 -0
  227. {dclab-0.64.0 → dclab-0.64.2}/scripts/fem2rtdc.py +0 -0
  228. {dclab-0.64.0 → dclab-0.64.2}/scripts/lut_recipes/__init__.py +0 -0
  229. {dclab-0.64.0 → dclab-0.64.2}/scripts/lut_recipes/hooks/LUT_analytical_linear-elastic_2Daxis.txt +0 -0
  230. {dclab-0.64.0 → dclab-0.64.2}/scripts/lut_recipes/hooks/README.md +0 -0
  231. {dclab-0.64.0 → dclab-0.64.2}/scripts/lut_recipes/hooks/__init__.py +0 -0
  232. {dclab-0.64.0 → dclab-0.64.2}/scripts/lut_recipes/hooks/common.py +0 -0
  233. {dclab-0.64.0 → dclab-0.64.2}/scripts/lut_recipes/hooks/he_2d_fem_22.py +0 -0
  234. {dclab-0.64.0 → dclab-0.64.2}/scripts/lut_recipes/hooks/he_3d_fem_22.py +0 -0
  235. {dclab-0.64.0 → dclab-0.64.2}/scripts/lut_recipes/hooks/le_2d_fem_19.py +0 -0
  236. {dclab-0.64.0 → dclab-0.64.2}/scripts/lut_recipes/lut_processor.py +0 -0
  237. {dclab-0.64.0 → dclab-0.64.2}/scripts/pixelation_correction.py +0 -0
  238. {dclab-0.64.0 → dclab-0.64.2}/scripts/pixelation_correction_2020.png +0 -0
  239. {dclab-0.64.0 → dclab-0.64.2}/scripts/pixelation_correction_2022.png +0 -0
  240. {dclab-0.64.0 → dclab-0.64.2}/scripts/requirements.txt +0 -0
  241. {dclab-0.64.0 → dclab-0.64.2}/setup.cfg +0 -0
  242. {dclab-0.64.0 → dclab-0.64.2}/setup.py +0 -0
  243. {dclab-0.64.0 → dclab-0.64.2}/tests/README.md +0 -0
  244. {dclab-0.64.0 → dclab-0.64.2}/tests/conftest.py +0 -0
  245. {dclab-0.64.0 → dclab-0.64.2}/tests/data/README.md +0 -0
  246. {dclab-0.64.0 → dclab-0.64.2}/tests/data/example_access_token.dcor-access +0 -0
  247. {dclab-0.64.0 → dclab-0.64.2}/tests/data/example_isoelastics.txt +0 -0
  248. {dclab-0.64.0 → dclab-0.64.2}/tests/data/feat_anc_plugin_creative.py +0 -0
  249. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-hdf5_fl-no-contour_2019.zip +0 -0
  250. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-hdf5_fl_2017.zip +0 -0
  251. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-hdf5_fl_2018.zip +0 -0
  252. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-hdf5_fl_wide-channel_2023.zip +0 -0
  253. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-hdf5_image-bg_2020.zip +0 -0
  254. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-hdf5_image-mask-blood_2021.zip +0 -0
  255. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-hdf5_mask-contour_2018.zip +0 -0
  256. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-hdf5_polygon_gate_2021.zip +0 -0
  257. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-hdf5_raw-cytoshot-exported.zip +0 -0
  258. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-hdf5_segfault-compound_2023.zip +0 -0
  259. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-hdf5_wide-channel_2023.zip +0 -0
  260. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-tdms_2fl-no-image_2017.zip +0 -0
  261. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-tdms_fl-image-bright_2017.zip +0 -0
  262. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-tdms_fl-image-large-fov_2017.zip +0 -0
  263. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-tdms_fl-image_2016.zip +0 -0
  264. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-tdms_fl_2015.zip +0 -0
  265. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-tdms_minimal_2016.zip +0 -0
  266. {dclab-0.64.0 → dclab-0.64.2}/tests/data/fmt-tdms_shapein-2.0.1-no-image_2017.zip +0 -0
  267. {dclab-0.64.0 → dclab-0.64.2}/tests/helper_methods.py +0 -0
  268. {dclab-0.64.0 → dclab-0.64.2}/tests/requirements.txt +0 -0
  269. {dclab-0.64.0 → dclab-0.64.2}/tests/test_cache.py +0 -0
  270. {dclab-0.64.0 → dclab-0.64.2}/tests/test_cli.py +0 -0
  271. {dclab-0.64.0 → dclab-0.64.2}/tests/test_cli_argparse.py +0 -0
  272. {dclab-0.64.0 → dclab-0.64.2}/tests/test_cli_compress.py +0 -0
  273. {dclab-0.64.0 → dclab-0.64.2}/tests/test_cli_condense.py +0 -0
  274. {dclab-0.64.0 → dclab-0.64.2}/tests/test_cli_join.py +0 -0
  275. {dclab-0.64.0 → dclab-0.64.2}/tests/test_cli_repack.py +0 -0
  276. {dclab-0.64.0 → dclab-0.64.2}/tests/test_cli_split.py +0 -0
  277. {dclab-0.64.0 → dclab-0.64.2}/tests/test_config_value_mapping.py +0 -0
  278. /dclab-0.64.0/tests/test_dfn.py → /dclab-0.64.2/tests/test_dfn_meta.py +0 -0
  279. {dclab-0.64.0 → dclab-0.64.2}/tests/test_downsampling.py +0 -0
  280. {dclab-0.64.0 → dclab-0.64.2}/tests/test_feat_bright.py +0 -0
  281. {dclab-0.64.0 → dclab-0.64.2}/tests/test_feat_bright_bc.py +0 -0
  282. {dclab-0.64.0 → dclab-0.64.2}/tests/test_feat_bright_perc.py +0 -0
  283. {dclab-0.64.0 → dclab-0.64.2}/tests/test_feat_contour.py +0 -0
  284. {dclab-0.64.0 → dclab-0.64.2}/tests/test_feat_emodulus.py +0 -0
  285. {dclab-0.64.0 → dclab-0.64.2}/tests/test_feat_emodulus_viscosity.py +0 -0
  286. {dclab-0.64.0 → dclab-0.64.2}/tests/test_feat_fl_crosstalk.py +0 -0
  287. {dclab-0.64.0 → dclab-0.64.2}/tests/test_feat_inert_ratio.py +0 -0
  288. {dclab-0.64.0 → dclab-0.64.2}/tests/test_feat_volume.py +0 -0
  289. {dclab-0.64.0 → dclab-0.64.2}/tests/test_http_utils.py +0 -0
  290. {dclab-0.64.0 → dclab-0.64.2}/tests/test_isoelastics.py +0 -0
  291. {dclab-0.64.0 → dclab-0.64.2}/tests/test_kde_contours.py +0 -0
  292. {dclab-0.64.0 → dclab-0.64.2}/tests/test_kde_deprecations.py +0 -0
  293. {dclab-0.64.0 → dclab-0.64.2}/tests/test_kde_methods.py +0 -0
  294. {dclab-0.64.0 → dclab-0.64.2}/tests/test_lme4.py +0 -0
  295. {dclab-0.64.0 → dclab-0.64.2}/tests/test_lut_he_2d_fem_22.py +0 -0
  296. {dclab-0.64.0 → dclab-0.64.2}/tests/test_lut_he_3d_fem_22.py +0 -0
  297. {dclab-0.64.0 → dclab-0.64.2}/tests/test_polygon_contains.py +0 -0
  298. {dclab-0.64.0 → dclab-0.64.2}/tests/test_polygon_filter.py +0 -0
  299. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_check_dataset.py +0 -0
  300. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_config.py +0 -0
  301. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_copier.py +0 -0
  302. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_core_feat.py +0 -0
  303. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_downsampling.py +0 -0
  304. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_export.py +0 -0
  305. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_export_avi.py +0 -0
  306. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_export_fcs.py +0 -0
  307. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_export_hdf5.py +0 -0
  308. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_export_tsv.py +0 -0
  309. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_feat_anc_core.py +0 -0
  310. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_feat_anc_ml.py +0 -0
  311. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_feat_anc_plugin.py +0 -0
  312. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_feat_basin_mapped.py +0 -0
  313. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_feat_basin_perishable.py +0 -0
  314. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_feat_temp.py +0 -0
  315. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_filter.py +0 -0
  316. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_fmt_dcor.py +0 -0
  317. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_fmt_dcor_access_token.py +0 -0
  318. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_fmt_dcor_basin.py +0 -0
  319. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_fmt_dcor_private.py +0 -0
  320. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_fmt_dict.py +0 -0
  321. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_fmt_hdf5.py +0 -0
  322. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_fmt_hdf5_basins.py +0 -0
  323. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_fmt_hdf5_basins_internal.py +0 -0
  324. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_fmt_hierarchy.py +0 -0
  325. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_fmt_http.py +0 -0
  326. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_fmt_s3.py +0 -0
  327. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_fmt_s3_basin.py +0 -0
  328. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_fmt_tdms.py +0 -0
  329. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_hash.py +0 -0
  330. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_kde.py +0 -0
  331. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_limit_events.py +0 -0
  332. {dclab-0.64.0 → dclab-0.64.2}/tests/test_rtdc_writer.py +0 -0
  333. {dclab-0.64.0 → dclab-0.64.2}/tests/test_util.py +0 -0
@@ -1,3 +1,16 @@
1
+ 0.64.2
2
+ - fix: string comparison TypeError when verifying basins, in niche cases
3
+ when basin's run identifier was not specified or could not be computed
4
+ - enh: raise NotImplementedError when subsetting basin contour data
5
+ - enh: make measurement identifier computation robust against empty strings
6
+ - ref: remove zombie code for fetching ML model label from model instance
7
+ - ref: minor cleanup in feature definitions
8
+ - docs: minor cleanup
9
+ 0.64.1
10
+ - enh: introduce `KernelDensityEstimator.get_at`
11
+ - enh: add 10th, 25th, 75th, and 90th percentile statistics methods
12
+ - enh: new `ret_dict` arg in `get_statistics` returns dict instead of tuple
13
+ - setup: fix finding packages in pyproject.toml
1
14
  0.64.0
2
15
  - feat: introduce concept of perishable (e.g. temporally expiring) basins
3
16
  - feat: add `PerishableRecord` to presigned URLs for DCOR basins (#244)
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dclab
3
- Version: 0.64.0
3
+ Version: 0.64.2
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>
7
- License: GPL-2.0-or-later
7
+ License-Expression: GPL-2.0-or-later
8
8
  Project-URL: source, https://github.com/DC-Analysis/dclab
9
9
  Project-URL: tracker, https://github.com/DC-Analysis/dclab/issues
10
10
  Project-URL: documentation, https://dclab.readthedocs.io/en/stable/
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.64.0'
21
- __version_tuple__ = version_tuple = (0, 64, 0)
20
+ __version__ = version = '0.64.2'
21
+ __version_tuple__ = version_tuple = (0, 64, 2)
@@ -1,6 +1,11 @@
1
+ import re
2
+
1
3
  from . import feat_const
2
4
 
3
5
 
6
+ ML_SCORE_REGEX = re.compile(r"^ml_score_[a-z0-9]{3}$")
7
+
8
+
4
9
  def check_feature_shape(name, data):
5
10
  """Check if (non)-scalar feature matches with its data's dimensionality
6
11
 
@@ -17,11 +22,15 @@ def check_feature_shape(name, data):
17
22
  If the data's shape does not match its scalar description
18
23
  """
19
24
  if len(data.shape) == 1 and not scalar_feature_exists(name):
20
- raise ValueError(f"Feature '{name}' is not a scalar feature, but "
21
- "a 1D array was given for `data`!")
25
+ raise ValueError(
26
+ f"Feature '{name}' is not a scalar feature, but "
27
+ "a 1D array was given for `data`!"
28
+ )
22
29
  elif len(data.shape) != 1 and scalar_feature_exists(name):
23
- raise ValueError(f"Feature '{name}' is a scalar feature, but the "
24
- "`data` array is not 1D!")
30
+ raise ValueError(
31
+ f"Feature '{name}' is a scalar feature, but the "
32
+ "`data` array is not 1D!"
33
+ )
25
34
 
26
35
 
27
36
  def feature_exists(name, scalar_only=False):
@@ -56,15 +65,9 @@ def feature_exists(name, scalar_only=False):
56
65
  elif not scalar_only and name in feat_const.feature_names:
57
66
  # non-scalar feature
58
67
  valid = True
59
- else:
60
- # check whether we have an `ml_score_???` feature
61
- valid_chars = "0123456789abcdefghijklmnopqrstuvwxyz"
62
- if (name.startswith("ml_score_")
63
- and len(name) == len("ml_score_???")
64
- and name[-3] in valid_chars
65
- and name[-2] in valid_chars
66
- and name[-1] in valid_chars):
67
- valid = True
68
+ elif ML_SCORE_REGEX.match(name):
69
+ # machine-learning score feature ml_score_???
70
+ valid = True
68
71
  return valid
69
72
 
70
73
 
@@ -93,8 +96,10 @@ def feature_register(name, label=None, is_scalar=True):
93
96
  allowed_chars = "abcdefghijklmnopqrstuvwxyz_1234567890"
94
97
  feat = "".join([f for f in name if f in allowed_chars])
95
98
  if feat != name:
96
- raise ValueError("`feature` must only contain lower-case characters, "
97
- f"digits, and underscores; got '{name}'!")
99
+ raise ValueError(
100
+ "`feature` must only contain lower-case characters, "
101
+ f"digits, and underscores; got '{name}'!"
102
+ )
98
103
  if label is None:
99
104
  label = f"User-defined feature {name}"
100
105
  if feature_exists(name):
@@ -156,22 +161,16 @@ def get_feature_label(name, rtdc_ds=None, with_unit=True):
156
161
  TODO: extract feature label from ancillary information when an rtdc_ds is
157
162
  given.
158
163
  """
159
- # TODO: Is there another way of avoiding this circular import?
160
- from ..rtdc_dataset.feat_anc_core.ancillary_feature import AncillaryFeature
161
- assert feature_exists(name)
162
164
  if name in feat_const.feature_name2label:
163
165
  label = feat_const.feature_name2label[name]
166
+ elif ML_SCORE_REGEX.match(name):
167
+ # use a generic name for machine-learning features
168
+ label = f"ML score {name[-3:].upper()}"
164
169
  else:
165
- # First check whether an ancillary feature with that
166
- # name exists.
167
- for af in AncillaryFeature.features:
168
- if af.feature_name == name:
169
- labelid = af.data.outputs.index(name)
170
- label = af.data.output_labels[labelid]
171
- break
172
- else:
173
- # If that did not work, use a generic name.
174
- label = "ML score {}".format(name[-3:].upper())
170
+ exists = feature_exists(name)
171
+ msg = f"Could not find label for '{name}'"
172
+ msg += " (feature does not exist)" if not exists else ""
173
+ raise ValueError(msg)
175
174
  if not with_unit:
176
175
  if label.endswith("]") and label.count("["):
177
176
  label = label.rsplit("[", 1)[0].strip()
@@ -1,6 +1,7 @@
1
1
  import warnings
2
2
 
3
3
  import numpy as np
4
+ from scipy.interpolate import RegularGridInterpolator as RGI
4
5
 
5
6
  from .methods import bin_width_doane_div5, get_bad_vals, methods
6
7
  from .contours import find_contours_level, get_quantile_levels
@@ -316,6 +317,8 @@ class KernelDensityEstimator:
316
317
  yscale="linear"):
317
318
  """Evaluate the kernel density estimate for scatter plots
318
319
 
320
+ The KDE is evaluated with the `kde_type` function for every point.
321
+
319
322
  Parameters
320
323
  ----------
321
324
  xax: str
@@ -332,7 +335,7 @@ class KernelDensityEstimator:
332
335
  Additional keyword arguments to the KDE method
333
336
  xscale: str
334
337
  If set to "log", take the logarithm of the x-values before
335
- computing the KDE. This is useful when data are are
338
+ computing the KDE. This is useful when data are
336
339
  displayed on a log-scale. Defaults to "linear".
337
340
  yscale: str
338
341
  See `xscale`.
@@ -374,3 +377,83 @@ class KernelDensityEstimator:
374
377
  density = np.array([])
375
378
 
376
379
  return density
380
+
381
+ def get_at(self, xax="area_um", yax="deform", positions=None,
382
+ kde_type="histogram", kde_kwargs=None, xscale="linear",
383
+ yscale="linear"):
384
+ """Evaluate the kernel density estimate for specific events
385
+
386
+ The KDE is computed via linear interpolation from the output
387
+ of `get_raster`.
388
+
389
+ Parameters
390
+ ----------
391
+ xax: str
392
+ Identifier for X axis (e.g. "area_um", "aspect", "deform")
393
+ yax: str
394
+ Identifier for Y axis
395
+ positions: list of two 1d ndarrays or ndarray of shape (2, N)
396
+ The positions where the KDE will be computed. Note that
397
+ the KDE estimate is computed from the points that
398
+ are set in `self.rtdc_ds.filter.all`.
399
+ kde_type: str
400
+ The KDE method to use, see :const:`.kde_methods.methods`
401
+ kde_kwargs: dict
402
+ Additional keyword arguments to the KDE method
403
+ xscale: str
404
+ If set to "log", take the logarithm of the x-values before
405
+ computing the KDE. This is useful when data are
406
+ displayed on a log-scale. Defaults to "linear".
407
+ yscale: str
408
+ See `xscale`.
409
+
410
+ Returns
411
+ -------
412
+ density : 1d ndarray
413
+ The kernel density evaluated for the filtered events.
414
+ """
415
+ if kde_kwargs is None:
416
+ kde_kwargs = {}
417
+ xax = xax.lower()
418
+ yax = yax.lower()
419
+ kde_type = kde_type.lower()
420
+ if kde_type not in methods:
421
+ raise ValueError(f"Not a valid kde type: {kde_type}!")
422
+
423
+ # Get data
424
+ x = self.rtdc_ds[xax][self.rtdc_ds.filter.all]
425
+ y = self.rtdc_ds[yax][self.rtdc_ds.filter.all]
426
+
427
+ # Apply scale (no change for linear scale)
428
+ xs = self.apply_scale(x, xscale, xax)
429
+ ys = self.apply_scale(y, yscale, yax)
430
+
431
+ if positions:
432
+ xs = self.apply_scale(positions[0], xscale, xax)
433
+ ys = self.apply_scale(positions[1], yscale, yax)
434
+
435
+ if len(x):
436
+ xr, yr, density_grid = self.get_raster(xax=xax,
437
+ yax=yax,
438
+ kde_type=kde_type,
439
+ kde_kwargs=kde_kwargs,
440
+ xscale=xscale,
441
+ yscale=yscale)
442
+
443
+ # Apply scale (no change for linear scale)
444
+ xrs = self.apply_scale(xr, xscale, xax)
445
+ yrs = self.apply_scale(yr, yscale, yax)
446
+
447
+ # 'scipy.interp2d' has been removed in SciPy 1.14.0
448
+ # https://scipy.github.io/devdocs/tutorial/interpolate/interp_transition_guide.html
449
+ interp_func = RGI((xrs[:, 0], yrs[0, :]),
450
+ density_grid,
451
+ method="linear",
452
+ bounds_error=False,
453
+ fill_value=np.nan)
454
+ density = interp_func((xs, ys))
455
+
456
+ else:
457
+ density = np.array([])
458
+
459
+ return density
@@ -835,9 +835,9 @@ class RTDCBase(abc.ABC):
835
835
  identifier = self.config.get("experiment", {}).get("run identifier",
836
836
  None)
837
837
  if identifier is None:
838
- time = self.config.get("experiment", {}).get("time", None)
839
- date = self.config.get("experiment", {}).get("date", None)
840
- sid = self.config.get("setup", {}).get("identifier", None)
838
+ time = self.config.get("experiment", {}).get("time", None) or None
839
+ date = self.config.get("experiment", {}).get("date", None) or None
840
+ sid = self.config.get("setup", {}).get("identifier", None) or None
841
841
  if None not in [time, date, sid]:
842
842
  # only compute an identifier if all of the above are defined.
843
843
  hasher = hashlib.md5(f"{time}_{date}_{sid}".encode("utf-8"))
@@ -458,22 +458,30 @@ class Basin(abc.ABC):
458
458
  if not self._measurement_identifier_verified:
459
459
  if self.measurement_identifier is None:
460
460
  # No measurement identifier was presented by the
461
- # referencing dataset. Don't perform any checks.
461
+ # referencing dataset. We are in the dark.
462
+ # Don't perform any checks.
462
463
  self._measurement_identifier_verified = True
463
464
  else:
464
- if self.mapping == "same":
465
- # When we have identical mapping, then the measurement
466
- # identifier has to match exactly.
467
- verifier = str.__eq__
465
+ # This is the measurement identifier of the basin.
466
+ basin_identifier = self.get_measurement_identifier()
467
+ if basin_identifier is None:
468
+ # Again, we are in the dark, because the basin dataset
469
+ # does not have an identifier. This is an undesirable
470
+ # situation, but there is nothing we can do about it.
471
+ self._measurement_identifier_verified = True
468
472
  else:
469
- # When we have non-identical mapping (e.g. exported
470
- # data), then the measurement identifier has to
471
- # partially match.
472
- verifier = str.startswith
473
- self._measurement_identifier_verified = verifier(
474
- self.measurement_identifier,
475
- self.get_measurement_identifier()
476
- )
473
+ if self.mapping == "same":
474
+ # When we have identical mapping, then the
475
+ # measurement identifier has to match exactly.
476
+ verifier = str.__eq__
477
+ else:
478
+ # When we have non-identical mapping (e.g. exported
479
+ # data), then the measurement identifier has to
480
+ # partially match.
481
+ verifier = str.startswith
482
+ self._measurement_identifier_verified = verifier(
483
+ self.measurement_identifier, basin_identifier)
484
+
477
485
  check_rid = self._measurement_identifier_verified
478
486
  else:
479
487
  check_rid = True
@@ -538,8 +546,12 @@ class BasinProxy:
538
546
 
539
547
  def __getitem__(self, feat):
540
548
  if feat not in self._features:
541
- feat_obj = BasinProxyFeature(feat_obj=self.ds[feat],
542
- basinmap=self.basinmap)
549
+ if feat == "contour":
550
+ raise NotImplementedError("Feature 'contour' cannot be "
551
+ "handled by BasinProxy.")
552
+ else:
553
+ feat_obj = BasinProxyFeature(feat_obj=self.ds[feat],
554
+ basinmap=self.basinmap)
543
555
  self._features[feat] = feat_obj
544
556
  return self._features[feat]
545
557
 
@@ -86,7 +86,7 @@ def flow_rate(ds):
86
86
  return np.nan
87
87
 
88
88
 
89
- def get_statistics(ds, methods=None, features=None):
89
+ def get_statistics(ds, methods=None, features=None, ret_dict=False):
90
90
  """Compute statistics for an RT-DC dataset
91
91
 
92
92
  Parameters
@@ -96,13 +96,16 @@ def get_statistics(ds, methods=None, features=None):
96
96
  methods: list of str or None
97
97
  The methods wih which to compute the statistics.
98
98
  The list of available methods is given with
99
- `dclab.statistics.Statistics.available_methods.keys()`
99
+ :func:`.available_methods.keys`
100
100
  If set to `None`, statistics for all methods are computed.
101
101
  features: list of str
102
102
  Feature name identifiers are defined by
103
- `dclab.definitions.feature_exists`.
103
+ :func:`dclab.definitions.feature_exists`.
104
104
  If set to `None`, statistics for all scalar features
105
105
  available are computed.
106
+ ret_dict: bool
107
+ Instead of returning ``(header, values)``, return a dictionary
108
+ with headers as keys.
106
109
 
107
110
  Returns
108
111
  -------
@@ -148,7 +151,10 @@ def get_statistics(ds, methods=None, features=None):
148
151
  label = dfn.get_feature_label(ft, rtdc_ds=ds)
149
152
  header.append(" ".join([mt, label]))
150
153
 
151
- return header, values
154
+ if ret_dict:
155
+ return dict(zip(header, values))
156
+ else:
157
+ return header, values
152
158
 
153
159
 
154
160
  def mode(data):
@@ -191,7 +197,24 @@ def mode(data):
191
197
  # Register all the methods
192
198
  # Methods that require an axis
193
199
  Statistics(name="Mean", req_feature=True, method=np.average)
200
+ # Premature-Optimization warning: `np.percentile` also accepts an array
201
+ # of percentiles as the `q` argument, which I would expect to yield better
202
+ # performance than computing percentiles individually. Implementing this
203
+ # would break the way we are defining statistical methods here (One
204
+ # `Statistics` instance per method) and thus requires a considerable
205
+ # amount of work (much more work than writing this text here). It would
206
+ # also make understanding the code more difficult. In addition, computing
207
+ # statistics is not done often and is extremely fast anyway for a few
208
+ # millions of events. Don't optimize this!
209
+ Statistics(name="10th Percentile", req_feature=True,
210
+ method=lambda data: np.percentile(data, 10))
211
+ Statistics(name="25th Percentile", req_feature=True,
212
+ method=lambda data: np.percentile(data, 25))
194
213
  Statistics(name="Median", req_feature=True, method=np.median)
214
+ Statistics(name="75th Percentile", req_feature=True,
215
+ method=lambda data: np.percentile(data, 75))
216
+ Statistics(name="90th Percentile", req_feature=True,
217
+ method=lambda data: np.percentile(data, 90))
195
218
  Statistics(name="Mode", req_feature=True, method=mode)
196
219
  Statistics(name="SD", req_feature=True, method=np.std)
197
220
  # Methods that work on RTDCBase
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dclab
3
- Version: 0.64.0
3
+ Version: 0.64.2
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>
7
- License: GPL-2.0-or-later
7
+ License-Expression: GPL-2.0-or-later
8
8
  Project-URL: source, https://github.com/DC-Analysis/dclab
9
9
  Project-URL: tracker, https://github.com/DC-Analysis/dclab/issues
10
10
  Project-URL: documentation, https://dclab.readthedocs.io/en/stable/
@@ -246,7 +246,8 @@ tests/test_cli_join.py
246
246
  tests/test_cli_repack.py
247
247
  tests/test_cli_split.py
248
248
  tests/test_config_value_mapping.py
249
- tests/test_dfn.py
249
+ tests/test_dfn_feat.py
250
+ tests/test_dfn_meta.py
250
251
  tests/test_downsampling.py
251
252
  tests/test_feat_bright.py
252
253
  tests/test_feat_bright_bc.py
@@ -432,7 +432,7 @@ are a few things to notice:
432
432
  This relative path makes it possible to copy-paste these two files *together* to
433
433
  other locations. You will always be able to open the output file and see the
434
434
  basin features defined in the input file. Internally, dclab also checks
435
- the :func:`measurement identifier <.RTDCBase.get_measurement_identifier>`
435
+ the :meth:`run identifier <dclab.rtdc_dataset.RTDCBase.get_measurement_identifier>`
436
436
  of the output file against that of the input file to avoid loading basin
437
437
  features from the wrong file.
438
438
 
@@ -304,8 +304,8 @@ isoelastics
304
304
 
305
305
  .. _sec_ref_kde:
306
306
 
307
- kernel density estimators (KDEs)
308
- -------------------------------
307
+ Kernel Density Estimators (KDEs)
308
+ --------------------------------
309
309
  .. autoclass:: dclab.kde.KernelDensityEstimator
310
310
  :members:
311
311
 
@@ -34,7 +34,7 @@ classifiers = [
34
34
  'Topic :: Scientific/Engineering :: Visualization',
35
35
  'Intended Audience :: Science/Research',
36
36
  ]
37
- license = {text = "GPL-2.0-or-later"}
37
+ license = "GPL-2.0-or-later"
38
38
  # This is not supported in Python 3.8
39
39
  # license = "GPL-2.0-or-later"
40
40
  dependencies = [
@@ -75,8 +75,8 @@ changelog = "https://dclab.readthedocs.io/en/stable/sec_changelog.html"
75
75
  # We need the following, because automatic package discovery does not work
76
76
  # when running cibuildwheel on GitHub Actions (there will be a "wheelhouse"
77
77
  # directory).
78
- [tool.setuptools]
79
- packages = ["dclab"]
78
+ [tool.setuptools.packages.find]
79
+ include = ["dclab"]
80
80
 
81
81
  [tool.setuptools_scm]
82
82
  write_to = "dclab/_version.py"
@@ -0,0 +1,27 @@
1
+ import pytest
2
+
3
+ import dclab
4
+ from dclab.definitions import get_feature_label
5
+
6
+
7
+ @pytest.mark.parametrize("name,label",
8
+ [
9
+ ["ml_score_rbc", "ML score RBC"],
10
+ ["deform", "Deformation"],
11
+ ["area_um", "Area [µm²]"],
12
+ ])
13
+ def test_get_feature_label_basic(name, label):
14
+ assert get_feature_label(name) == label
15
+
16
+
17
+ def test_get_feature_label_temporary():
18
+ name = "unknown"
19
+ label = "User-defined feature unknown"
20
+ dclab.register_temporary_feature(name)
21
+ assert get_feature_label(name) == label
22
+
23
+
24
+ def test_get_feature_label_invalid():
25
+ name = "unknown2"
26
+ with pytest.raises(ValueError, match="unknown2"):
27
+ get_feature_label(name)
@@ -5,6 +5,8 @@ from dclab.external import skimage
5
5
  from dclab.kde import KernelDensityEstimator
6
6
  from dclab import polygon_filter
7
7
 
8
+ from helper_methods import example_data_dict
9
+
8
10
 
9
11
  def test_contour_lines():
10
12
  np.random.seed(47)
@@ -99,3 +101,71 @@ def test_contour_lines_data_with_too_much_space():
99
101
  yscale="linear",
100
102
  quantiles=[0.5])
101
103
  assert not contours, "there should be no contours with too much space"
104
+
105
+
106
+ def test_kde_log_get_at():
107
+ ddict = example_data_dict(size=300, keys=["area_um", "deform"])
108
+ ddict["deform"][:20] = .1
109
+ ddict["area_um"][:20] = .5
110
+ ds = dclab.new_dataset(ddict)
111
+ kde_instance = KernelDensityEstimator(ds)
112
+ a = kde_instance.get_at(xax="area_um", yax="deform", yscale="log")
113
+ assert np.all(a[:20] == a[0])
114
+
115
+
116
+ def test_kde_log_get_at_points():
117
+ ddict = example_data_dict(size=300, keys=["area_um", "tilt"])
118
+ ds = dclab.new_dataset(ddict)
119
+ kde_instance = KernelDensityEstimator(ds)
120
+ a = kde_instance.get_at(yscale="log", xax="area_um", yax="tilt")
121
+ b = kde_instance.get_at(yscale="log", xax="area_um", yax="tilt")
122
+
123
+ assert np.all(a == b)
124
+
125
+
126
+ def test_kde_log_get_at_invalid():
127
+ ddict = example_data_dict(size=300, keys=["area_um", "deform"])
128
+ ddict["deform"][:20] = .1
129
+ ddict["area_um"][:20] = .5
130
+ ddict["deform"][21] = np.nan
131
+ ddict["deform"][22] = np.inf
132
+ ddict["deform"][23] = -.1
133
+ ds = dclab.new_dataset(ddict)
134
+ kde_instance = KernelDensityEstimator(ds)
135
+ a = kde_instance.get_at(xax="area_um", yax="deform", yscale="log")
136
+ assert np.all(a[:20] == a[0])
137
+ assert np.isnan(a[21])
138
+ assert np.isnan(a[22])
139
+ assert np.isnan(a[23])
140
+
141
+
142
+ def test_kde_get_at_positions():
143
+ ddict = example_data_dict()
144
+ ds = dclab.new_dataset(ddict)
145
+
146
+ kde_instance = KernelDensityEstimator(ds)
147
+
148
+ ds.config["filtering"]["enable filters"] = False
149
+ sc = kde_instance.get_at(xax="area_um", yax="deform")
150
+ sc2 = kde_instance.get_at(xax="area_um", yax="deform",
151
+ positions=(ds["area_um"], ds["deform"]))
152
+ assert np.all(sc == sc2)
153
+
154
+
155
+ def test_kde_log_get_at_out_of_bounds():
156
+ ddict = example_data_dict(size=300, keys=["area_um", "deform"])
157
+ ds = dclab.new_dataset(ddict)
158
+ kde_instance = KernelDensityEstimator(ds)
159
+
160
+ # Define a positions that has values outside the typical data range
161
+ # `area_um` ([0.0, 400]) and `deform` ([0.0, 0.02])
162
+ positions = ([410, 300, 300, 300],
163
+ [-1, -2, 0.01, 0.015])
164
+
165
+ # Get the density at the out-of-bounds position
166
+ a = kde_instance.get_at(xax="area_um", yax="deform",
167
+ positions=positions, yscale="log")
168
+ assert np.isnan(a[0])
169
+ assert np.isnan(a[1])
170
+ assert np.isfinite(a[2])
171
+ assert np.isfinite(a[3])
@@ -418,6 +418,48 @@ def test_basin_key_reproducible():
418
418
  ]
419
419
 
420
420
 
421
+ def test_basin_run_identifier_unknown():
422
+ """
423
+ When the run identifier of a basin is unknown, the basin
424
+ should still be accepted.
425
+ """
426
+ h5path = retrieve_data("fmt-hdf5_fl_wide-channel_2023.zip")
427
+ with h5py.File(h5path, "a") as h5:
428
+ # remove run identifier and metadata from which run identifier
429
+ # can be computed.
430
+ for attr in [
431
+ "experiment:run identifier",
432
+ "experiment:time",
433
+ "experiment:date",
434
+ "setup:identifier",
435
+ ]:
436
+ if attr in h5.attrs:
437
+ del h5.attrs[attr]
438
+ assert attr not in h5.attrs
439
+
440
+ export_same = h5path.with_name("same.rtdc")
441
+ export_subs = h5path.with_name("subs.rtdc")
442
+
443
+ # Check whether that worked and export a subset with basins.
444
+ with dclab.new_dataset(h5path) as ds:
445
+ assert ds.get_measurement_identifier() is None
446
+ # export without filters
447
+ ds.export.hdf5(export_same, features=["deform"], basins=True)
448
+ # export with filters
449
+ ds.filter.manual[::2] = False
450
+ ds.apply_filter()
451
+ ds.export.hdf5(export_subs, features=["deform"], basins=True)
452
+
453
+ # Try to open the exported datasets (this raised an error before)
454
+ with dclab.new_dataset(export_same) as ds:
455
+ assert "image" in ds
456
+ assert ds["image"][0][0, 0] == 124
457
+
458
+ with dclab.new_dataset(export_subs) as ds:
459
+ assert "image" in ds
460
+ assert ds["image"][0][0, 0] == 126
461
+
462
+
421
463
  def test_basin_sorting_basic():
422
464
  bnlist = [
423
465
  {"type": "remote", "format": "dcor", "ident": 0},
@@ -258,7 +258,7 @@ def test_trace_availability_invalid(tmp_path):
258
258
  bdat = {
259
259
  "type": "remote",
260
260
  "format": "http",
261
- "urls": ["https://dcor.mpl.mpg.de/api/3/action/site_read"],
261
+ "urls": ["https://dcor.mpl.mpg.de/api/3/action/status_show"],
262
262
  "features": ["trace"],
263
263
  }
264
264
  blines = json.dumps(bdat, indent=2).split("\n")
@@ -99,6 +99,21 @@ def test_false_method():
99
99
  break
100
100
 
101
101
 
102
+ def test_percentiles():
103
+ ddict = example_data_dict(size=1_000, keys=["area_um", "deform"])
104
+ np.random.seed(42)
105
+ ddict["userdef1"] = np.random.random(1_000)
106
+ ds = dclab.new_dataset(ddict)
107
+ stats = dclab.statistics.get_statistics(ds, ret_dict=True)
108
+ for pp in [10, 25, 75, 90]:
109
+ # We have one thousand events in the userdef1 feature that are
110
+ # evenly distributed between 0 and 1. We allow an error of 5%
111
+ # relative to 1, which should be sufficient to capture the
112
+ # randomness.
113
+ assert np.allclose(stats[f"{pp}th Percentile User-defined 1"], pp/100,
114
+ rtol=0, atol=0.05)
115
+
116
+
102
117
  def test_stats_without_features():
103
118
  ddict = example_data_dict(size=5085, keys=["area_um", "deform"])
104
119
  ds = dclab.new_dataset(ddict)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes