fucciphase 0.0.2__py3-none-any.whl → 0.0.3__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.
- fucciphase/__init__.py +7 -1
- fucciphase/__main__.py +12 -0
- fucciphase/fucci_phase.py +97 -51
- fucciphase/io.py +16 -12
- fucciphase/main_cli.py +72 -9
- fucciphase/napari/tracks_to_napari.py +14 -16
- fucciphase/phase.py +77 -74
- fucciphase/plot.py +236 -87
- fucciphase/sensor.py +31 -31
- fucciphase/tracking_utilities.py +63 -8
- fucciphase/utils/__init__.py +14 -1
- fucciphase/utils/checks.py +2 -5
- fucciphase/utils/dtw.py +2 -4
- fucciphase/utils/normalize.py +6 -8
- fucciphase/utils/simulator.py +1 -1
- fucciphase/utils/track_postprocessing.py +6 -8
- fucciphase/utils/trackmate.py +12 -12
- fucciphase-0.0.3.dist-info/METADATA +238 -0
- fucciphase-0.0.3.dist-info/RECORD +25 -0
- {fucciphase-0.0.2.dist-info → fucciphase-0.0.3.dist-info}/WHEEL +1 -1
- fucciphase-0.0.2.dist-info/METADATA +0 -137
- fucciphase-0.0.2.dist-info/RECORD +0 -24
- {fucciphase-0.0.2.dist-info → fucciphase-0.0.3.dist-info}/entry_points.txt +0 -0
- {fucciphase-0.0.2.dist-info → fucciphase-0.0.3.dist-info}/licenses/LICENSE +0 -0
fucciphase/phase.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from enum import Enum
|
|
2
|
-
from typing import List
|
|
3
2
|
|
|
4
3
|
import dtaidistance.preprocessing
|
|
5
4
|
import numpy as np
|
|
@@ -99,45 +98,40 @@ class NewColumns(str, Enum):
|
|
|
99
98
|
|
|
100
99
|
def generate_cycle_phases(
|
|
101
100
|
df: pd.DataFrame,
|
|
102
|
-
channels:
|
|
101
|
+
channels: list[str],
|
|
103
102
|
sensor: FUCCISensor,
|
|
104
|
-
thresholds:
|
|
103
|
+
thresholds: list[float],
|
|
105
104
|
estimate_percentage: bool = False,
|
|
106
105
|
) -> None:
|
|
107
|
-
"""Add
|
|
106
|
+
"""Add cell-cycle phase (and optionally percentage) columns to the dataframe.
|
|
108
107
|
|
|
109
|
-
The phase is determined using
|
|
110
|
-
assuming a FUCCI sensor.
|
|
108
|
+
The phase is determined using thresholds on the normalized channel
|
|
109
|
+
intensities, assuming a FUCCI-like sensor. For each row (spot) in the
|
|
110
|
+
dataframe, this function:
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
1. Checks that normalized intensity columns exist for all requested channels.
|
|
113
|
+
2. Uses :func:`estimate_cell_phase_from_max_intensity` to assign a
|
|
114
|
+
discrete phase label based on whether each channel is ON/OFF.
|
|
115
|
+
3. Optionally calls :func:`estimate_cell_cycle_percentage` to estimate
|
|
116
|
+
a continuous cell-cycle percentage from the intensities and the
|
|
117
|
+
discrete phase.
|
|
113
118
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
The sensor needs to be calibrated for each cell line.
|
|
119
|
-
For that, record the FUCCI intensities of multiple cell cycles
|
|
120
|
-
by live-cell fluorescence microscopy.
|
|
121
|
-
See the examples for more details.
|
|
122
|
-
|
|
123
|
-
The thresholds need to be chosen based on the expected noise of the background and
|
|
124
|
-
uncertainty in intensity computation.
|
|
125
|
-
They give the ratio to the maximum intensity.
|
|
126
|
-
E.g., a threshold of 0.1 means that all intensities below 0.1 times the maximum
|
|
127
|
-
intensity are considered background signal.
|
|
119
|
+
The thresholds per channel must be between 0 and 1 and are interpreted
|
|
120
|
+
as fractions of the maximum intensity in that channel (e.g. 0.1 means
|
|
121
|
+
“10% of max”).
|
|
128
122
|
|
|
129
123
|
Parameters
|
|
130
124
|
----------
|
|
131
|
-
df :
|
|
132
|
-
Dataframe with columns holding normalized intensities
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
thresholds: List[float]
|
|
138
|
-
Thresholds to separate phases
|
|
139
|
-
estimate_percentage: bool
|
|
140
|
-
|
|
125
|
+
df : pandas.DataFrame
|
|
126
|
+
Dataframe with columns holding normalized intensities.
|
|
127
|
+
channels : List[str]
|
|
128
|
+
Names of normalized channels to use for phase estimation.
|
|
129
|
+
sensor : FUCCISensor
|
|
130
|
+
FUCCI sensor with phase-specific information.
|
|
131
|
+
thresholds : List[float]
|
|
132
|
+
Thresholds (0-1) used to separate phases.
|
|
133
|
+
estimate_percentage : bool, optional
|
|
134
|
+
If True, also estimate a continuous cell-cycle percentage.
|
|
141
135
|
|
|
142
136
|
|
|
143
137
|
Raises
|
|
@@ -163,7 +157,7 @@ def generate_cycle_phases(
|
|
|
163
157
|
# check that all channels are present
|
|
164
158
|
check_channels(sensor.fluorophores, channels)
|
|
165
159
|
|
|
166
|
-
# compute phases
|
|
160
|
+
# compute discrete phases based on normalized intensities
|
|
167
161
|
estimate_cell_phase_from_max_intensity(
|
|
168
162
|
df,
|
|
169
163
|
norm_channel_names,
|
|
@@ -172,28 +166,33 @@ def generate_cycle_phases(
|
|
|
172
166
|
thresholds=thresholds,
|
|
173
167
|
)
|
|
174
168
|
|
|
175
|
-
# name of
|
|
169
|
+
# name of phase column
|
|
176
170
|
phase_column = NewColumns.discrete_phase_max()
|
|
177
|
-
# compute percentages
|
|
171
|
+
# optionally compute continuous cell-cycle percentages
|
|
178
172
|
if estimate_percentage:
|
|
179
173
|
estimate_cell_cycle_percentage(df, norm_channel_names, sensor, phase_column)
|
|
180
174
|
|
|
181
175
|
|
|
182
176
|
def estimate_cell_cycle_percentage(
|
|
183
|
-
df: pd.DataFrame, channels:
|
|
177
|
+
df: pd.DataFrame, channels: list[str], sensor: FUCCISensor, phase_column: str
|
|
184
178
|
) -> None:
|
|
185
179
|
"""Estimate cell cycle percentage from intensity pairs.
|
|
186
180
|
|
|
181
|
+
For each row in the dataframe, this function reads the normalized
|
|
182
|
+
intensities in ``channels`` together with the discrete phase label in
|
|
183
|
+
``phase_column`` and queries the sensor for an estimated cell-cycle
|
|
184
|
+
percentage. The result is stored in the ``CELL_CYCLE_PERC`` column.
|
|
185
|
+
|
|
187
186
|
Parameters
|
|
188
187
|
----------
|
|
189
|
-
df :
|
|
190
|
-
Dataframe with columns
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
phase_column: str
|
|
196
|
-
Name of phase
|
|
188
|
+
df : pandas.DataFrame
|
|
189
|
+
Dataframe with normalized intensity columns and a phase column.
|
|
190
|
+
channels : List[str]
|
|
191
|
+
Names of normalized intensity columns for each fluorophore.
|
|
192
|
+
sensor : FUCCISensor
|
|
193
|
+
FUCCI sensor used to map intensities and phase to cycle percentage.
|
|
194
|
+
phase_column : str
|
|
195
|
+
Name of the column storing discrete phase labels.
|
|
197
196
|
"""
|
|
198
197
|
percentages = []
|
|
199
198
|
# iterate through data frame
|
|
@@ -210,39 +209,39 @@ def estimate_cell_cycle_percentage(
|
|
|
210
209
|
|
|
211
210
|
def estimate_cell_phase_from_max_intensity(
|
|
212
211
|
df: pd.DataFrame,
|
|
213
|
-
channels:
|
|
212
|
+
channels: list[str],
|
|
214
213
|
sensor: FUCCISensor,
|
|
215
|
-
background:
|
|
216
|
-
thresholds:
|
|
214
|
+
background: list[float],
|
|
215
|
+
thresholds: list[float],
|
|
217
216
|
) -> None:
|
|
218
|
-
"""
|
|
219
|
-
cycle, where the phase is determined by thresholding the channel intensities.
|
|
217
|
+
"""Estimate discrete cell-cycle phase by thresholding normalized intensities.
|
|
220
218
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
219
|
+
For each channel, the background value is subtracted from the mean
|
|
220
|
+
intensity. The resulting intensities are normalized by the maximum
|
|
221
|
+
mean intensity observed in that channel. A channel is considered ON
|
|
222
|
+
if its normalized intensity exceeds the corresponding threshold.
|
|
223
|
+
|
|
224
|
+
The ON/OFF pattern across channels is then mapped to a discrete phase
|
|
225
|
+
using the sensor model.
|
|
228
226
|
|
|
229
227
|
Parameters
|
|
230
228
|
----------
|
|
231
|
-
df:
|
|
232
|
-
Dataframe
|
|
233
|
-
channels: List[str]
|
|
234
|
-
Names of
|
|
235
|
-
sensor: FUCCISensor
|
|
236
|
-
FUCCI sensor with
|
|
237
|
-
background: List[float]
|
|
238
|
-
Single value per channel
|
|
239
|
-
thresholds: List[float]
|
|
240
|
-
Thresholds to separate phases
|
|
229
|
+
df : pandas.DataFrame
|
|
230
|
+
Dataframe containing the normalized intensity columns.
|
|
231
|
+
channels : List[str]
|
|
232
|
+
Names of normalized intensity columns.
|
|
233
|
+
sensor : FUCCISensor
|
|
234
|
+
FUCCI sensor with phase analysis information.
|
|
235
|
+
background : List[float]
|
|
236
|
+
Single background value per channel.
|
|
237
|
+
thresholds : List[float]
|
|
238
|
+
Thresholds (0-1) used to separate phases.
|
|
241
239
|
|
|
242
240
|
Raises
|
|
243
241
|
------
|
|
244
242
|
ValueError
|
|
245
|
-
If
|
|
243
|
+
If required channels are missing or if background/threshold lists
|
|
244
|
+
are inconsistent with the number of channels.
|
|
246
245
|
"""
|
|
247
246
|
# sanity check: check that channels are present
|
|
248
247
|
for channel in channels:
|
|
@@ -257,8 +256,10 @@ def estimate_cell_phase_from_max_intensity(
|
|
|
257
256
|
check_channels(sensor.fluorophores, channels)
|
|
258
257
|
check_thresholds(sensor.fluorophores, thresholds)
|
|
259
258
|
|
|
260
|
-
phase_markers_list:
|
|
261
|
-
for channel, bg_value, threshold in zip(
|
|
259
|
+
phase_markers_list: list[pd.Series[bool]] = []
|
|
260
|
+
for channel, bg_value, threshold in zip(
|
|
261
|
+
channels, background, thresholds, strict=True
|
|
262
|
+
):
|
|
262
263
|
# get intensities and subtract background
|
|
263
264
|
intensity = df[channel] - bg_value
|
|
264
265
|
# threshold channels to decide if ON / OFF (data is in list per spot)
|
|
@@ -275,10 +276,10 @@ def estimate_cell_phase_from_max_intensity(
|
|
|
275
276
|
|
|
276
277
|
def estimate_cell_phase_from_background(
|
|
277
278
|
df: pd.DataFrame,
|
|
278
|
-
channels:
|
|
279
|
+
channels: list[str],
|
|
279
280
|
sensor: FUCCISensor,
|
|
280
|
-
background:
|
|
281
|
-
thresholds:
|
|
281
|
+
background: list[float],
|
|
282
|
+
thresholds: list[float],
|
|
282
283
|
) -> None:
|
|
283
284
|
"""Add a column in place to the dataframe with the estimated phase of the cell
|
|
284
285
|
cycle, where the phase is determined by comparing the channel intensities to
|
|
@@ -319,8 +320,10 @@ def estimate_cell_phase_from_background(
|
|
|
319
320
|
|
|
320
321
|
check_channels(sensor.fluorophores, channels)
|
|
321
322
|
|
|
322
|
-
phase_markers_list:
|
|
323
|
-
for channel, bg_value, threshold in zip(
|
|
323
|
+
phase_markers_list: list[pd.Series[bool]] = []
|
|
324
|
+
for channel, bg_value, threshold in zip(
|
|
325
|
+
channels, background, thresholds, strict=True
|
|
326
|
+
):
|
|
324
327
|
intensity = df[channel]
|
|
325
328
|
# threshold channels to decide if ON / OFF (data is in list per spot)
|
|
326
329
|
phase_markers_list.append(intensity > threshold * bg_value)
|
|
@@ -337,7 +340,7 @@ def estimate_cell_phase_from_background(
|
|
|
337
340
|
def estimate_percentage_by_subsequence_alignment(
|
|
338
341
|
df: pd.DataFrame,
|
|
339
342
|
dt: float,
|
|
340
|
-
channels:
|
|
343
|
+
channels: list[str],
|
|
341
344
|
reference_data: pd.DataFrame,
|
|
342
345
|
smooth: float = 0.1,
|
|
343
346
|
penalty: float = 0.05,
|