cellects 0.1.3__py3-none-any.whl → 0.2.6__py3-none-any.whl
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.
- cellects/__main__.py +65 -25
- cellects/config/all_vars_dict.py +18 -17
- cellects/core/cellects_threads.py +1034 -396
- cellects/core/motion_analysis.py +1664 -2010
- cellects/core/one_image_analysis.py +1082 -1061
- cellects/core/program_organizer.py +1687 -1316
- cellects/core/script_based_run.py +80 -76
- cellects/gui/advanced_parameters.py +365 -326
- cellects/gui/cellects.py +102 -91
- cellects/gui/custom_widgets.py +4 -3
- cellects/gui/first_window.py +226 -104
- cellects/gui/if_several_folders_window.py +117 -68
- cellects/gui/image_analysis_window.py +841 -450
- cellects/gui/required_output.py +100 -56
- cellects/gui/ui_strings.py +840 -0
- cellects/gui/video_analysis_window.py +317 -135
- cellects/image_analysis/cell_leaving_detection.py +64 -4
- cellects/image_analysis/image_segmentation.py +451 -22
- cellects/image_analysis/morphological_operations.py +2166 -1635
- cellects/image_analysis/network_functions.py +616 -253
- cellects/image_analysis/one_image_analysis_threads.py +94 -153
- cellects/image_analysis/oscillations_functions.py +131 -0
- cellects/image_analysis/progressively_add_distant_shapes.py +2 -3
- cellects/image_analysis/shape_descriptors.py +517 -466
- cellects/utils/formulas.py +169 -6
- cellects/utils/load_display_save.py +362 -105
- cellects/utils/utilitarian.py +86 -9
- cellects-0.2.6.dist-info/LICENSE +675 -0
- cellects-0.2.6.dist-info/METADATA +829 -0
- cellects-0.2.6.dist-info/RECORD +44 -0
- cellects/core/one_video_per_blob.py +0 -540
- cellects/image_analysis/cluster_flux_study.py +0 -102
- cellects-0.1.3.dist-info/LICENSE.odt +0 -0
- cellects-0.1.3.dist-info/METADATA +0 -176
- cellects-0.1.3.dist-info/RECORD +0 -44
- {cellects-0.1.3.dist-info → cellects-0.2.6.dist-info}/WHEEL +0 -0
- {cellects-0.1.3.dist-info → cellects-0.2.6.dist-info}/entry_points.txt +0 -0
- {cellects-0.1.3.dist-info → cellects-0.2.6.dist-info}/top_level.txt +0 -0
cellects/utils/formulas.py
CHANGED
|
@@ -28,6 +28,7 @@ Notes:
|
|
|
28
28
|
- Image processing functions expect binary (boolean/int8) input matrices
|
|
29
29
|
"""
|
|
30
30
|
from copy import deepcopy
|
|
31
|
+
import pandas as pd
|
|
31
32
|
from cellects.utils.decorators import njit
|
|
32
33
|
import numpy as np
|
|
33
34
|
from numpy.typing import NDArray
|
|
@@ -115,10 +116,22 @@ def bracket_to_uint8_image_contrast(image: NDArray):
|
|
|
115
116
|
-------
|
|
116
117
|
ndarray of uint8
|
|
117
118
|
Output image converted to uint8 type after normalization.
|
|
118
|
-
"""
|
|
119
|
-
image -= np.min(image)
|
|
120
|
-
return to_uint8(255 * (image / np.max(image)))
|
|
121
119
|
|
|
120
|
+
Examples
|
|
121
|
+
--------
|
|
122
|
+
>>> image = np.random.randint(0, 255, (10, 10), dtype=np.uint8)
|
|
123
|
+
>>> res = bracket_to_uint8_image_contrast(image)
|
|
124
|
+
>>> print(res)
|
|
125
|
+
|
|
126
|
+
>>> image = np.zeros((10, 10), dtype=np.uint8)
|
|
127
|
+
>>> res = bracket_to_uint8_image_contrast(image)
|
|
128
|
+
>>> print(res)
|
|
129
|
+
"""
|
|
130
|
+
image -= image.min()
|
|
131
|
+
if image.max() == 0:
|
|
132
|
+
return np.zeros_like(image, dtype=np.uint8)
|
|
133
|
+
else:
|
|
134
|
+
return to_uint8(255 * (image / np.max(image)))
|
|
122
135
|
|
|
123
136
|
@njit()
|
|
124
137
|
def linear_model(x: NDArray, a: float, b: float) -> float:
|
|
@@ -229,8 +242,11 @@ def get_var(mo: dict, binary_image: NDArray, Xn: NDArray, Yn: NDArray) -> Tuple[
|
|
|
229
242
|
-----
|
|
230
243
|
Performance considerations: This function uses Numba's `@njit` decorator for performance.
|
|
231
244
|
"""
|
|
232
|
-
|
|
233
|
-
|
|
245
|
+
if mo['m00'] == 0:
|
|
246
|
+
vx, vy = 0., 0.
|
|
247
|
+
else:
|
|
248
|
+
vx = np.sum(binary_image * Xn) / mo["m00"]
|
|
249
|
+
vy = np.sum(binary_image * Yn) / mo["m00"]
|
|
234
250
|
return vx, vy
|
|
235
251
|
|
|
236
252
|
|
|
@@ -277,7 +293,17 @@ def get_skewness_kurtosis(mnx: float, mny: float, sx: float, sy: float, n: int)
|
|
|
277
293
|
Kurtosis: nan
|
|
278
294
|
|
|
279
295
|
"""
|
|
280
|
-
|
|
296
|
+
if sx == 0:
|
|
297
|
+
fx = 0
|
|
298
|
+
else:
|
|
299
|
+
fx = mnx / sx ** n
|
|
300
|
+
|
|
301
|
+
if sy == 0:
|
|
302
|
+
fy = 0
|
|
303
|
+
else:
|
|
304
|
+
fy = mny / sy ** n
|
|
305
|
+
|
|
306
|
+
return fx, fy
|
|
281
307
|
|
|
282
308
|
|
|
283
309
|
def get_standard_deviations(mo: dict, binary_image: NDArray, cx: float, cy: float) -> Tuple[float, float]:
|
|
@@ -635,3 +661,140 @@ def find_duplicates_coord(array1: NDArray[int]) -> NDArray[bool]:
|
|
|
635
661
|
counts = np.bincount(inverse_indices)
|
|
636
662
|
# A row is duplicate if its count > 1
|
|
637
663
|
return counts[inverse_indices] > 1
|
|
664
|
+
|
|
665
|
+
def detect_first_move(size_dynamics: NDArray, growth_threshold)-> int:
|
|
666
|
+
"""
|
|
667
|
+
Detects the first move in a time series where the value exceeds the initial value by a given threshold.
|
|
668
|
+
|
|
669
|
+
Parameters
|
|
670
|
+
----------
|
|
671
|
+
size_dynamics : numpy.ndarray
|
|
672
|
+
The time series data of dynamics.
|
|
673
|
+
growth_threshold: int or float
|
|
674
|
+
The threshold value for detecting the first move.
|
|
675
|
+
|
|
676
|
+
Returns
|
|
677
|
+
-------
|
|
678
|
+
int or pandas.NA
|
|
679
|
+
The index of the first move where the condition is met.
|
|
680
|
+
Returns `pandas.NA` if no such index exists.
|
|
681
|
+
|
|
682
|
+
Examples
|
|
683
|
+
--------
|
|
684
|
+
>>> size_dynamics = np.array([10, 12, 15, 18])
|
|
685
|
+
>>> growth_threshold = 5
|
|
686
|
+
>>> detect_first_move(size_dynamics, growth_threshold)
|
|
687
|
+
2
|
|
688
|
+
"""
|
|
689
|
+
first_move = pd.NA
|
|
690
|
+
thresh_reached = np.nonzero(size_dynamics >= (size_dynamics[0] + growth_threshold))[0]
|
|
691
|
+
if len(thresh_reached) > 0:
|
|
692
|
+
first_move = thresh_reached[0]
|
|
693
|
+
return first_move
|
|
694
|
+
|
|
695
|
+
@njit()
|
|
696
|
+
def get_newly_explored_area(binary_vid: NDArray[np.uint8]) -> NDArray:
|
|
697
|
+
"""
|
|
698
|
+
Get newly explored area in a binary video.
|
|
699
|
+
|
|
700
|
+
Calculate the number of new pixels that have become active (==1) from
|
|
701
|
+
the previous frame in a binary video representation.
|
|
702
|
+
|
|
703
|
+
Parameters
|
|
704
|
+
----------
|
|
705
|
+
binary_vid : np.ndarray
|
|
706
|
+
The current frame of the binary video.
|
|
707
|
+
|
|
708
|
+
Returns
|
|
709
|
+
-------
|
|
710
|
+
np.ndarray
|
|
711
|
+
An array containing the number of new active pixels for each row.
|
|
712
|
+
|
|
713
|
+
Notes
|
|
714
|
+
-----
|
|
715
|
+
This function uses Numba's @njit decorator for performance.
|
|
716
|
+
|
|
717
|
+
Examples
|
|
718
|
+
--------
|
|
719
|
+
>>> binary_vid=np.zeros((4, 5, 5), dtype=np.uint8)
|
|
720
|
+
>>> binary_vid[:2, 3, 3] = 1
|
|
721
|
+
>>> binary_vid[1, 4, 3] = 1
|
|
722
|
+
>>> binary_vid[2, 3, 4] = 1
|
|
723
|
+
>>> binary_vid[3, 2, 3] = 1
|
|
724
|
+
>>> get_newly_explored_area(binary_vid)
|
|
725
|
+
array([0, 1, 1, 1])
|
|
726
|
+
|
|
727
|
+
>>> binary_vid=np.zeros((5, 5), dtype=np.uint8)[None, :, :]
|
|
728
|
+
>>> get_newly_explored_area(binary_vid)
|
|
729
|
+
array([0])
|
|
730
|
+
"""
|
|
731
|
+
return ((binary_vid - binary_vid[0, ...]) == 1).reshape(binary_vid.shape[0], - 1).sum(1)
|
|
732
|
+
|
|
733
|
+
def get_contour_width_from_im_shape(im_shape: Tuple) -> int:
|
|
734
|
+
"""
|
|
735
|
+
Calculate the contour width based on image shape.
|
|
736
|
+
|
|
737
|
+
Parameters
|
|
738
|
+
----------
|
|
739
|
+
im_shape : tuple of int, two items
|
|
740
|
+
The dimensions of the image.
|
|
741
|
+
|
|
742
|
+
Returns
|
|
743
|
+
-------
|
|
744
|
+
int
|
|
745
|
+
The calculated contour width.
|
|
746
|
+
"""
|
|
747
|
+
return np.max((np.round(np.log10(np.max(im_shape)) - 2).astype(int), 1))
|
|
748
|
+
|
|
749
|
+
def scale_coordinates(coord: NDArray, scale: Tuple, dims: Tuple) -> Tuple[NDArray[np.int64], np.int64, np.int64, np.int64, np.int64]:
|
|
750
|
+
"""
|
|
751
|
+
Scale coordinates based on given scale factors and dimensions.
|
|
752
|
+
|
|
753
|
+
Parameters
|
|
754
|
+
----------
|
|
755
|
+
coord : numpy.ndarray
|
|
756
|
+
A 2x2 array of coordinates to be scaled.
|
|
757
|
+
scale : tuple of float
|
|
758
|
+
Scaling factors for the x and y coordinates, respectively.
|
|
759
|
+
dims : tuple of int
|
|
760
|
+
Maximum dimensions (height, width) for the scaled coordinates.
|
|
761
|
+
|
|
762
|
+
Returns
|
|
763
|
+
-------
|
|
764
|
+
numpy.ndarray
|
|
765
|
+
Scaled and rounded coordinates.
|
|
766
|
+
int
|
|
767
|
+
Minimum y-coordinate.
|
|
768
|
+
int
|
|
769
|
+
Maximum y-coordinate.
|
|
770
|
+
int
|
|
771
|
+
Minimum x-coordinate.
|
|
772
|
+
int
|
|
773
|
+
Maximum x-coordinate.
|
|
774
|
+
|
|
775
|
+
Examples
|
|
776
|
+
--------
|
|
777
|
+
>>> coord = np.array(((47, 38), (59, 37)))
|
|
778
|
+
>>> scale = (0.92, 0.87)
|
|
779
|
+
>>> dims = (245, 300, 3)
|
|
780
|
+
>>> scaled_coord, min_y, max_y, min_x, max_x = scale_coordinates(coord, scale, dims)
|
|
781
|
+
>>> scaled_coord
|
|
782
|
+
array([[43, 33],
|
|
783
|
+
[54, 32]])
|
|
784
|
+
>>> min_y, max_y
|
|
785
|
+
(np.int64(43), np.int64(54))
|
|
786
|
+
>>> min_x, max_x
|
|
787
|
+
(np.int64(32), np.int64(33))
|
|
788
|
+
|
|
789
|
+
Notes
|
|
790
|
+
-----
|
|
791
|
+
This function assumes that the input coordinates are in a specific format
|
|
792
|
+
and will fail if not. The scaling factors should be positive.
|
|
793
|
+
"""
|
|
794
|
+
coord = np.array(((np.round(coord[0][0] * scale[0]), np.round(coord[0][1] * scale[1])),
|
|
795
|
+
(np.round(coord[1][0] * scale[0]), np.round(coord[1][1] * scale[1]))), dtype=np.int64)
|
|
796
|
+
min_y = np.max((0, np.min(coord[:, 0])))
|
|
797
|
+
max_y = np.min((dims[0], np.max(coord[:, 0])))
|
|
798
|
+
min_x = np.max((0, np.min(coord[:, 1])))
|
|
799
|
+
max_x = np.min((dims[1], np.max(coord[:, 1])))
|
|
800
|
+
return coord, min_y, max_y, min_x, max_x
|