celldetective 1.3.1__py3-none-any.whl → 1.3.3.post1__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.
Files changed (34) hide show
  1. celldetective/_version.py +1 -1
  2. celldetective/events.py +2 -0
  3. celldetective/gui/classifier_widget.py +51 -3
  4. celldetective/gui/control_panel.py +9 -3
  5. celldetective/gui/generic_signal_plot.py +161 -2
  6. celldetective/gui/gui_utils.py +90 -1
  7. celldetective/gui/measurement_options.py +35 -32
  8. celldetective/gui/plot_signals_ui.py +8 -3
  9. celldetective/gui/process_block.py +36 -114
  10. celldetective/gui/retrain_segmentation_model_options.py +3 -1
  11. celldetective/gui/signal_annotator.py +53 -26
  12. celldetective/gui/signal_annotator2.py +17 -30
  13. celldetective/gui/survival_ui.py +7 -3
  14. celldetective/gui/tableUI.py +300 -183
  15. celldetective/gui/thresholds_gui.py +195 -199
  16. celldetective/gui/viewers.py +267 -13
  17. celldetective/io.py +110 -10
  18. celldetective/measure.py +128 -88
  19. celldetective/models/segmentation_effectors/ricm_bf_all_last/config_input.json +79 -0
  20. celldetective/models/segmentation_effectors/ricm_bf_all_last/ricm_bf_all_last +0 -0
  21. celldetective/models/segmentation_effectors/ricm_bf_all_last/training_instructions.json +37 -0
  22. celldetective/models/segmentation_effectors/test-transfer/config_input.json +39 -0
  23. celldetective/models/segmentation_effectors/test-transfer/test-transfer +0 -0
  24. celldetective/neighborhood.py +154 -69
  25. celldetective/relative_measurements.py +128 -4
  26. celldetective/scripts/measure_cells.py +3 -3
  27. celldetective/signals.py +207 -213
  28. celldetective/utils.py +16 -0
  29. {celldetective-1.3.1.dist-info → celldetective-1.3.3.post1.dist-info}/METADATA +11 -10
  30. {celldetective-1.3.1.dist-info → celldetective-1.3.3.post1.dist-info}/RECORD +34 -29
  31. {celldetective-1.3.1.dist-info → celldetective-1.3.3.post1.dist-info}/WHEEL +1 -1
  32. {celldetective-1.3.1.dist-info → celldetective-1.3.3.post1.dist-info}/LICENSE +0 -0
  33. {celldetective-1.3.1.dist-info → celldetective-1.3.3.post1.dist-info}/entry_points.txt +0 -0
  34. {celldetective-1.3.1.dist-info → celldetective-1.3.3.post1.dist-info}/top_level.txt +0 -0
@@ -1169,202 +1169,198 @@ class ThresholdNormalisation(ThresholdConfigWizard):
1169
1169
  self.close()
1170
1170
 
1171
1171
 
1172
- class ThresholdSpot(ThresholdConfigWizard):
1173
- def __init__(self, current_channel, img, mask, parent_window=None):
1174
- QMainWindow.__init__(self)
1175
- self.parent_window = parent_window
1176
- self.screen_height = self.parent_window.parent_window.parent_window.parent_window.screen_height
1177
- self.screen_width = self.parent_window.parent_window.parent_window.parent_window.screen_width
1178
- self.setMinimumHeight(int(0.8 * self.screen_height))
1179
- self.setWindowTitle("Spot threshold preview")
1180
- center_window(self)
1181
- self.img = img
1182
- self.current_channel = current_channel
1183
- self.mode = self.parent_window.mode
1184
- self.pos = self.parent_window.parent_window.parent_window.pos
1185
- self.exp_dir = self.parent_window.parent_window.exp_dir
1186
- self.onlyFloat = QDoubleValidator()
1187
- self.onlyInt = QIntValidator()
1188
- self.soft_path = get_software_location()
1189
- self.auto_close = False
1190
-
1191
- if self.img is not None:
1192
- print(self.img.shape)
1193
- #self.test_frame = self.img
1194
- self.frame = self.img
1195
- self.test_mask = mask
1196
- self.populate_all()
1197
- self.setAttribute(Qt.WA_DeleteOnClose)
1198
- if self.auto_close:
1199
- self.close()
1200
-
1201
- def populate_left_panel(self):
1202
-
1203
- self.left_layout = QVBoxLayout()
1204
- diameter_layout=QHBoxLayout()
1205
- self.diameter_lbl = QLabel('Spot diameter: ')
1206
- self.diameter_value = QLineEdit()
1207
- self.diameter_value.setText(self.parent_window.diameter_value.text())
1208
- self.diameter_value.setValidator(self.onlyFloat)
1209
- diameter_layout.addWidget(self.diameter_lbl, alignment=Qt.AlignCenter)
1210
- diameter_layout.addWidget(self.diameter_value, alignment=Qt.AlignCenter)
1211
- self.left_layout.addLayout(diameter_layout)
1212
- threshold_layout=QHBoxLayout()
1213
- self.threshold_lbl = QLabel('Spot threshold: ')
1214
- self.threshold_value = QLineEdit()
1215
- self.threshold_value.setValidator(self.onlyFloat)
1216
- self.threshold_value.setText(self.parent_window.threshold_value.text())
1217
- threshold_layout.addWidget(self.threshold_lbl, alignment=Qt.AlignCenter)
1218
- threshold_layout.addWidget(self.threshold_value, alignment=Qt.AlignCenter)
1219
- self.left_layout.addLayout(threshold_layout)
1220
- self.left_panel.addLayout(self.left_layout)
1221
-
1222
- def enable_preview(self):
1223
-
1224
- diam = self.diameter_value.text().replace(',','').replace('.','')
1225
- thresh = self.threshold_value.text().replace(',','').replace('.','')
1226
- if diam.isnumeric() and thresh.isnumeric():
1227
- self.preview_button.setEnabled(True)
1228
- else:
1229
- self.preview_button.setEnabled(False)
1230
-
1231
- def draw_spot_preview(self):
1232
-
1233
- try:
1234
- diameter_value = float(self.parent_window.diameter_value.text().replace(',','.'))
1235
- except:
1236
- print('Diameter could not be converted to float... Abort.')
1237
- self.auto_close = True
1238
- return None
1239
-
1240
- try:
1241
- threshold_value = float(self.parent_window.threshold_value.text().replace(',','.'))
1242
- except:
1243
- print('Threshold could not be converted to float... Abort.')
1244
- self.auto_close = True
1245
- return None
1246
-
1247
- lbl = self.test_mask
1248
- blobs = self.blob_preview(image=self.img[:, :, self.current_channel], label=lbl, threshold=threshold_value,
1249
- diameter=diameter_value)
1250
- mask = np.array([lbl[int(y), int(x)] != 0 for y, x, r in blobs])
1251
- if np.any(mask):
1252
- blobs_filtered = blobs[mask]
1253
- else:
1254
- blobs_filtered=[]
1255
-
1256
- self.fig_contour, self.ax_contour = plt.subplots(figsize=(4, 6))
1257
- self.fcanvas = FigureCanvas(self.fig_contour, title="Blob measurement", interactive=True)
1258
- self.ax_contour.clear()
1259
- self.im = self.ax_contour.imshow(self.img[:, :, self.current_channel], cmap='gray')
1260
- self.circles = [Circle((x, y), r, color='red', fill=False, alpha=0.3) for y, x, r in blobs_filtered]
1261
- for circle in self.circles:
1262
- self.ax_contour.add_artist(circle)
1263
- self.ax_contour.set_xticks([])
1264
- self.ax_contour.set_yticks([])
1265
- self.fig_contour.set_facecolor('none') # or 'None'
1266
- self.fig_contour.canvas.setStyleSheet("background-color: transparent;")
1267
- self.fcanvas.canvas.draw()
1268
-
1269
- def populate_all(self):
1270
- self.button_widget = QWidget()
1271
- main_layout = QVBoxLayout()
1272
- self.button_widget.setLayout(main_layout)
1273
- self.right_panel = QVBoxLayout()
1274
- self.left_panel = QVBoxLayout()
1275
- self.left_panel.setContentsMargins(30, 30, 30, 30)
1276
- self.populate_left_panel()
1277
- self.draw_spot_preview()
1278
- self.setCentralWidget(self.button_widget)
1279
- contrast_slider_layout = QHBoxLayout()
1280
- self.contrast_slider = QLabeledDoubleRangeSlider()
1281
- self.contrast_slider.setSingleStep(0.00001)
1282
- self.contrast_slider.setTickInterval(0.00001)
1283
- self.contrast_slider.setOrientation(1)
1284
- selection = self.frame[:, :, self.current_channel]
1285
- self.contrast_slider.setRange(np.amin(selection[selection==selection]), np.amax(selection[selection==selection]))
1286
- self.contrast_slider.setValue(
1287
- [np.percentile(self.frame[:, :, self.current_channel].flatten(), 1), np.percentile(self.frame[:, :, self.current_channel].flatten(), 99.99)])
1288
- self.contrast_slider.valueChanged.connect(self.contrast_slider_action)
1289
- contrast_label = QLabel("Contrast: ")
1290
- contrast_slider_layout.addWidget(contrast_label)
1291
- contrast_slider_layout.addWidget(self.contrast_slider)
1292
- self.preview_button=QPushButton("Preview")
1293
- self.preview_button.clicked.connect(self.update_spots)
1294
- self.preview_button.setStyleSheet(self.button_style_sheet_2)
1295
- self.apply_changes=QPushButton("Apply")
1296
- self.apply_changes.setStyleSheet(self.button_style_sheet)
1297
- self.apply_changes.clicked.connect(self.apply)
1298
-
1299
- self.diameter_value.textChanged.connect(self.enable_preview)
1300
- self.threshold_value.textChanged.connect(self.enable_preview)
1301
-
1302
- self.right_panel.addWidget(self.fcanvas.canvas)
1303
- self.right_panel.addWidget(self.fcanvas.toolbar)
1304
-
1305
- main_layout.addLayout(self.right_panel)
1306
- main_layout.addLayout(self.left_panel)
1307
- main_layout.addLayout(contrast_slider_layout)
1308
- main_layout.addWidget(self.preview_button)
1309
- main_layout.addWidget(self.apply_changes)
1310
- self.show()
1311
-
1312
- def blob_preview(self, image, label, threshold, diameter):
1313
- removed_background = image.copy()
1314
- dilated_image = ndimage.grey_dilation(label, footprint=disk(10))
1315
- removed_background[np.where(dilated_image == 0)] = 0
1316
- min_sigma = (1 / (1 + math.sqrt(2))) * diameter
1317
- max_sigma = math.sqrt(2) * min_sigma
1318
- blobs = skimage.feature.blob_dog(removed_background, threshold=threshold, min_sigma=min_sigma,
1319
- max_sigma=max_sigma, overlap=0.75)
1320
- return blobs
1321
-
1322
- def update_spots(self):
1323
-
1324
- try:
1325
- diameter_value = float(self.diameter_value.text().replace(',','.'))
1326
- except:
1327
- print('Diameter could not be converted to float... Abort.')
1328
- return None
1329
-
1330
- try:
1331
- threshold_value = float(self.threshold_value.text().replace(',','.'))
1332
- except:
1333
- print('Threshold could not be converted to float... Abort.')
1334
- return None
1335
- xlim = self.ax_contour.get_xlim()
1336
- ylim = self.ax_contour.get_ylim()
1337
- contrast_levels = self.contrast_slider.value()
1338
- blobs = self.blob_preview(image=self.frame[:, :, self.current_channel], label=self.test_mask,
1339
- threshold=threshold_value,
1340
- diameter=diameter_value)
1341
- mask = np.array([self.test_mask[int(y), int(x)] != 0 for y, x, r in blobs])
1342
- if np.any(mask):
1343
- blobs_filtered = blobs[mask]
1344
- else:
1345
- blobs_filtered = []
1346
- self.ax_contour.clear()
1347
- self.im = self.ax_contour.imshow(self.frame[:, :, self.current_channel], cmap='gray')
1348
- self.ax_contour.set_xticks([])
1349
- self.ax_contour.set_yticks([])
1350
- self.circles = [Circle((x, y), r, color='red', fill=False, alpha=0.3) for y, x, r in blobs_filtered]
1351
- for circle in self.circles:
1352
- self.ax_contour.add_artist(circle)
1353
- self.ax_contour.set_xlim(xlim)
1354
- self.ax_contour.set_ylim(ylim)
1355
-
1356
- self.im.set_data(self.frame[:, :, self.current_channel])
1357
- self.fig_contour.canvas.draw()
1358
- self.contrast_slider.setValue(contrast_levels)
1359
-
1360
-
1361
-
1362
-
1363
- def apply(self):
1364
- self.parent_window.threshold_value.setText(self.threshold_value.text())
1365
- self.parent_window.diameter_value.setText(self.diameter_value.text())
1366
- self.close()
1367
-
1368
-
1369
-
1370
-
1172
+ # class ThresholdSpot(ThresholdConfigWizard):
1173
+ # def __init__(self, current_channel, img, mask, parent_window=None):
1174
+ # QMainWindow.__init__(self)
1175
+ # self.parent_window = parent_window
1176
+ # self.screen_height = self.parent_window.parent_window.parent_window.parent_window.screen_height
1177
+ # self.screen_width = self.parent_window.parent_window.parent_window.parent_window.screen_width
1178
+ # self.setMinimumHeight(int(0.8 * self.screen_height))
1179
+ # self.setWindowTitle("Spot threshold preview")
1180
+ # center_window(self)
1181
+ # self.img = img
1182
+ # self.current_channel = current_channel
1183
+ # self.mode = self.parent_window.mode
1184
+ # self.pos = self.parent_window.parent_window.parent_window.pos
1185
+ # self.exp_dir = self.parent_window.parent_window.exp_dir
1186
+ # self.onlyFloat = QDoubleValidator()
1187
+ # self.onlyInt = QIntValidator()
1188
+ # self.soft_path = get_software_location()
1189
+ # self.auto_close = False
1190
+
1191
+ # if self.img is not None:
1192
+ # print(self.img.shape)
1193
+ # #self.test_frame = self.img
1194
+ # self.frame = self.img
1195
+ # self.test_mask = mask
1196
+ # self.populate_all()
1197
+ # self.setAttribute(Qt.WA_DeleteOnClose)
1198
+ # if self.auto_close:
1199
+ # self.close()
1200
+
1201
+ # def populate_left_panel(self):
1202
+
1203
+ # self.left_layout = QVBoxLayout()
1204
+ # diameter_layout=QHBoxLayout()
1205
+ # self.diameter_lbl = QLabel('Spot diameter: ')
1206
+ # self.diameter_value = QLineEdit()
1207
+ # self.diameter_value.setText(self.parent_window.diameter_value.text())
1208
+ # self.diameter_value.setValidator(self.onlyFloat)
1209
+ # diameter_layout.addWidget(self.diameter_lbl, alignment=Qt.AlignCenter)
1210
+ # diameter_layout.addWidget(self.diameter_value, alignment=Qt.AlignCenter)
1211
+ # self.left_layout.addLayout(diameter_layout)
1212
+ # threshold_layout=QHBoxLayout()
1213
+ # self.threshold_lbl = QLabel('Spot threshold: ')
1214
+ # self.threshold_value = QLineEdit()
1215
+ # self.threshold_value.setValidator(self.onlyFloat)
1216
+ # self.threshold_value.setText(self.parent_window.threshold_value.text())
1217
+ # threshold_layout.addWidget(self.threshold_lbl, alignment=Qt.AlignCenter)
1218
+ # threshold_layout.addWidget(self.threshold_value, alignment=Qt.AlignCenter)
1219
+ # self.left_layout.addLayout(threshold_layout)
1220
+ # self.left_panel.addLayout(self.left_layout)
1221
+
1222
+ # def enable_preview(self):
1223
+
1224
+ # diam = self.diameter_value.text().replace(',','').replace('.','')
1225
+ # thresh = self.threshold_value.text().replace(',','').replace('.','')
1226
+ # if diam.isnumeric() and thresh.isnumeric():
1227
+ # self.preview_button.setEnabled(True)
1228
+ # else:
1229
+ # self.preview_button.setEnabled(False)
1230
+
1231
+ # def draw_spot_preview(self):
1232
+
1233
+ # try:
1234
+ # diameter_value = float(self.parent_window.diameter_value.text().replace(',','.'))
1235
+ # except:
1236
+ # print('Diameter could not be converted to float... Abort.')
1237
+ # self.auto_close = True
1238
+ # return None
1239
+
1240
+ # try:
1241
+ # threshold_value = float(self.parent_window.threshold_value.text().replace(',','.'))
1242
+ # except:
1243
+ # print('Threshold could not be converted to float... Abort.')
1244
+ # self.auto_close = True
1245
+ # return None
1246
+
1247
+ # lbl = self.test_mask
1248
+ # blobs = self.blob_preview(image=self.img[:, :, self.current_channel], label=lbl, threshold=threshold_value,
1249
+ # diameter=diameter_value)
1250
+ # mask = np.array([lbl[int(y), int(x)] != 0 for y, x, r in blobs])
1251
+ # if np.any(mask):
1252
+ # blobs_filtered = blobs[mask]
1253
+ # else:
1254
+ # blobs_filtered=[]
1255
+
1256
+ # self.fig_contour, self.ax_contour = plt.subplots(figsize=(4, 6))
1257
+ # self.fcanvas = FigureCanvas(self.fig_contour, title="Blob measurement", interactive=True)
1258
+ # self.ax_contour.clear()
1259
+ # self.im = self.ax_contour.imshow(self.img[:, :, self.current_channel], cmap='gray')
1260
+ # self.circles = [Circle((x, y), r, color='red', fill=False, alpha=0.3) for y, x, r in blobs_filtered]
1261
+ # for circle in self.circles:
1262
+ # self.ax_contour.add_artist(circle)
1263
+ # self.ax_contour.set_xticks([])
1264
+ # self.ax_contour.set_yticks([])
1265
+ # self.fig_contour.set_facecolor('none') # or 'None'
1266
+ # self.fig_contour.canvas.setStyleSheet("background-color: transparent;")
1267
+ # self.fcanvas.canvas.draw()
1268
+
1269
+ # def populate_all(self):
1270
+ # self.button_widget = QWidget()
1271
+ # main_layout = QVBoxLayout()
1272
+ # self.button_widget.setLayout(main_layout)
1273
+ # self.right_panel = QVBoxLayout()
1274
+ # self.left_panel = QVBoxLayout()
1275
+ # self.left_panel.setContentsMargins(30, 30, 30, 30)
1276
+ # self.populate_left_panel()
1277
+ # self.draw_spot_preview()
1278
+ # self.setCentralWidget(self.button_widget)
1279
+ # contrast_slider_layout = QHBoxLayout()
1280
+ # self.contrast_slider = QLabeledDoubleRangeSlider()
1281
+ # self.contrast_slider.setSingleStep(0.00001)
1282
+ # self.contrast_slider.setTickInterval(0.00001)
1283
+ # self.contrast_slider.setOrientation(1)
1284
+ # selection = self.frame[:, :, self.current_channel]
1285
+ # self.contrast_slider.setRange(np.amin(selection[selection==selection]), np.amax(selection[selection==selection]))
1286
+ # self.contrast_slider.setValue(
1287
+ # [np.percentile(self.frame[:, :, self.current_channel].flatten(), 1), np.percentile(self.frame[:, :, self.current_channel].flatten(), 99.99)])
1288
+ # self.contrast_slider.valueChanged.connect(self.contrast_slider_action)
1289
+ # contrast_label = QLabel("Contrast: ")
1290
+ # contrast_slider_layout.addWidget(contrast_label)
1291
+ # contrast_slider_layout.addWidget(self.contrast_slider)
1292
+ # self.preview_button=QPushButton("Preview")
1293
+ # self.preview_button.clicked.connect(self.update_spots)
1294
+ # self.preview_button.setStyleSheet(self.button_style_sheet_2)
1295
+ # self.apply_changes=QPushButton("Apply")
1296
+ # self.apply_changes.setStyleSheet(self.button_style_sheet)
1297
+ # self.apply_changes.clicked.connect(self.apply)
1298
+
1299
+ # self.diameter_value.textChanged.connect(self.enable_preview)
1300
+ # self.threshold_value.textChanged.connect(self.enable_preview)
1301
+
1302
+ # self.right_panel.addWidget(self.fcanvas.canvas)
1303
+ # self.right_panel.addWidget(self.fcanvas.toolbar)
1304
+
1305
+ # main_layout.addLayout(self.right_panel)
1306
+ # main_layout.addLayout(self.left_panel)
1307
+ # main_layout.addLayout(contrast_slider_layout)
1308
+ # main_layout.addWidget(self.preview_button)
1309
+ # main_layout.addWidget(self.apply_changes)
1310
+ # self.show()
1311
+
1312
+ # def blob_preview(self, image, label, threshold, diameter):
1313
+ # removed_background = image.copy()
1314
+ # dilated_image = ndimage.grey_dilation(label, footprint=disk(10))
1315
+ # removed_background[np.where(dilated_image == 0)] = 0
1316
+ # min_sigma = (1 / (1 + math.sqrt(2))) * diameter
1317
+ # max_sigma = math.sqrt(2) * min_sigma
1318
+ # blobs = skimage.feature.blob_dog(removed_background, threshold=threshold, min_sigma=min_sigma,
1319
+ # max_sigma=max_sigma, overlap=0.75)
1320
+ # return blobs
1321
+
1322
+ # def update_spots(self):
1323
+
1324
+ # try:
1325
+ # diameter_value = float(self.diameter_value.text().replace(',','.'))
1326
+ # except:
1327
+ # print('Diameter could not be converted to float... Abort.')
1328
+ # return None
1329
+
1330
+ # try:
1331
+ # threshold_value = float(self.threshold_value.text().replace(',','.'))
1332
+ # except:
1333
+ # print('Threshold could not be converted to float... Abort.')
1334
+ # return None
1335
+ # xlim = self.ax_contour.get_xlim()
1336
+ # ylim = self.ax_contour.get_ylim()
1337
+ # contrast_levels = self.contrast_slider.value()
1338
+ # blobs = self.blob_preview(image=self.frame[:, :, self.current_channel], label=self.test_mask,
1339
+ # threshold=threshold_value,
1340
+ # diameter=diameter_value)
1341
+ # mask = np.array([self.test_mask[int(y), int(x)] != 0 for y, x, r in blobs])
1342
+ # if np.any(mask):
1343
+ # blobs_filtered = blobs[mask]
1344
+ # else:
1345
+ # blobs_filtered = []
1346
+ # self.ax_contour.clear()
1347
+ # self.im = self.ax_contour.imshow(self.frame[:, :, self.current_channel], cmap='gray')
1348
+ # self.ax_contour.set_xticks([])
1349
+ # self.ax_contour.set_yticks([])
1350
+ # self.circles = [Circle((x, y), r, color='red', fill=False, alpha=0.3) for y, x, r in blobs_filtered]
1351
+ # for circle in self.circles:
1352
+ # self.ax_contour.add_artist(circle)
1353
+ # self.ax_contour.set_xlim(xlim)
1354
+ # self.ax_contour.set_ylim(ylim)
1355
+
1356
+ # self.im.set_data(self.frame[:, :, self.current_channel])
1357
+ # self.fig_contour.canvas.draw()
1358
+ # self.contrast_slider.setValue(contrast_levels)
1359
+
1360
+
1361
+
1362
+
1363
+ # def apply(self):
1364
+ # self.parent_window.threshold_value.setText(self.threshold_value.text())
1365
+ # self.parent_window.diameter_value.setText(self.diameter_value.text())
1366
+ # self.close()