celldetective 1.3.5__py3-none-any.whl → 1.3.6.post2__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.
@@ -8,7 +8,7 @@ import os
8
8
  import json
9
9
  from stardist.models import StarDist2D
10
10
  from cellpose.models import CellposeModel
11
- from celldetective.io import locate_segmentation_model, auto_load_number_of_frames, load_frames
11
+ from celldetective.io import locate_segmentation_model, auto_load_number_of_frames, load_frames, extract_position_name
12
12
  from celldetective.utils import interpolate_nan, _estimate_scale_factor, _extract_channel_indices_from_config, ConfigSectionMap, _extract_nbr_channels_from_config, _get_img_num_per_channel
13
13
  from pathlib import Path, PurePath
14
14
  from glob import glob
@@ -44,6 +44,7 @@ if use_gpu=='True' or use_gpu=='true' or use_gpu=='1':
44
44
  n_threads = 1 # avoid misbehavior on GPU with multithreading
45
45
  else:
46
46
  use_gpu = False
47
+ #n_threads = 1 # force 1 threads since all CPUs seem to be in use anyway
47
48
 
48
49
  if not use_gpu:
49
50
  os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
@@ -60,20 +61,22 @@ parent1 = Path(pos).parent
60
61
  expfolder = parent1.parent
61
62
  config = PurePath(expfolder,Path("config.ini"))
62
63
  assert os.path.exists(config),'The configuration file for the experiment could not be located. Abort.'
64
+
65
+ print(f"Position: {extract_position_name(pos)}...")
63
66
  print("Configuration file: ",config)
67
+ print(f"Population: {mode}...")
64
68
 
65
69
  ####################################
66
70
  # Check model requirements #########
67
71
  ####################################
68
72
 
69
73
  modelpath = os.sep.join([os.path.split(os.path.dirname(os.path.realpath(__file__)))[0],"models"])
70
- print(modelpath)
71
74
  model_complete_path = locate_segmentation_model(modelname)
72
75
  if model_complete_path is None:
73
76
  print('Model could not be found. Abort.')
74
77
  os.abort()
75
78
  else:
76
- print(f'Model successfully located in {model_complete_path}')
79
+ print(f'Model path: {model_complete_path}...')
77
80
 
78
81
  # load config
79
82
  assert os.path.exists(model_complete_path+"config_input.json"),'The configuration for the inputs to the model could not be located. Abort.'
@@ -86,7 +89,7 @@ required_channels = input_config["channels"]
86
89
  channel_indices = _extract_channel_indices_from_config(config, required_channels)
87
90
  print(f'Required channels: {required_channels} located at channel indices {channel_indices}.')
88
91
  required_spatial_calibration = input_config['spatial_calibration']
89
- print(f'Expected spatial calibration is {required_spatial_calibration}.')
92
+ print(f'Spatial calibration expected by the model: {required_spatial_calibration}...')
90
93
 
91
94
  normalization_percentile = input_config['normalization_percentile']
92
95
  normalization_clip = input_config['normalization_clip']
@@ -117,18 +120,19 @@ if model_type=='cellpose':
117
120
  flow_threshold = input_config['flow_threshold']
118
121
 
119
122
  scale = _estimate_scale_factor(spatial_calibration, required_spatial_calibration)
120
- print(f"Scale = {scale}...")
123
+ print(f"Scale: {scale}...")
121
124
 
122
125
  nbr_channels = _extract_nbr_channels_from_config(config)
123
- print(f'Number of channels in the input movie: {nbr_channels}')
126
+ #print(f'Number of channels in the input movie: {nbr_channels}')
124
127
  img_num_channels = _get_img_num_per_channel(channel_indices, int(len_movie), nbr_channels)
125
128
 
126
129
  # If everything OK, prepare output, load models
127
- print('Erasing previous segmentation folder.')
128
130
  if os.path.exists(pos+label_folder):
131
+ print('Erasing the previous labels folder...')
129
132
  rmtree(pos+label_folder)
130
133
  os.mkdir(pos+label_folder)
131
- print(f'Folder {pos+label_folder} successfully generated.')
134
+ print(f'Labels folder successfully generated...')
135
+
132
136
  log=f'segmentation model: {modelname}\n'
133
137
  with open(pos+f'log_{mode}.json', 'a') as f:
134
138
  f.write(f'{datetime.datetime.now()} SEGMENT \n')
@@ -137,6 +141,7 @@ with open(pos+f'log_{mode}.json', 'a') as f:
137
141
 
138
142
  # Loop over all frames and segment
139
143
  def segment_index(indices):
144
+
140
145
  global scale
141
146
 
142
147
  if model_type=='stardist':
@@ -179,8 +184,7 @@ def segment_index(indices):
179
184
  f = np.moveaxis([interpolate_nan(f[:,:,c].copy()) for c in range(f.shape[-1])],0,-1)
180
185
 
181
186
  if np.any(img_num_channels[:,t]==-1):
182
- f[:,:,np.where(img_num_channels[:,t]==-1)[0]] = 0.
183
-
187
+ f[:,:,np.where(img_num_channels[:,t]==-1)[0]] = 0.
184
188
 
185
189
  if model_type=="stardist":
186
190
  Y_pred, details = model.predict_instances(f, n_tiles=model._guess_n_tiles(f), show_tile_progress=False, verbose=False)
@@ -206,6 +210,10 @@ def segment_index(indices):
206
210
  del Y_pred;
207
211
  gc.collect()
208
212
 
213
+ return
214
+
215
+
216
+ print(f"Starting the segmentation with {n_threads} thread(s) and GPU={use_gpu}...")
209
217
 
210
218
  import concurrent.futures
211
219
 
@@ -214,16 +222,12 @@ indices = list(range(img_num_channels.shape[1]))
214
222
  chunks = np.array_split(indices, n_threads)
215
223
 
216
224
  with concurrent.futures.ThreadPoolExecutor() as executor:
217
- executor.map(segment_index, chunks)
218
-
219
- # threads = []
220
- # for i in range(n_threads):
221
- # thread_i = threading.Thread(target=segment_index, args=[chunks[i]])
222
- # threads.append(thread_i)
223
- # for th in threads:
224
- # th.start()
225
- # for th in threads:
226
- # th.join()
225
+ results = executor.map(segment_index, chunks)
226
+ try:
227
+ for i,return_value in enumerate(results):
228
+ print(f"Thread {i} output check: ",return_value)
229
+ except Exception as e:
230
+ print("Exception: ", e)
227
231
 
228
232
  print('Done.')
229
233
 
@@ -5,7 +5,7 @@ Copright © 2022 Laboratoire Adhesion et Inflammation, Authored by Remy Torro.
5
5
  import argparse
6
6
  import os
7
7
  import json
8
- from celldetective.io import auto_load_number_of_frames, load_frames
8
+ from celldetective.io import auto_load_number_of_frames, load_frames, extract_position_name
9
9
  from celldetective.segmentation import segment_frame_from_thresholds
10
10
  from celldetective.utils import _extract_channel_indices_from_config, ConfigSectionMap, _extract_nbr_channels_from_config, _get_img_num_per_channel, extract_experiment_channels
11
11
  from pathlib import Path, PurePath
@@ -48,8 +48,6 @@ else:
48
48
  print('The configuration path is not valid. Abort.')
49
49
  os.abort()
50
50
 
51
- print('The following instructions were successfully loaded: ', threshold_instructions)
52
-
53
51
  if mode.lower()=="target" or mode.lower()=="targets":
54
52
  label_folder = "labels_targets"
55
53
  elif mode.lower()=="effector" or mode.lower()=="effectors":
@@ -60,12 +58,14 @@ parent1 = Path(pos).parent
60
58
  expfolder = parent1.parent
61
59
  config = PurePath(expfolder,Path("config.ini"))
62
60
  assert os.path.exists(config),'The configuration file for the experiment could not be located. Abort.'
63
- print("Configuration file: ",config)
64
61
 
62
+ print(f"Position: {extract_position_name(pos)}...")
63
+ print("Configuration file: ",config)
64
+ print(f"Population: {mode}...")
65
65
 
66
66
  channel_indices = _extract_channel_indices_from_config(config, required_channels)
67
67
  # need to abort if channel not found
68
- print(f'Required channels: {required_channels} located at channel indices {channel_indices}.')
68
+ print(f'Required channels: {required_channels} located at channel indices {channel_indices}...')
69
69
 
70
70
  threshold_instructions.update({'target_channel': channel_indices[0]})
71
71
 
@@ -86,15 +86,15 @@ if len_movie_auto is not None:
86
86
  len_movie = len_movie_auto
87
87
 
88
88
  nbr_channels = _extract_nbr_channels_from_config(config)
89
- print(f'Number of channels in the input movie: {nbr_channels}')
89
+ #print(f'Number of channels in the input movie: {nbr_channels}')
90
90
  img_num_channels = _get_img_num_per_channel(np.arange(nbr_channels), len_movie, nbr_channels)
91
91
 
92
92
  # If everything OK, prepare output, load models
93
- print('Erasing previous segmentation folder.')
94
93
  if os.path.exists(os.sep.join([pos,label_folder])):
94
+ print('Erasing the previous labels folder...')
95
95
  rmtree(os.sep.join([pos,label_folder]))
96
96
  os.mkdir(os.sep.join([pos,label_folder]))
97
- print(f'Folder {os.sep.join([pos,label_folder])} successfully generated.')
97
+ print(f'Labels folder successfully generated...')
98
98
 
99
99
  if equalize:
100
100
  f_reference = load_frames(img_num_channels[:,equalize_time], file, scale=None, normalize_input=False)
@@ -103,7 +103,7 @@ else:
103
103
  f_reference = None
104
104
 
105
105
  threshold_instructions.update({'equalize_reference': f_reference})
106
- print(threshold_instructions)
106
+ print(f"Instructions: {threshold_instructions}...")
107
107
 
108
108
  # Loop over all frames and segment
109
109
  def segment_index(indices):
@@ -119,6 +119,11 @@ def segment_index(indices):
119
119
  del mask;
120
120
  gc.collect()
121
121
 
122
+ return
123
+
124
+
125
+ print(f"Starting the segmentation with {n_threads} thread(s)...")
126
+
122
127
  import concurrent.futures
123
128
 
124
129
  # Multithreading
@@ -126,20 +131,15 @@ indices = list(range(img_num_channels.shape[1]))
126
131
  chunks = np.array_split(indices, n_threads)
127
132
 
128
133
  with concurrent.futures.ThreadPoolExecutor() as executor:
129
- executor.map(segment_index, chunks)
130
-
131
- # indices = list(range(img_num_channels.shape[1]))
132
- # chunks = np.array_split(indices, n_threads)
133
- # threads = []
134
- # for i in range(n_threads):
135
- # thread_i = threading.Thread(target=segment_index, args=[chunks[i]])
136
- # threads.append(thread_i)
137
- # for th in threads:
138
- # th.start()
139
- # for th in threads:
140
- # th.join()
134
+ results = executor.map(segment_index, chunks)
135
+ try:
136
+ for i,return_value in enumerate(results):
137
+ print(f"Thread {i} output check: ",return_value)
138
+ except Exception as e:
139
+ print("Exception: ", e)
141
140
 
142
141
  print('Done.')
142
+
143
143
  gc.collect()
144
144
 
145
145
 
@@ -6,7 +6,7 @@ import argparse
6
6
  import datetime
7
7
  import os
8
8
  import json
9
- from celldetective.io import auto_load_number_of_frames, load_frames, interpret_tracking_configuration
9
+ from celldetective.io import auto_load_number_of_frames, load_frames, interpret_tracking_configuration, extract_position_name
10
10
  from celldetective.utils import extract_experiment_channels, ConfigSectionMap, _get_img_num_per_channel, extract_experiment_channels
11
11
  from celldetective.measure import drop_tonal_features, measure_features
12
12
  from celldetective.tracking import track
@@ -59,6 +59,10 @@ expfolder = parent1.parent
59
59
  config = PurePath(expfolder,Path("config.ini"))
60
60
  assert os.path.exists(config),'The configuration file for the experiment could not be located. Abort.'
61
61
 
62
+ print(f"Position: {extract_position_name(pos)}...")
63
+ print("Configuration file: ",config)
64
+ print(f"Population: {mode}...")
65
+
62
66
  # from exp config fetch spatial calib, channel names
63
67
  movie_prefix = ConfigSectionMap(config,"MovieSettings")["movie_prefix"]
64
68
  spatial_calibration = float(ConfigSectionMap(config,"MovieSettings")["pxtoum"])
@@ -71,9 +75,10 @@ channel_names, channel_indices = extract_experiment_channels(config)
71
75
  nbr_channels = len(channel_names)
72
76
 
73
77
  # from tracking instructions, fetch btrack config, features, haralick, clean_traj, idea: fetch custom timeline?
78
+ print('Looking for tracking instruction file...')
74
79
  instr_path = PurePath(expfolder,Path(f"{instruction_file}"))
75
80
  if os.path.exists(instr_path):
76
- print(f"Tracking instructions for the {mode} population have been successfully loaded...")
81
+ print(f"Tracking instruction file successfully loaded...")
77
82
  with open(instr_path, 'r') as f:
78
83
  instructions = json.load(f)
79
84
  btrack_config = interpret_tracking_configuration(instructions['btrack_config_path'])
@@ -97,6 +102,16 @@ if os.path.exists(instr_path):
97
102
  post_processing_options = instructions['post_processing_options']
98
103
  else:
99
104
  post_processing_options = None
105
+
106
+ btrack_option = True
107
+ if 'btrack_option' in instructions:
108
+ btrack_option = instructions['btrack_option']
109
+ search_range = None
110
+ if 'search_range' in instructions:
111
+ search_range = instructions['search_range']
112
+ memory = None
113
+ if 'memory' in instructions:
114
+ memory = instructions['memory']
100
115
  else:
101
116
  print('Tracking instructions could not be located... Using a standard bTrack motion model instead...')
102
117
  btrack_config = interpret_tracking_configuration(None)
@@ -104,7 +119,9 @@ else:
104
119
  mask_channels = None
105
120
  haralick_options = None
106
121
  post_processing_options = None
107
-
122
+ btrack_option = True
123
+ memory = None
124
+ search_range = None
108
125
  if features is None:
109
126
  features = []
110
127
 
@@ -147,7 +164,15 @@ with open(pos+f'log_{mode}.json', 'a') as f:
147
164
  f.write(f'{datetime.datetime.now()} TRACK \n')
148
165
  f.write(log+"\n")
149
166
 
167
+
168
+ if not btrack_option:
169
+ features = []
170
+ channel_names = None
171
+ haralick_options = None
172
+
173
+
150
174
  def measure_index(indices):
175
+
151
176
  for t in tqdm(indices,desc="frame"):
152
177
 
153
178
  # Load channels at time t
@@ -160,24 +185,27 @@ def measure_index(indices):
160
185
  df_props.rename(columns={'centroid-1': 'x', 'centroid-0': 'y'},inplace=True)
161
186
  df_props['t'] = int(t)
162
187
  timestep_dataframes.append(df_props)
188
+ return
189
+
190
+
191
+
192
+ print(f"Measuring features with {n_threads} thread(s)...")
193
+
194
+ import concurrent.futures
163
195
 
164
196
  # Multithreading
165
197
  indices = list(range(img_num_channels.shape[1]))
166
198
  chunks = np.array_split(indices, n_threads)
167
199
 
168
- import concurrent.futures
169
-
170
200
  with concurrent.futures.ThreadPoolExecutor() as executor:
171
- executor.map(measure_index, chunks)
201
+ results = executor.map(measure_index, chunks)
202
+ try:
203
+ for i,return_value in enumerate(results):
204
+ print(f"Thread {i} output check: ",return_value)
205
+ except Exception as e:
206
+ print("Exception: ", e)
172
207
 
173
- # threads = []
174
- # for i in range(n_threads):
175
- # thread_i = threading.Thread(target=measure_index, args=[chunks[i]])
176
- # threads.append(thread_i)
177
- # for th in threads:
178
- # th.start()
179
- # for th in threads:
180
- # th.join()
208
+ print('Features successfully measured...')
181
209
 
182
210
  df = pd.concat(timestep_dataframes)
183
211
  df.reset_index(inplace=True, drop=True)
@@ -193,6 +221,13 @@ if mask_channels is not None:
193
221
  df = df.drop(cols_to_drop, axis=1)
194
222
 
195
223
  # do tracking
224
+ if btrack_option:
225
+ tracker = 'bTrack'
226
+ else:
227
+ tracker = 'trackpy'
228
+
229
+ print(f"Start the tracking step using the {tracker} tracker...")
230
+
196
231
  trajectories, napari_data = track(None,
197
232
  configuration=btrack_config,
198
233
  objects=df,
@@ -203,15 +238,18 @@ trajectories, napari_data = track(None,
203
238
  track_kwargs={'step_size': 100},
204
239
  clean_trajectories_kwargs=post_processing_options,
205
240
  volume=(shape_x, shape_y),
241
+ btrack_option=btrack_option,
242
+ search_range=search_range,
243
+ memory=memory,
206
244
  )
245
+ print(f"Tracking successfully performed...")
207
246
 
208
247
  # out trajectory table, create POSITION_X_um, POSITION_Y_um, TIME_min (new ones)
209
- # Save napari data
248
+ # Save napari data # deprecated, should disappear progressively
210
249
  np.save(pos+os.sep.join(['output', 'tables', napari_name]), napari_data, allow_pickle=True)
211
- print(f"napari data successfully saved in {pos+os.sep.join(['output', 'tables'])}")
212
250
 
213
251
  trajectories.to_csv(pos+os.sep.join(['output', 'tables', table_name]), index=False)
214
- print(f"Table {table_name} successfully saved in {os.sep.join(['output', 'tables'])}")
252
+ print(f"Trajectory table successfully exported in {os.sep.join(['output', 'tables'])}...")
215
253
 
216
254
  if os.path.exists(pos+os.sep.join(['output', 'tables', table_name.replace('.csv','.pkl')])):
217
255
  os.remove(pos+os.sep.join(['output', 'tables', table_name.replace('.csv','.pkl')]))
celldetective/tracking.py CHANGED
@@ -12,13 +12,14 @@ from celldetective.io import interpret_tracking_configuration
12
12
 
13
13
  import os
14
14
  import subprocess
15
+ import trackpy as tp
15
16
 
16
17
  abs_path = os.sep.join([os.path.split(os.path.dirname(os.path.realpath(__file__)))[0],'celldetective'])
17
18
 
18
19
  def track(labels, configuration=None, stack=None, spatial_calibration=1, features=None, channel_names=None,
19
20
  haralick_options=None, return_napari_data=False, view_on_napari=False, mask_timepoints=None, mask_channels=None, volume=(2048,2048),
20
21
  optimizer_options = {'tm_lim': int(12e4)}, track_kwargs={'step_size': 100}, objects=None,
21
- clean_trajectories_kwargs=None, column_labels={'track': "TRACK_ID", 'time': 'FRAME', 'x': 'POSITION_X', 'y': 'POSITION_Y'},
22
+ clean_trajectories_kwargs=None, btrack_option=True, search_range=None, memory=None,column_labels={'track': "TRACK_ID", 'time': 'FRAME', 'x': 'POSITION_X', 'y': 'POSITION_Y'},
22
23
  ):
23
24
 
24
25
  """
@@ -90,6 +91,12 @@ def track(labels, configuration=None, stack=None, spatial_calibration=1, feature
90
91
  configuration = interpret_tracking_configuration(configuration)
91
92
 
92
93
  if objects is None:
94
+
95
+ if not btrack_option:
96
+ features = []
97
+ channel_names = None
98
+ haralick_options = None
99
+
93
100
  objects = extract_objects_and_features(labels, stack, features,
94
101
  channel_names=channel_names,
95
102
  haralick_options=haralick_options,
@@ -97,63 +104,81 @@ def track(labels, configuration=None, stack=None, spatial_calibration=1, feature
97
104
  mask_channels=mask_channels,
98
105
  )
99
106
 
100
- columns = list(objects.columns)
101
- to_remove = ['x','y','class_id','t']
102
- for tr in to_remove:
103
- try:
104
- columns.remove(tr)
105
- except:
106
- print(f'column {tr} could not be found...')
107
-
108
- scaler = StandardScaler()
109
- if columns:
110
- x = objects[columns].values
111
- x_scaled = scaler.fit_transform(x)
112
- df_temp = pd.DataFrame(x_scaled, columns=columns, index = objects.index)
113
- objects[columns] = df_temp
114
- else:
115
- print('Warning: no features were passed to bTrack...')
107
+ if btrack_option:
108
+ columns = list(objects.columns)
109
+ to_remove = ['x','y','class_id','t']
110
+ for tr in to_remove:
111
+ try:
112
+ columns.remove(tr)
113
+ except:
114
+ print(f'column {tr} could not be found...')
116
115
 
117
- # 2) track the objects
118
- new_btrack_objects = localizations_to_objects(objects)
116
+ scaler = StandardScaler()
117
+ if columns:
118
+ x = objects[columns].values
119
+ x_scaled = scaler.fit_transform(x)
120
+ df_temp = pd.DataFrame(x_scaled, columns=columns, index = objects.index)
121
+ objects[columns] = df_temp
122
+ else:
123
+ print('Warning: no features were passed to bTrack...')
119
124
 
120
- with BayesianTracker() as tracker:
125
+ # 2) track the objects
126
+ new_btrack_objects = localizations_to_objects(objects)
121
127
 
122
- tracker.configure(configuration)
128
+ with BayesianTracker() as tracker:
123
129
 
124
- if columns:
125
- tracking_updates = ["motion","visual"]
126
- #tracker.tracking_updates = ["motion","visual"]
127
- tracker.features = columns
130
+ tracker.configure(configuration)
131
+
132
+ if columns:
133
+ tracking_updates = ["motion","visual"]
134
+ #tracker.tracking_updates = ["motion","visual"]
135
+ tracker.features = columns
136
+ else:
137
+ tracking_updates = ["motion"]
138
+
139
+ tracker.append(new_btrack_objects)
140
+ tracker.volume = ((0,volume[0]), (0,volume[1]), (-1e5, 1e5)) #(-1e5, 1e5)
141
+ #print(tracker.volume)
142
+ tracker.track(tracking_updates=tracking_updates, **track_kwargs)
143
+ tracker.optimize(options=optimizer_options)
144
+
145
+ data, properties, graph = tracker.to_napari() #ndim=2
146
+ # do the table post processing and napari options
147
+ if data.shape[1]==4:
148
+ df = pd.DataFrame(data, columns=[column_labels['track'],column_labels['time'],column_labels['y'],column_labels['x']])
149
+ elif data.shape[1]==5:
150
+ df = pd.DataFrame(data, columns=[column_labels['track'],column_labels['time'],"z",column_labels['y'],column_labels['x']])
151
+ df = df.drop(columns=['z'])
152
+ df[column_labels['x']+'_um'] = df[column_labels['x']]*spatial_calibration
153
+ df[column_labels['y']+'_um'] = df[column_labels['y']]*spatial_calibration
154
+
155
+ else:
156
+ properties = None
157
+ graph = {}
158
+ print(f"{objects=} {objects.columns=}")
159
+ objects = objects.rename(columns={"t": "frame"})
160
+ if search_range is not None and memory is not None:
161
+ data = tp.link(objects, search_range, memory=memory,link_strategy='auto')
128
162
  else:
129
- tracking_updates = ["motion"]
130
-
131
- tracker.append(new_btrack_objects)
132
- tracker.volume = ((0,volume[0]), (0,volume[1]), (-1e5, 1e5)) #(-1e5, 1e5)
133
- #print(tracker.volume)
134
- tracker.track(tracking_updates=tracking_updates, **track_kwargs)
135
- tracker.optimize(options=optimizer_options)
136
-
137
- data, properties, graph = tracker.to_napari() #ndim=2
138
-
139
- # do the table post processing and napari options
140
- if data.shape[1]==4:
141
- df = pd.DataFrame(data, columns=[column_labels['track'],column_labels['time'],column_labels['y'],column_labels['x']])
142
- elif data.shape[1]==5:
143
- df = pd.DataFrame(data, columns=[column_labels['track'],column_labels['time'],"z",column_labels['y'],column_labels['x']])
144
- df = df.drop(columns=['z'])
145
- df[column_labels['x']+'_um'] = df[column_labels['x']]*spatial_calibration
146
- df[column_labels['y']+'_um'] = df[column_labels['y']]*spatial_calibration
147
-
148
- df = df.merge(pd.DataFrame(properties),left_index=True, right_index=True)
149
- if columns:
150
- x = df[columns].values
151
- x_scaled = scaler.inverse_transform(x)
152
- df_temp = pd.DataFrame(x_scaled, columns=columns, index = df.index)
153
- df[columns] = df_temp
154
-
155
- # set dummy features to NaN
156
- df.loc[df['dummy'],['class_id']+columns] = np.nan
163
+ print('Please provide a valid search range and memory value...')
164
+ return None
165
+ data['particle'] = data['particle'] + 1 # force track id to start at 1
166
+ df = data.rename(columns={'frame': column_labels['time'], 'x': column_labels['x'], 'y': column_labels['y'], 'particle': column_labels['track']})
167
+ df['state'] = 5.0; df['generation'] = 0.0; df['root'] = 1.0; df['parent'] = 1.0; df['dummy'] = False; df['z'] = 0.0;
168
+ data = df[[column_labels['track'],column_labels['time'],"z",column_labels['y'],column_labels['x']]].to_numpy()
169
+ print(f"{df=}")
170
+
171
+ if btrack_option:
172
+ df = df.merge(pd.DataFrame(properties),left_index=True, right_index=True)
173
+ if columns:
174
+ x = df[columns].values
175
+ x_scaled = scaler.inverse_transform(x)
176
+ df_temp = pd.DataFrame(x_scaled, columns=columns, index = df.index)
177
+ df[columns] = df_temp
178
+
179
+ # set dummy features to NaN
180
+ df.loc[df['dummy'],['class_id']+columns] = np.nan
181
+
157
182
  df = df.sort_values(by=[column_labels['track'],column_labels['time']])
158
183
  df = velocity_per_track(df, window_size=3, mode='bi')
159
184
 
celldetective/utils.py CHANGED
@@ -424,7 +424,7 @@ def estimate_unreliable_edge(activation_protocol=[['gauss',2],['std',4]]):
424
424
  else:
425
425
  edge=0
426
426
  for fct in activation_protocol:
427
- if isinstance(fct[1],(int,np.int_)):
427
+ if isinstance(fct[1],(int,np.int_)) and not fct[0]=='invert':
428
428
  edge+=fct[1]
429
429
  return edge
430
430
 
@@ -1250,7 +1250,10 @@ def ConfigSectionMap(path,section):
1250
1250
  Config = configparser.ConfigParser()
1251
1251
  Config.read(path)
1252
1252
  dict1 = {}
1253
- options = Config.options(section)
1253
+ try:
1254
+ options = Config.options(section)
1255
+ except:
1256
+ return None
1254
1257
  for option in options:
1255
1258
  try:
1256
1259
  dict1[option] = Config.get(section, option)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: celldetective
3
- Version: 1.3.5
3
+ Version: 1.3.6.post2
4
4
  Summary: description
5
5
  Home-page: http://github.com/remyeltorro/celldetective
6
6
  Author: Rémy Torro
@@ -42,6 +42,7 @@ Requires-Dist: pytest-qt
42
42
  Requires-Dist: h5py
43
43
  Requires-Dist: cliffs_delta
44
44
  Requires-Dist: requests
45
+ Requires-Dist: trackpy
45
46
 
46
47
  # Celldetective
47
48