dclab 0.63.1__tar.gz → 0.64.0__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 (332) hide show
  1. {dclab-0.63.1 → dclab-0.64.0}/CHANGELOG +15 -0
  2. {dclab-0.63.1 → dclab-0.64.0}/PKG-INFO +2 -2
  3. {dclab-0.63.1 → dclab-0.64.0}/dclab/_version.py +2 -2
  4. {dclab-0.63.1 → dclab-0.64.0}/dclab/http_utils.py +1 -1
  5. {dclab-0.63.1 → dclab-0.64.0}/dclab/kde/base.py +143 -5
  6. {dclab-0.63.1 → dclab-0.64.0}/dclab/kde/methods.py +10 -0
  7. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/core.py +13 -4
  8. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/export.py +8 -3
  9. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/feat_basin.py +138 -3
  10. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_dcor/api.py +70 -8
  11. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_dcor/base.py +103 -4
  12. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_dcor/logs.py +1 -1
  13. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_dcor/tables.py +1 -1
  14. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/writer.py +12 -4
  15. {dclab-0.63.1 → dclab-0.64.0}/dclab.egg-info/PKG-INFO +2 -2
  16. {dclab-0.63.1 → dclab-0.64.0}/dclab.egg-info/SOURCES.txt +3 -0
  17. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_dc_io.rst +19 -0
  18. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_scatter.rst +25 -25
  19. {dclab-0.63.1 → dclab-0.64.0}/pyproject.toml +1 -1
  20. dclab-0.64.0/tests/test_kde.py +101 -0
  21. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_copier.py +16 -4
  22. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_export_hdf5.py +23 -0
  23. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_feat_basin.py +3 -2
  24. dclab-0.64.0/tests/test_rtdc_feat_basin_perishable.py +236 -0
  25. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_fmt_dcor.py +84 -0
  26. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_fmt_dcor_basin.py +12 -0
  27. dclab-0.64.0/tests/test_rtdc_fmt_dcor_private.py +77 -0
  28. {dclab-0.63.1 → dclab-0.64.0}/.gitignore +0 -0
  29. {dclab-0.63.1 → dclab-0.64.0}/.readthedocs.yml +0 -0
  30. {dclab-0.63.1 → dclab-0.64.0}/LICENSE +0 -0
  31. {dclab-0.63.1 → dclab-0.64.0}/MANIFEST.in +0 -0
  32. {dclab-0.63.1 → dclab-0.64.0}/README.rst +0 -0
  33. {dclab-0.63.1 → dclab-0.64.0}/dclab/__init__.py +0 -0
  34. {dclab-0.63.1 → dclab-0.64.0}/dclab/cached.py +0 -0
  35. {dclab-0.63.1 → dclab-0.64.0}/dclab/cli/__init__.py +0 -0
  36. {dclab-0.63.1 → dclab-0.64.0}/dclab/cli/common.py +0 -0
  37. {dclab-0.63.1 → dclab-0.64.0}/dclab/cli/task_compress.py +0 -0
  38. {dclab-0.63.1 → dclab-0.64.0}/dclab/cli/task_condense.py +0 -0
  39. {dclab-0.63.1 → dclab-0.64.0}/dclab/cli/task_join.py +0 -0
  40. {dclab-0.63.1 → dclab-0.64.0}/dclab/cli/task_repack.py +0 -0
  41. {dclab-0.63.1 → dclab-0.64.0}/dclab/cli/task_split.py +0 -0
  42. {dclab-0.63.1 → dclab-0.64.0}/dclab/cli/task_tdms2rtdc.py +0 -0
  43. {dclab-0.63.1 → dclab-0.64.0}/dclab/cli/task_verify_dataset.py +0 -0
  44. {dclab-0.63.1 → dclab-0.64.0}/dclab/definitions/__init__.py +0 -0
  45. {dclab-0.63.1 → dclab-0.64.0}/dclab/definitions/feat_const.py +0 -0
  46. {dclab-0.63.1 → dclab-0.64.0}/dclab/definitions/feat_logic.py +0 -0
  47. {dclab-0.63.1 → dclab-0.64.0}/dclab/definitions/meta_const.py +0 -0
  48. {dclab-0.63.1 → dclab-0.64.0}/dclab/definitions/meta_logic.py +0 -0
  49. {dclab-0.63.1 → dclab-0.64.0}/dclab/definitions/meta_parse.py +0 -0
  50. {dclab-0.63.1 → dclab-0.64.0}/dclab/downsampling.pyx +0 -0
  51. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/__init__.py +0 -0
  52. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/packaging/LICENSE +0 -0
  53. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/packaging/LICENSE.APACHE +0 -0
  54. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/packaging/LICENSE.BSD +0 -0
  55. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/packaging/__init__.py +0 -0
  56. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/packaging/_structures.py +0 -0
  57. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/packaging/version.py +0 -0
  58. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/skimage/LICENSE +0 -0
  59. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/skimage/__init__.py +0 -0
  60. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/skimage/_find_contours.py +0 -0
  61. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/skimage/_find_contours_cy.pyx +0 -0
  62. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/skimage/_pnpoly.pyx +0 -0
  63. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/skimage/_shared/__init__.py +0 -0
  64. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/skimage/_shared/geometry.pxd +0 -0
  65. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/skimage/_shared/geometry.pyx +0 -0
  66. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/skimage/measure.py +0 -0
  67. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/skimage/pnpoly.py +0 -0
  68. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/statsmodels/LICENSE +0 -0
  69. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/statsmodels/__init__.py +0 -0
  70. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/statsmodels/nonparametric/__init__.py +0 -0
  71. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/statsmodels/nonparametric/_kernel_base.py +0 -0
  72. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/statsmodels/nonparametric/kernel_density.py +0 -0
  73. {dclab-0.63.1 → dclab-0.64.0}/dclab/external/statsmodels/nonparametric/kernels.py +0 -0
  74. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/__init__.py +0 -0
  75. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/bright.py +0 -0
  76. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/bright_bc.py +0 -0
  77. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/bright_perc.py +0 -0
  78. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/contour.py +0 -0
  79. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/emodulus/__init__.py +0 -0
  80. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/emodulus/load.py +0 -0
  81. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/emodulus/lut_HE-2D-FEM-22.txt +0 -0
  82. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/emodulus/lut_HE-3D-FEM-22.txt +0 -0
  83. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/emodulus/lut_LE-2D-FEM-19.txt +0 -0
  84. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/emodulus/pxcorr.py +0 -0
  85. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/emodulus/scale_linear.py +0 -0
  86. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/emodulus/viscosity.py +0 -0
  87. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/fl_crosstalk.py +0 -0
  88. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/inert_ratio.py +0 -0
  89. {dclab-0.63.1 → dclab-0.64.0}/dclab/features/volume.py +0 -0
  90. {dclab-0.63.1 → dclab-0.64.0}/dclab/isoelastics/__init__.py +0 -0
  91. {dclab-0.63.1 → dclab-0.64.0}/dclab/isoelastics/iso_HE-2D-FEM-22-area_um-deform.txt +0 -0
  92. {dclab-0.63.1 → dclab-0.64.0}/dclab/isoelastics/iso_HE-2D-FEM-22-volume-deform.txt +0 -0
  93. {dclab-0.63.1 → dclab-0.64.0}/dclab/isoelastics/iso_HE-3D-FEM-22-area_um-deform.txt +0 -0
  94. {dclab-0.63.1 → dclab-0.64.0}/dclab/isoelastics/iso_HE-3D-FEM-22-volume-deform.txt +0 -0
  95. {dclab-0.63.1 → dclab-0.64.0}/dclab/isoelastics/iso_LE-2D-FEM-19-area_um-deform.txt +0 -0
  96. {dclab-0.63.1 → dclab-0.64.0}/dclab/isoelastics/iso_LE-2D-FEM-19-volume-deform.txt +0 -0
  97. {dclab-0.63.1 → dclab-0.64.0}/dclab/isoelastics/iso_LE-2D-ana-18-area_um-deform.txt +0 -0
  98. {dclab-0.63.1 → dclab-0.64.0}/dclab/kde/__init__.py +0 -0
  99. {dclab-0.63.1 → dclab-0.64.0}/dclab/kde/contours.py +0 -0
  100. {dclab-0.63.1 → dclab-0.64.0}/dclab/kde_contours.py +0 -0
  101. {dclab-0.63.1 → dclab-0.64.0}/dclab/kde_methods.py +0 -0
  102. {dclab-0.63.1 → dclab-0.64.0}/dclab/lme4/__init__.py +0 -0
  103. {dclab-0.63.1 → dclab-0.64.0}/dclab/lme4/lme4_template.R +0 -0
  104. {dclab-0.63.1 → dclab-0.64.0}/dclab/lme4/rsetup.py +0 -0
  105. {dclab-0.63.1 → dclab-0.64.0}/dclab/lme4/wrapr.py +0 -0
  106. {dclab-0.63.1 → dclab-0.64.0}/dclab/polygon_filter.py +0 -0
  107. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/__init__.py +0 -0
  108. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/check.py +0 -0
  109. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/config.py +0 -0
  110. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/copier.py +0 -0
  111. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/feat_anc_core/__init__.py +0 -0
  112. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/feat_anc_core/af_basic.py +0 -0
  113. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/feat_anc_core/af_emodulus.py +0 -0
  114. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/feat_anc_core/af_fl_max_ctc.py +0 -0
  115. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/feat_anc_core/af_image_contour.py +0 -0
  116. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/feat_anc_core/af_ml_class.py +0 -0
  117. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/feat_anc_core/ancillary_feature.py +0 -0
  118. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/feat_anc_ml/__init__.py +0 -0
  119. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/feat_anc_plugin/__init__.py +0 -0
  120. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/feat_anc_plugin/plugin_feature.py +0 -0
  121. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/feat_temp.py +0 -0
  122. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/filter.py +0 -0
  123. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_dcor/__init__.py +0 -0
  124. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_dcor/access_token.py +0 -0
  125. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_dcor/basin.py +0 -0
  126. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_dict.py +0 -0
  127. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_hdf5/__init__.py +0 -0
  128. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_hdf5/base.py +0 -0
  129. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_hdf5/basin.py +0 -0
  130. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_hdf5/events.py +0 -0
  131. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_hdf5/feat_defect.py +0 -0
  132. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_hdf5/logs.py +0 -0
  133. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_hdf5/tables.py +0 -0
  134. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_hierarchy/__init__.py +0 -0
  135. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_hierarchy/base.py +0 -0
  136. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_hierarchy/events.py +0 -0
  137. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_hierarchy/hfilter.py +0 -0
  138. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_hierarchy/mapper.py +0 -0
  139. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_http.py +0 -0
  140. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_s3.py +0 -0
  141. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_tdms/__init__.py +0 -0
  142. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_tdms/event_contour.py +0 -0
  143. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_tdms/event_image.py +0 -0
  144. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_tdms/event_mask.py +0 -0
  145. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_tdms/event_trace.py +0 -0
  146. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_tdms/exc.py +0 -0
  147. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/fmt_tdms/naming.py +0 -0
  148. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/load.py +0 -0
  149. {dclab-0.63.1 → dclab-0.64.0}/dclab/rtdc_dataset/meta_table.py +0 -0
  150. {dclab-0.63.1 → dclab-0.64.0}/dclab/statistics.py +0 -0
  151. {dclab-0.63.1 → dclab-0.64.0}/dclab/util.py +0 -0
  152. {dclab-0.63.1 → dclab-0.64.0}/dclab/warn.py +0 -0
  153. {dclab-0.63.1 → dclab-0.64.0}/dclab.egg-info/dependency_links.txt +0 -0
  154. {dclab-0.63.1 → dclab-0.64.0}/dclab.egg-info/entry_points.txt +0 -0
  155. {dclab-0.63.1 → dclab-0.64.0}/dclab.egg-info/requires.txt +0 -0
  156. {dclab-0.63.1 → dclab-0.64.0}/dclab.egg-info/top_level.txt +0 -0
  157. {dclab-0.63.1 → dclab-0.64.0}/docs/.gitignore +0 -0
  158. {dclab-0.63.1 → dclab-0.64.0}/docs/README.md +0 -0
  159. {dclab-0.63.1 → dclab-0.64.0}/docs/conf.py +0 -0
  160. {dclab-0.63.1 → dclab-0.64.0}/docs/data/example.poly +0 -0
  161. {dclab-0.63.1 → dclab-0.64.0}/docs/data/example.rtdc +0 -0
  162. {dclab-0.63.1 → dclab-0.64.0}/docs/data/example_plugin.py +0 -0
  163. {dclab-0.63.1 → dclab-0.64.0}/docs/data/example_plugin_metadata.py +0 -0
  164. {dclab-0.63.1 → dclab-0.64.0}/docs/data/example_traces.rtdc +0 -0
  165. {dclab-0.63.1 → dclab-0.64.0}/docs/data/example_video.rtdc +0 -0
  166. {dclab-0.63.1 → dclab-0.64.0}/docs/dclab.bib +0 -0
  167. {dclab-0.63.1 → dclab-0.64.0}/docs/extensions/dclab_defs.py +0 -0
  168. {dclab-0.63.1 → dclab-0.64.0}/docs/extensions/fancy_include.py +0 -0
  169. {dclab-0.63.1 → dclab-0.64.0}/docs/extensions/github_changelog.py +0 -0
  170. {dclab-0.63.1 → dclab-0.64.0}/docs/extensions/simple_argparse.py +0 -0
  171. {dclab-0.63.1 → dclab-0.64.0}/docs/figures/DCOR_API_Token_website.png +0 -0
  172. {dclab-0.63.1 → dclab-0.64.0}/docs/index.rst +0 -0
  173. {dclab-0.63.1 → dclab-0.64.0}/docs/logo/dc_logo.png +0 -0
  174. {dclab-0.63.1 → dclab-0.64.0}/docs/logo/dc_logo.svg +0 -0
  175. {dclab-0.63.1 → dclab-0.64.0}/docs/logo/dclab.png +0 -0
  176. {dclab-0.63.1 → dclab-0.64.0}/docs/logo/dclab.svg +0 -0
  177. {dclab-0.63.1 → dclab-0.64.0}/docs/logo/dclab_large_white.png +0 -0
  178. {dclab-0.63.1 → dclab-0.64.0}/docs/logo/dclab_large_white.svg +0 -0
  179. {dclab-0.63.1 → dclab-0.64.0}/docs/logo/favicon.ico +0 -0
  180. {dclab-0.63.1 → dclab-0.64.0}/docs/logo/favicon.svg +0 -0
  181. {dclab-0.63.1 → dclab-0.64.0}/docs/requirements.txt +0 -0
  182. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_advanced_usage.rst +0 -0
  183. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_basins/basin_example_workflows.svg +0 -0
  184. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_basins/index.rst +0 -0
  185. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_dc_usage.rst +0 -0
  186. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_dcor.rst +0 -0
  187. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_emodulus/figures_emodulus/.gitignore +0 -0
  188. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_emodulus/figures_emodulus/emodulus_20um_HE-2D-FEM-22.png +0 -0
  189. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_emodulus/figures_emodulus/emodulus_20um_HE-3D-FEM-22.png +0 -0
  190. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_emodulus/figures_emodulus/emodulus_20um_LE-2D-FEM-19.png +0 -0
  191. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_emodulus/figures_emodulus/plot_emodulus_lut.py +0 -0
  192. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_emodulus/figures_emodulus/requirements.txt +0 -0
  193. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_emodulus/figures_viscosity/LICENSE +0 -0
  194. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_emodulus/figures_viscosity/buyukurganci_22_fig3a.jpg +0 -0
  195. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_emodulus/figures_viscosity/buyukurganci_22_fig3a.pdf +0 -0
  196. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_emodulus/index.rst +0 -0
  197. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_feat_plugin.rst +0 -0
  198. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_feat_temp.rst +0 -0
  199. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_fluorescence.rst +0 -0
  200. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_lme4.rst +0 -0
  201. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_notation.rst +0 -0
  202. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_av_s3.rst +0 -0
  203. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_changelog.rst +0 -0
  204. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_cli.rst +0 -0
  205. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_code_reference.rst +0 -0
  206. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_examples.rst +0 -0
  207. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_getting_started.rst +0 -0
  208. {dclab-0.63.1 → dclab-0.64.0}/docs/sec_z_bib.rst +0 -0
  209. {dclab-0.63.1 → dclab-0.64.0}/examples/emodulus_dcor.jpg +0 -0
  210. {dclab-0.63.1 → dclab-0.64.0}/examples/emodulus_dcor.py +0 -0
  211. {dclab-0.63.1 → dclab-0.64.0}/examples/generate_example_images.py +0 -0
  212. {dclab-0.63.1 → dclab-0.64.0}/examples/isoelastics.jpg +0 -0
  213. {dclab-0.63.1 → dclab-0.64.0}/examples/isoelastics.py +0 -0
  214. {dclab-0.63.1 → dclab-0.64.0}/examples/isoelastics_custom.jpg +0 -0
  215. {dclab-0.63.1 → dclab-0.64.0}/examples/isoelastics_custom.py +0 -0
  216. {dclab-0.63.1 → dclab-0.64.0}/examples/lme4_glmer_diff.py +0 -0
  217. {dclab-0.63.1 → dclab-0.64.0}/examples/lme4_lmer.jpg +0 -0
  218. {dclab-0.63.1 → dclab-0.64.0}/examples/lme4_lmer.py +0 -0
  219. {dclab-0.63.1 → dclab-0.64.0}/examples/overview_plot.jpg +0 -0
  220. {dclab-0.63.1 → dclab-0.64.0}/examples/overview_plot.py +0 -0
  221. {dclab-0.63.1 → dclab-0.64.0}/examples/plugin_example.py +0 -0
  222. {dclab-0.63.1 → dclab-0.64.0}/examples/plugin_usage.jpg +0 -0
  223. {dclab-0.63.1 → dclab-0.64.0}/examples/plugin_usage.py +0 -0
  224. {dclab-0.63.1 → dclab-0.64.0}/examples/viscosity_models.jpg +0 -0
  225. {dclab-0.63.1 → dclab-0.64.0}/examples/viscosity_models.py +0 -0
  226. {dclab-0.63.1 → dclab-0.64.0}/scripts/.gitignore +0 -0
  227. {dclab-0.63.1 → dclab-0.64.0}/scripts/README.md +0 -0
  228. {dclab-0.63.1 → dclab-0.64.0}/scripts/fem2iso_volume.py +0 -0
  229. {dclab-0.63.1 → dclab-0.64.0}/scripts/fem2lutiso_std.py +0 -0
  230. {dclab-0.63.1 → dclab-0.64.0}/scripts/fem2rtdc.py +0 -0
  231. {dclab-0.63.1 → dclab-0.64.0}/scripts/lut_recipes/__init__.py +0 -0
  232. {dclab-0.63.1 → dclab-0.64.0}/scripts/lut_recipes/hooks/LUT_analytical_linear-elastic_2Daxis.txt +0 -0
  233. {dclab-0.63.1 → dclab-0.64.0}/scripts/lut_recipes/hooks/README.md +0 -0
  234. {dclab-0.63.1 → dclab-0.64.0}/scripts/lut_recipes/hooks/__init__.py +0 -0
  235. {dclab-0.63.1 → dclab-0.64.0}/scripts/lut_recipes/hooks/common.py +0 -0
  236. {dclab-0.63.1 → dclab-0.64.0}/scripts/lut_recipes/hooks/he_2d_fem_22.py +0 -0
  237. {dclab-0.63.1 → dclab-0.64.0}/scripts/lut_recipes/hooks/he_3d_fem_22.py +0 -0
  238. {dclab-0.63.1 → dclab-0.64.0}/scripts/lut_recipes/hooks/le_2d_fem_19.py +0 -0
  239. {dclab-0.63.1 → dclab-0.64.0}/scripts/lut_recipes/lut_processor.py +0 -0
  240. {dclab-0.63.1 → dclab-0.64.0}/scripts/pixelation_correction.py +0 -0
  241. {dclab-0.63.1 → dclab-0.64.0}/scripts/pixelation_correction_2020.png +0 -0
  242. {dclab-0.63.1 → dclab-0.64.0}/scripts/pixelation_correction_2022.png +0 -0
  243. {dclab-0.63.1 → dclab-0.64.0}/scripts/requirements.txt +0 -0
  244. {dclab-0.63.1 → dclab-0.64.0}/setup.cfg +0 -0
  245. {dclab-0.63.1 → dclab-0.64.0}/setup.py +0 -0
  246. {dclab-0.63.1 → dclab-0.64.0}/tests/README.md +0 -0
  247. {dclab-0.63.1 → dclab-0.64.0}/tests/conftest.py +0 -0
  248. {dclab-0.63.1 → dclab-0.64.0}/tests/data/README.md +0 -0
  249. {dclab-0.63.1 → dclab-0.64.0}/tests/data/example_access_token.dcor-access +0 -0
  250. {dclab-0.63.1 → dclab-0.64.0}/tests/data/example_isoelastics.txt +0 -0
  251. {dclab-0.63.1 → dclab-0.64.0}/tests/data/feat_anc_plugin_creative.py +0 -0
  252. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-hdf5_fl-no-contour_2019.zip +0 -0
  253. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-hdf5_fl_2017.zip +0 -0
  254. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-hdf5_fl_2018.zip +0 -0
  255. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-hdf5_fl_wide-channel_2023.zip +0 -0
  256. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-hdf5_image-bg_2020.zip +0 -0
  257. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-hdf5_image-mask-blood_2021.zip +0 -0
  258. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-hdf5_mask-contour_2018.zip +0 -0
  259. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-hdf5_polygon_gate_2021.zip +0 -0
  260. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-hdf5_raw-cytoshot-exported.zip +0 -0
  261. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-hdf5_segfault-compound_2023.zip +0 -0
  262. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-hdf5_wide-channel_2023.zip +0 -0
  263. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-tdms_2fl-no-image_2017.zip +0 -0
  264. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-tdms_fl-image-bright_2017.zip +0 -0
  265. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-tdms_fl-image-large-fov_2017.zip +0 -0
  266. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-tdms_fl-image_2016.zip +0 -0
  267. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-tdms_fl_2015.zip +0 -0
  268. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-tdms_minimal_2016.zip +0 -0
  269. {dclab-0.63.1 → dclab-0.64.0}/tests/data/fmt-tdms_shapein-2.0.1-no-image_2017.zip +0 -0
  270. {dclab-0.63.1 → dclab-0.64.0}/tests/helper_methods.py +0 -0
  271. {dclab-0.63.1 → dclab-0.64.0}/tests/requirements.txt +0 -0
  272. {dclab-0.63.1 → dclab-0.64.0}/tests/test_cache.py +0 -0
  273. {dclab-0.63.1 → dclab-0.64.0}/tests/test_cli.py +0 -0
  274. {dclab-0.63.1 → dclab-0.64.0}/tests/test_cli_argparse.py +0 -0
  275. {dclab-0.63.1 → dclab-0.64.0}/tests/test_cli_compress.py +0 -0
  276. {dclab-0.63.1 → dclab-0.64.0}/tests/test_cli_condense.py +0 -0
  277. {dclab-0.63.1 → dclab-0.64.0}/tests/test_cli_join.py +0 -0
  278. {dclab-0.63.1 → dclab-0.64.0}/tests/test_cli_repack.py +0 -0
  279. {dclab-0.63.1 → dclab-0.64.0}/tests/test_cli_split.py +0 -0
  280. {dclab-0.63.1 → dclab-0.64.0}/tests/test_config_value_mapping.py +0 -0
  281. {dclab-0.63.1 → dclab-0.64.0}/tests/test_dfn.py +0 -0
  282. {dclab-0.63.1 → dclab-0.64.0}/tests/test_downsampling.py +0 -0
  283. {dclab-0.63.1 → dclab-0.64.0}/tests/test_feat_bright.py +0 -0
  284. {dclab-0.63.1 → dclab-0.64.0}/tests/test_feat_bright_bc.py +0 -0
  285. {dclab-0.63.1 → dclab-0.64.0}/tests/test_feat_bright_perc.py +0 -0
  286. {dclab-0.63.1 → dclab-0.64.0}/tests/test_feat_contour.py +0 -0
  287. {dclab-0.63.1 → dclab-0.64.0}/tests/test_feat_emodulus.py +0 -0
  288. {dclab-0.63.1 → dclab-0.64.0}/tests/test_feat_emodulus_viscosity.py +0 -0
  289. {dclab-0.63.1 → dclab-0.64.0}/tests/test_feat_fl_crosstalk.py +0 -0
  290. {dclab-0.63.1 → dclab-0.64.0}/tests/test_feat_inert_ratio.py +0 -0
  291. {dclab-0.63.1 → dclab-0.64.0}/tests/test_feat_volume.py +0 -0
  292. {dclab-0.63.1 → dclab-0.64.0}/tests/test_http_utils.py +0 -0
  293. {dclab-0.63.1 → dclab-0.64.0}/tests/test_isoelastics.py +0 -0
  294. {dclab-0.63.1 → dclab-0.64.0}/tests/test_kde_contours.py +0 -0
  295. {dclab-0.63.1 → dclab-0.64.0}/tests/test_kde_deprecations.py +0 -0
  296. {dclab-0.63.1 → dclab-0.64.0}/tests/test_kde_methods.py +0 -0
  297. {dclab-0.63.1 → dclab-0.64.0}/tests/test_lme4.py +0 -0
  298. {dclab-0.63.1 → dclab-0.64.0}/tests/test_lut_he_2d_fem_22.py +0 -0
  299. {dclab-0.63.1 → dclab-0.64.0}/tests/test_lut_he_3d_fem_22.py +0 -0
  300. {dclab-0.63.1 → dclab-0.64.0}/tests/test_polygon_contains.py +0 -0
  301. {dclab-0.63.1 → dclab-0.64.0}/tests/test_polygon_filter.py +0 -0
  302. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_check_dataset.py +0 -0
  303. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_config.py +0 -0
  304. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_core_feat.py +0 -0
  305. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_downsampling.py +0 -0
  306. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_export.py +0 -0
  307. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_export_avi.py +0 -0
  308. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_export_fcs.py +0 -0
  309. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_export_tsv.py +0 -0
  310. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_feat_anc_core.py +0 -0
  311. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_feat_anc_ml.py +0 -0
  312. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_feat_anc_plugin.py +0 -0
  313. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_feat_basin_mapped.py +0 -0
  314. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_feat_temp.py +0 -0
  315. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_filter.py +0 -0
  316. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_fmt_dcor_access_token.py +0 -0
  317. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_fmt_dict.py +0 -0
  318. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_fmt_hdf5.py +0 -0
  319. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_fmt_hdf5_basins.py +0 -0
  320. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_fmt_hdf5_basins_internal.py +0 -0
  321. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_fmt_hierarchy.py +0 -0
  322. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_fmt_http.py +0 -0
  323. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_fmt_http_basin.py +0 -0
  324. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_fmt_s3.py +0 -0
  325. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_fmt_s3_basin.py +0 -0
  326. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_fmt_tdms.py +0 -0
  327. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_hash.py +0 -0
  328. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_kde.py +0 -0
  329. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_limit_events.py +0 -0
  330. {dclab-0.63.1 → dclab-0.64.0}/tests/test_rtdc_writer.py +0 -0
  331. {dclab-0.63.1 → dclab-0.64.0}/tests/test_statistics.py +0 -0
  332. {dclab-0.63.1 → dclab-0.64.0}/tests/test_util.py +0 -0
@@ -1,3 +1,18 @@
1
+ 0.64.0
2
+ - feat: introduce concept of perishable (e.g. temporally expiring) basins
3
+ - feat: add `PerishableRecord` to presigned URLs for DCOR basins (#244)
4
+ - fix: do not export perishable basins (#254)
5
+ - fix: allow `Basin.verify_basin` to fail
6
+ - fix: `Basin.__repr__` failed when location did not exist
7
+ - fix: fetching tables information from DCOR dataset could time out
8
+ - fix: default to compression level 5 when exporting or writing (#272)
9
+ - enh: increase timeout every time fetching data from DCOR API times out
10
+ - docs: update docs `RTDCWriter` I/O
11
+ - setup: drop support for Python 3.8
12
+ - tests: add tests for fetching tables from a DCOR dataset (#229)
13
+ - ref: add `get_contour_lines` method to `KernelDensityEstimator` class
14
+ - ref: deprecate get_contour and use bin_width_doane_div5 in kde submodule
15
+ - ref: cache "basins" in `RTDC_DCOR` instead of in `RTDC_DCOR.api`
1
16
  0.63.1
2
17
  - docs: update documentation and code references for kde submodule
3
18
  - enh: cache S3 sessions and clients (test suite duration reduced by 30%)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dclab
3
- Version: 0.63.1
3
+ Version: 0.64.0
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>
@@ -14,7 +14,7 @@ Classifier: Operating System :: OS Independent
14
14
  Classifier: Programming Language :: Python :: 3
15
15
  Classifier: Topic :: Scientific/Engineering :: Visualization
16
16
  Classifier: Intended Audience :: Science/Research
17
- Requires-Python: <4,>=3.8
17
+ Requires-Python: <4,>=3.9
18
18
  Description-Content-Type: text/x-rst
19
19
  License-File: LICENSE
20
20
  Requires-Dist: h5py<4,>=3.0.0
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.63.1'
21
- __version_tuple__ = version_tuple = (0, 63, 1)
20
+ __version__ = version = '0.64.0'
21
+ __version_tuple__ = version_tuple = (0, 64, 0)
@@ -254,7 +254,7 @@ class ResoluteRequestsSession(requests.Session):
254
254
  break
255
255
  else:
256
256
  raise requests.exceptions.ReadTimeout(
257
- f"Resolut sesion failed for {args} and {kwargs}!")
257
+ f"Resolute session failed for {args} and {kwargs}!")
258
258
  return resp
259
259
 
260
260
 
@@ -2,7 +2,12 @@ import warnings
2
2
 
3
3
  import numpy as np
4
4
 
5
- from .methods import bin_width_doane, get_bad_vals, methods
5
+ from .methods import bin_width_doane_div5, get_bad_vals, methods
6
+ from .contours import find_contours_level, get_quantile_levels
7
+
8
+
9
+ class ContourSpacingTooLarge(UserWarning):
10
+ pass
6
11
 
7
12
 
8
13
  class KernelDensityEstimator:
@@ -107,6 +112,139 @@ class KernelDensityEstimator:
107
112
  yscale: str
108
113
  See `xscale`.
109
114
 
115
+ Returns
116
+ -------
117
+ X, Y, Z : coordinates
118
+ The kernel density Z evaluated on a rectangular grid (X,Y).
119
+ """
120
+ warnings.warn("`get_contour` is deprecated; please use "
121
+ "`get_raster` instead", DeprecationWarning)
122
+ return self.get_raster(
123
+ xax=xax, yax=yax, xacc=xacc, yacc=yacc,
124
+ kde_type=kde_type, kde_kwargs=kde_kwargs,
125
+ xscale=xscale, yscale=yscale
126
+ )
127
+
128
+ def get_contour_lines(self, quantiles=None, xax="area_um", yax="deform",
129
+ xacc=None, yacc=None, kde_type="histogram",
130
+ kde_kwargs=None, xscale="linear", yscale="linear",
131
+ ret_levels=False):
132
+ """Compute contour lines for a given kernel kensity estimate.
133
+
134
+ Parameters
135
+ ----------
136
+ quantiles: list or array of floats
137
+ KDE Quantiles for which contour levels are computed. The
138
+ values must be between 0 and 1. If set to None, use
139
+ [0.5, 0.95] as default.
140
+ xax: str
141
+ Identifier for X axis (e.g. "area_um", "aspect", "deform")
142
+ yax: str
143
+ Identifier for Y axis
144
+ xacc: float
145
+ Contour accuracy in x direction
146
+ if set to None, will use :func:`bin_width_doane_div5`
147
+ yacc: float
148
+ Contour accuracy in y direction
149
+ if set to None, will use :func:`bin_width_doane_div5`
150
+ kde_type: str
151
+ The KDE method to use
152
+ kde_kwargs: dict
153
+ Additional keyword arguments to the KDE method
154
+ xscale: str
155
+ If set to "log", take the logarithm of the x-values before
156
+ computing the KDE. This is useful when data are
157
+ displayed on a log-scale. Defaults to "linear".
158
+ yscale: str
159
+ See `xscale`
160
+ ret_levels: bool
161
+ If set to True, return the levels of the contours
162
+ (default: False)
163
+
164
+ Returns
165
+ -------
166
+ contour_lines: list of lists (of lists)
167
+ For every number in `quantiles`, this list contains a list of
168
+ corresponding contour lines. Each contour line is a 2D
169
+ array of shape (N, 2), where N is the number of points in the
170
+ contour line.
171
+ levels: list of floats
172
+ The density levels corresponding to each number in `quantiles`.
173
+ Only returned if `ret_levels` is set to True.
174
+ """
175
+ if not quantiles:
176
+ quantiles = [0.5, 0.95]
177
+ try:
178
+ x, y, density = self.get_raster(
179
+ xax=xax,
180
+ yax=yax,
181
+ xacc=xacc,
182
+ yacc=yacc,
183
+ xscale=xscale,
184
+ yscale=yscale,
185
+ kde_type=kde_type,
186
+ kde_kwargs=kde_kwargs,
187
+ )
188
+ except ValueError:
189
+ # most-likely there is nothing to compute a contour for
190
+ return []
191
+ if density.shape[0] < 3 or density.shape[1] < 3:
192
+ warnings.warn("Contour not possible; spacing may be too large!",
193
+ ContourSpacingTooLarge)
194
+ return []
195
+ levels = get_quantile_levels(
196
+ density=density,
197
+ x=x,
198
+ y=y,
199
+ xp=self.rtdc_ds[xax][self.rtdc_ds.filter.all],
200
+ yp=self.rtdc_ds[yax][self.rtdc_ds.filter.all],
201
+ q=np.array(quantiles),
202
+ normalize=False)
203
+ contours = []
204
+ # Normalize levels to [0, 1]
205
+ nlevels = np.array(levels) / density.max()
206
+ for nlev in nlevels:
207
+ # make sure that the contour levels are not at the boundaries
208
+ if not (np.allclose(nlev, 0, atol=1e-12, rtol=0)
209
+ or np.allclose(nlev, 1, atol=1e-12, rtol=0)):
210
+ cc = find_contours_level(
211
+ density, x=x, y=y, level=nlev)
212
+ contours.append(cc)
213
+ else:
214
+ contours.append([])
215
+ if ret_levels:
216
+ return contours, levels
217
+ else:
218
+ return contours
219
+
220
+ def get_raster(self, xax="area_um", yax="deform", xacc=None, yacc=None,
221
+ kde_type="histogram", kde_kwargs=None, xscale="linear",
222
+ yscale="linear"):
223
+ """Evaluate the kernel density estimate on a grid
224
+
225
+ Parameters
226
+ ----------
227
+ xax: str
228
+ Identifier for X axis (e.g. "area_um", "aspect", "deform")
229
+ yax: str
230
+ Identifier for Y axis
231
+ xacc: float
232
+ Contour accuracy in x direction
233
+ if set to None, will use :func:`bin_width_doane_div5`
234
+ yacc: float
235
+ Contour accuracy in y direction
236
+ if set to None, will use :func:`bin_width_doane_div5`
237
+ kde_type: str
238
+ The KDE method to use
239
+ kde_kwargs: dict
240
+ Additional keyword arguments to the KDE method
241
+ xscale: str
242
+ If set to "log", take the logarithm of the x-values before
243
+ computing the KDE. This is useful when data are
244
+ displayed on a log-scale. Defaults to "linear".
245
+ yscale: str
246
+ See `xscale`.
247
+
110
248
  Returns
111
249
  -------
112
250
  X, Y, Z : coordinates
@@ -128,21 +266,21 @@ class KernelDensityEstimator:
128
266
  a=x,
129
267
  feat=xax,
130
268
  scale=xscale,
131
- method=bin_width_doane,
269
+ method=bin_width_doane_div5,
132
270
  ret_scaled=True)
133
271
 
134
272
  yacc_sc, ys = self.get_spacing(
135
273
  a=y,
136
274
  feat=yax,
137
275
  scale=yscale,
138
- method=bin_width_doane,
276
+ method=bin_width_doane_div5,
139
277
  ret_scaled=True)
140
278
 
141
279
  if xacc is None or xacc == 0:
142
- xacc = xacc_sc / 5
280
+ xacc = xacc_sc
143
281
 
144
282
  if yacc is None or yacc == 0:
145
- yacc = yacc_sc / 5
283
+ yacc = yacc_sc
146
284
 
147
285
  # Ignore infs and nans
148
286
  bad = get_bad_vals(xs, ys)
@@ -56,6 +56,16 @@ def bin_width_doane(a):
56
56
  return acc
57
57
 
58
58
 
59
+ def bin_width_doane_div5(a):
60
+ """Compute contour spacing based on Doane's formula divided by five
61
+
62
+ See Also
63
+ --------
64
+ bin_width_doane: method used to compute the bin width
65
+ """
66
+ return bin_width_doane(a) / 5
67
+
68
+
59
69
  def bin_width_percentile(a):
60
70
  """Compute contour spacing based on data percentiles
61
71
 
@@ -635,7 +635,7 @@ class RTDCBase(abc.ABC):
635
635
  The kernel density Z evaluated on a rectangular grid (X,Y).
636
636
  """
637
637
  kde_instance = KernelDensityEstimator(rtdc_ds=self)
638
- xmesh, ymesh, density = kde_instance.get_contour(
638
+ xmesh, ymesh, density = kde_instance.get_raster(
639
639
  xax=xax, yax=yax, xacc=xacc, yacc=yacc, kde_type=kde_type,
640
640
  kde_kwargs=kde_kwargs, xscale=xscale, yscale=yscale
641
641
  )
@@ -746,6 +746,8 @@ class RTDCBase(abc.ABC):
746
746
  "ignored_basins": bd_keys,
747
747
  # basin key
748
748
  "key": bdict["key"],
749
+ # whether the basin is perishable or not
750
+ "perishable": bdict.get("perishable", False),
749
751
  }
750
752
 
751
753
  # Check whether this basin is supported and exists
@@ -783,12 +785,19 @@ class RTDCBase(abc.ABC):
783
785
  b_cls = bc[bdict["format"]]
784
786
  # Try absolute path
785
787
  bna = b_cls(pp, **kwargs)
786
- if bna.verify_basin():
787
- basins.append(bna)
788
- break
788
+
789
+ try:
790
+ absolute_exists = bna.verify_basin()
791
+ except BaseException:
792
+ pass
793
+ else:
794
+ if absolute_exists:
795
+ basins.append(bna)
796
+ break
789
797
  # Try relative path
790
798
  this_path = pathlib.Path(self.path)
791
799
  if this_path.exists():
800
+
792
801
  # Insert relative path
793
802
  bnr = b_cls(this_path.parent / pp, **kwargs)
794
803
  if bnr.verify_basin():
@@ -268,8 +268,8 @@ class Export(object):
268
268
  compression_kwargs: dict
269
269
  Dictionary with the keys "compression" and "compression_opts"
270
270
  which are passed to :func:`h5py.H5File.create_dataset`. The
271
- default is Zstandard compression with the lowest compression
272
- level `hdf5plugin.Zstd(clevel=1)`.
271
+ default is Zstandard compression with the compression
272
+ level 5 `hdf5plugin.Zstd(clevel=5)`.
273
273
  compression: str or None
274
274
  Compression method used for data storage;
275
275
  one of [None, "lzf", "gzip", "szip"].
@@ -300,7 +300,7 @@ class Export(object):
300
300
  # be backwards-compatible
301
301
  compression_kwargs = {"compression": compression}
302
302
  if compression_kwargs is None:
303
- compression_kwargs = hdf5plugin.Zstd(clevel=1)
303
+ compression_kwargs = hdf5plugin.Zstd(clevel=5)
304
304
  path = pathlib.Path(path)
305
305
  # Make sure that path ends with .rtdc
306
306
  if path.suffix not in [".rtdc", ".rtdc~"]:
@@ -505,6 +505,11 @@ class Export(object):
505
505
  # defined in. Since we are exporting, it does not
506
506
  # make sense to store these basins in the output file.
507
507
  continue
508
+ elif bn_dict.get("perishable"):
509
+ # Perishable basins require secret keys or complicated
510
+ # logic to execute in order to refresh them. We do not
511
+ # store them in the output file.
512
+ continue
508
513
  basinmap_orig = bn_dict.get("basin_map")
509
514
  if not filtered:
510
515
  # filtering disabled: just copy basins
@@ -6,9 +6,10 @@ which, when opened in dclab, can access features stored in the input file
6
6
  from __future__ import annotations
7
7
 
8
8
  import abc
9
+ import logging
9
10
  import numbers
10
11
  import threading
11
- from typing import Dict, List, Literal
12
+ from typing import Callable, Dict, List, Literal, Union
12
13
  import uuid
13
14
  import warnings
14
15
  import weakref
@@ -18,6 +19,9 @@ import numpy as np
18
19
  from ..util import copy_if_needed
19
20
 
20
21
 
22
+ logger = logging.getLogger(__name__)
23
+
24
+
21
25
  class BasinFeatureMissingWarning(UserWarning):
22
26
  """Used when a badin feature is defined but not stored"""
23
27
 
@@ -26,6 +30,10 @@ class CyclicBasinDependencyFoundWarning(UserWarning):
26
30
  """Used when a basin is defined in one of its sub-basins"""
27
31
 
28
32
 
33
+ class IgnoringPerishableBasinTTL(UserWarning):
34
+ """Used when refreshing a basin does not support TTL"""
35
+
36
+
29
37
  class BasinmapFeatureMissingError(KeyError):
30
38
  """Used when one of the `basinmap` features is not defined"""
31
39
  pass
@@ -47,6 +55,114 @@ class BasinAvailabilityChecker(threading.Thread):
47
55
  self.basin.is_available()
48
56
 
49
57
 
58
+ class PerishableRecord:
59
+ """A class containing information about perishable basins
60
+
61
+ Perishable basins are basins than may discontinue to work after
62
+ e.g. a specific amount of time (e.g. presigned S3 URLs). With the
63
+ `PerishableRecord`, these basins may be "refreshed" (made
64
+ available again).
65
+ """
66
+ def __init__(self,
67
+ basin,
68
+ expiration_func: Callable = None,
69
+ expiration_kwargs: Dict = None,
70
+ refresh_func: Callable = None,
71
+ refresh_kwargs: Dict = None,
72
+ ):
73
+ """
74
+ Parameters
75
+ ----------
76
+ basin: Basin
77
+ Instance of the perishable basin
78
+ expiration_func: callable
79
+ A function that determines whether the basin has perished.
80
+ It must accept `basin` as the first argument. Calling this
81
+ function should be fast, as it is called every time a feature
82
+ is accessed.
83
+ Note that if you are implementing this in the time domain, then
84
+ you should use `time.time()` (TSE), because you need an absolute
85
+ time measure. `time.monotonic()` for instance does not count up
86
+ when the system goes to sleep. However, keep in mind that if
87
+ a remote machine dictates the expiration time, then that
88
+ remote machine should also transmit the creation time (in case
89
+ there are time offsets).
90
+ expiration_kwargs: dict
91
+ Additional kwargs for `expiration_func`.
92
+ refresh_func: callable
93
+ The function used to refresh the `basin`. It must accept
94
+ `basin` as the first argument.
95
+ refresh_kwargs: dict
96
+ Additional kwargs for `refresh_func`
97
+ """
98
+ if not isinstance(basin, weakref.ProxyType):
99
+ basin = weakref.proxy(basin)
100
+ self.basin = basin
101
+ self.expiration_func = expiration_func
102
+ self.expiration_kwargs = expiration_kwargs or {}
103
+ self.refresh_func = refresh_func
104
+ self.refresh_kwargs = refresh_kwargs or {}
105
+
106
+ def __repr__(self):
107
+ state = "perished" if self.perished() else "valid"
108
+ return f"<PerishableRecord ({state}) at {hex(id(self))}>"
109
+
110
+ def perished(self) -> Union[bool, None]:
111
+ """Determine whether the basin has perished
112
+
113
+ Returns
114
+ -------
115
+ state: bool or None
116
+ True means the basin has perished, False means the basin
117
+ has not perished, and `None` means we don't know
118
+ """
119
+ if self.expiration_func is None:
120
+ return None
121
+ else:
122
+ return self.expiration_func(self.basin, **self.expiration_kwargs)
123
+
124
+ def refresh(self, extend_by: float = None) -> None:
125
+ """Extend the lifetime of the associated perishable basin
126
+
127
+ Parameters
128
+ ----------
129
+ extend_by: float
130
+ Custom argument for extending the life of the basin.
131
+ Normally, this would be a lifetime.
132
+
133
+ Returns
134
+ -------
135
+ basin: dict | None
136
+ Dictionary for instantiating a new basin
137
+ """
138
+ if self.refresh_func is None:
139
+ # The basin is a perishable basin, but we have no way of
140
+ # refreshing it.
141
+ logger.error(f"Cannot refresh basin '{self.basin}'")
142
+ return
143
+
144
+ if extend_by and "extend_by" not in self.refresh_kwargs:
145
+ warnings.warn(
146
+ "Parameter 'extend_by' ignored, because the basin "
147
+ "source does not support it",
148
+ IgnoringPerishableBasinTTL)
149
+ extend_by = None
150
+
151
+ rkw = {}
152
+ rkw.update(self.refresh_kwargs)
153
+
154
+ if extend_by is not None:
155
+ rkw["extend_by"] = extend_by
156
+
157
+ self.refresh_func(self.basin, **rkw)
158
+ logger.info(f"Refreshed basin '{self.basin}'")
159
+
160
+ # If everything went well, reset the current dataset of the basin
161
+ if self.basin._ds is not None:
162
+ self.basin._ds.close()
163
+ self.basin._ds = None
164
+
165
+
50
166
  class Basin(abc.ABC):
51
167
  """A basin represents data from an external source
52
168
 
@@ -76,6 +192,7 @@ class Basin(abc.ABC):
76
192
  mapping_referrer: Dict = None,
77
193
  ignored_basins: List[str] = None,
78
194
  key: str = None,
195
+ perishable=False,
79
196
  **kwargs):
80
197
  """
81
198
 
@@ -115,6 +232,10 @@ class Basin(abc.ABC):
115
232
  Unique key to identify this basin; normally computed from
116
233
  a JSON dump of the basin definition. A random string is used
117
234
  if None is specified.
235
+ perishable: bool or PerishableRecord
236
+ If this is not False, then it must be a :class:`.PerishableRecord`
237
+ that holds the information about the expiration time, and that
238
+ comes with a method `refresh` to extend the lifetime of the basin.
118
239
  kwargs:
119
240
  Additional keyword arguments passed to the `load_dataset`
120
241
  method of the `Basin` subclass.
@@ -130,7 +251,12 @@ class Basin(abc.ABC):
130
251
  self.name = name
131
252
  #: lengthy description of the basin
132
253
  self.description = description
133
- # defining key of the basin
254
+ # perishable record
255
+ if isinstance(perishable, bool) and perishable:
256
+ # Create an empty perishable record
257
+ perishable = PerishableRecord(self)
258
+ self.perishable = perishable
259
+ # define key of the basin
134
260
  self.key = key or str(uuid.uuid4())
135
261
  # features this basin provides
136
262
  self._features = features
@@ -164,10 +290,14 @@ class Basin(abc.ABC):
164
290
  self._av_check.start()
165
291
 
166
292
  def __repr__(self):
293
+ try:
294
+ feature_info = len(self.features)
295
+ except BaseException:
296
+ feature_info = "unknown"
167
297
  options = [
168
298
  self.name,
169
299
  f"mapped {self.mapping}" if self.mapping != "same" else "",
170
- f"features {self._features}" if self.features else "full-featured",
300
+ f"{feature_info} features",
171
301
  f"location {self.location}",
172
302
  ]
173
303
  opt_str = ", ".join([o for o in options if o])
@@ -220,6 +350,10 @@ class Basin(abc.ABC):
220
350
  @property
221
351
  def ds(self):
222
352
  """The :class:`.RTDCBase` instance represented by the basin"""
353
+ if self.perishable and self.perishable.perished():
354
+ # We have perished. Ask the PerishableRecord to refresh this
355
+ # basin so we can access it again.
356
+ self.perishable.refresh()
223
357
  if self._ds is None:
224
358
  if not self.is_available():
225
359
  raise BasinNotAvailableError(f"Basin {self} is not available!")
@@ -265,6 +399,7 @@ class Basin(abc.ABC):
265
399
  "basin_descr": self.description,
266
400
  "basin_feats": self.features,
267
401
  "basin_map": self.basinmap,
402
+ "perishable": bool(self.perishable),
268
403
  }
269
404
 
270
405
  def close(self):
@@ -11,8 +11,10 @@ class DCORAccessError(BaseException):
11
11
 
12
12
  class APIHandler:
13
13
  """Handles the DCOR api with caching for simple queries"""
14
- #: these are cached to minimize network usage
15
- cache_queries = ["basins", "metadata", "size", "feature_list", "valid"]
14
+ #: These are cached to minimize network usage
15
+ #: Note that we are not caching basins, since they may contain
16
+ #: expiring URLs.
17
+ cache_queries = ["metadata", "size", "feature_list", "valid"]
16
18
  #: DCOR API Keys/Tokens in the current session
17
19
  api_keys = []
18
20
 
@@ -52,8 +54,36 @@ class APIHandler:
52
54
  if api_key.strip() and api_key not in APIHandler.api_keys:
53
55
  APIHandler.api_keys.append(api_key)
54
56
 
55
- def _get(self, query, feat=None, trace=None, event=None, api_key="",
56
- retries=13):
57
+ def _get(self,
58
+ query: str,
59
+ feat: str = None,
60
+ trace: str = None,
61
+ event: str = None,
62
+ api_key: str = "",
63
+ timeout: float = None,
64
+ retries: int = 5):
65
+ """Fetch information via the DCOR API
66
+
67
+ Parameters
68
+ ----------
69
+ query: str
70
+ API route
71
+ feat: str
72
+ DEPRECATED (use basins instead), adds f"&feature={feat}" to query
73
+ trace: str
74
+ DEPRECATED (use basins instead), adds f"&trace={trace}" to query
75
+ event: str
76
+ DEPRECATED (use basins instead), adds f"&event={event}" to query
77
+ api_key: str
78
+ DCOR API token to use
79
+ timeout: float
80
+ Request timeout
81
+ retries: int
82
+ Number of retries to fetch the request. For every retry, the
83
+ timeout is increased by two seconds.
84
+ """
85
+ if timeout is None:
86
+ timeout = 1
57
87
  # "version=2" introduced in dclab 0.54.3
58
88
  # (supported since ckanext.dc_serve 0.13.2)
59
89
  qstr = f"&version={self.dcserv_api_version}&query={query}"
@@ -65,13 +95,13 @@ class APIHandler:
65
95
  qstr += f"&event={event}"
66
96
  apicall = self.url + qstr
67
97
  fail_reasons = []
68
- for _ in range(retries):
98
+ for ii in range(retries):
69
99
  try:
70
100
  # try-except both requests and json conversion
71
101
  req = self.session.get(apicall,
72
102
  headers={"Authorization": api_key},
73
103
  verify=self.verify,
74
- timeout=1,
104
+ timeout=timeout + ii * 2,
75
105
  )
76
106
  jreq = req.json()
77
107
  except requests.urllib3.exceptions.ConnectionError: # requests
@@ -92,13 +122,45 @@ class APIHandler:
92
122
  f"Messages: {fail_reasons}")
93
123
  return jreq
94
124
 
95
- def get(self, query, feat=None, trace=None, event=None):
125
+ def get(self,
126
+ query: str,
127
+ feat: str = None,
128
+ trace: str = None,
129
+ event: str = None,
130
+ timeout: float = None,
131
+ retries: int = 5,
132
+ ):
133
+ """Fetch information from DCOR
134
+
135
+ Parameters
136
+ ----------
137
+ query: str
138
+ API route
139
+ feat: str
140
+ DEPRECATED (use basins instead), adds f"&feature={feat}" to query
141
+ trace: str
142
+ DEPRECATED (use basins instead), adds f"&trace={trace}" to query
143
+ event: str
144
+ DEPRECATED (use basins instead), adds f"&event={event}" to query
145
+ timeout: float
146
+ Request timeout
147
+ retries: int
148
+ Number of retries to fetch the request. For every retry, the
149
+ timeout is increased by two seconds.
150
+ """
96
151
  if query in APIHandler.cache_queries and query in self._cache:
97
152
  result = self._cache[query]
98
153
  else:
99
154
  req = {"error": {"message": "No access to API (api key?)"}}
100
155
  for api_key in [self.api_key] + APIHandler.api_keys:
101
- req = self._get(query, feat, trace, event, api_key)
156
+ req = self._get(query=query,
157
+ feat=feat,
158
+ trace=trace,
159
+ event=event,
160
+ api_key=api_key,
161
+ timeout=timeout,
162
+ retries=retries,
163
+ )
102
164
  if req["success"]:
103
165
  self.api_key = api_key # remember working key
104
166
  break