deepliif 1.2.3__py3-none-any.whl → 1.2.4__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.
deepliif/util/__init__.py CHANGED
@@ -377,6 +377,104 @@ def adjust_background_tile(img):
377
377
  return image
378
378
 
379
379
 
380
+ def infer_background_colors(dir_data, sample_size=5, input_no=1, modalities_no=4,
381
+ seg_no=1, tile_size=32, return_list=False):
382
+ fns = [x for x in os.listdir(dir_data) if x.endswith('.png')]
383
+ sample_size = min(sample_size, len(fns))
384
+ w, h, num_img = None, None, None
385
+
386
+ background_colors = {}
387
+
388
+ count = 0
389
+ while count < sample_size and len(fns) > 0:
390
+ fn = fns.pop(0)
391
+ img = Image.open(f"{dir_data}/{fn}")
392
+
393
+ if w is None:
394
+ num_img = img.size[0] / img.size[1]
395
+ num_img = int(num_img)
396
+ w, h = img.size
397
+
398
+ background_colors_img = infer_background_colors_for_img(img, input_no=input_no, modalities_no=modalities_no, seg_no=seg_no, tile_size=tile_size, w=w, h=h, num_img=num_img)
399
+
400
+ if background_colors_img is not None:
401
+ count += 1
402
+ for mod_id, rgb_avg in background_colors_img.items():
403
+ try:
404
+ background_colors[mod_id].append(rgb_avg)
405
+ except:
406
+ background_colors[mod_id] = [rgb_avg]
407
+
408
+ if count > 0:
409
+ print(f'Calculating average color for empty tiles from {count} images..')
410
+ background_colors = {k:np.mean(v,axis=0).astype(np.uint8) for k,v in background_colors.items()}
411
+
412
+ if return_list:
413
+ return [tuple(e) for e in background_colors.values()]
414
+ else:
415
+ return background_colors
416
+ else:
417
+ print('None of the images have empty tiles for estimating averge background color. Try with a proper tile size.')
418
+ return None
419
+
420
+
421
+ def infer_background_colors_for_img(img, input_no=1, modalities_no=4, seg_no=1, tile_size=32,
422
+ w=None, h=None, num_img=None):
423
+ """
424
+ Estimate background colors for a given RGB image.
425
+ The empty tiles are determined by applying is_empty() function on segmentation modalities.
426
+ If multiple segmentation modalities present, only common empty tiles are used for background
427
+ color calculation.
428
+ """
429
+ from ..models import is_empty
430
+
431
+ if w is None:
432
+ num_img = img.size[0] / img.size[1]
433
+ num_img = int(num_img)
434
+ w, h = img.size
435
+
436
+ empty_tiles = {}
437
+ l_box = []
438
+ background_colors = {}
439
+
440
+ for i in range(num_img-seg_no, num_img):
441
+ img_mod = img.crop((h*i,0,h*(i+1),h))
442
+ l_box_mod = []
443
+ for x in range(0, h, tile_size):
444
+ for y in range(0, h, tile_size):
445
+ box = (x, y, x+tile_size, y+tile_size)
446
+ tile = img_mod.crop(box)
447
+ if is_empty(tile):
448
+ l_box_mod.append(box)
449
+ l_box.append(l_box_mod)
450
+
451
+ l_box_final = set()
452
+ if len(l_box) > 1:
453
+ # only keep overlapped boxes
454
+ for l in l_box:
455
+ l_box_final = l_box_final & set(l)
456
+ l_box_final = list(l_box_final)
457
+ else:
458
+ l_box_final = l_box[0]
459
+ #print(f'{len(l_box_final)} tiles are considered empty using segmentation modalities')
460
+
461
+ if len(l_box_final) == 0: # this can happen for images with dense cells
462
+ return None
463
+
464
+ for i in range(input_no, modalities_no+input_no):
465
+ empty_tiles[i] = []
466
+ img_mod = img.crop((h*i,0,h*(i+1),h))
467
+ for box in l_box_final:
468
+ tile = img_mod.crop(box)
469
+ empty_tiles[i].append(tile)
470
+
471
+ img_avg = np.mean(np.stack(empty_tiles[i], axis=0), axis=0) # take an average across all empty images
472
+ rgb_avg = np.mean(img_avg,axis=(0,1)).astype(np.uint8)
473
+ background_colors[i] = rgb_avg
474
+
475
+ return background_colors
476
+
477
+
380
478
  def image_variance_gray(img):
381
479
  px = np.asarray(img) if img.mode == 'L' else np.asarray(img.convert('L'))
382
480
  idx = np.logical_and(px != 255, px != 0)
@@ -531,7 +629,6 @@ class WSIReader:
531
629
 
532
630
 
533
631
 
534
-
535
632
  def write_results_to_pickle_file(output_addr, results):
536
633
  """
537
634
  This function writes data into the pickle file.
deepliif/util/util.py CHANGED
@@ -205,3 +205,88 @@ class HardwareStatus():
205
205
  self.timer.cancel()
206
206
 
207
207
 
208
+ def get_mod_id_seg(dir_model):
209
+ # assume we already know there are seg models - this check is intended to be done prior to calling this function
210
+ fns = [fn for fn in os.listdir(dir_model) if fn.endswith('.pth') and 'net_G' in fn]
211
+
212
+ if len(fns) == 0: # typically this means the directory only contains serialized models
213
+ fns = [fn for fn in os.listdir(dir_model) if fn.endswith('.pt') and fn.startswith('G')]
214
+ model_names = [fn[1:-3] for fn in fns] # 1[:-3] drop ".pt" and the starting G
215
+ else:
216
+ model_names = [fn[:-4].split('_')[2][1:] for fn in fns] # [1:] drop "G"
217
+
218
+ if len(fns) == 0:
219
+ raise Exception('Cannot find any model file ending with .pt or .pth in directory',dir_model)
220
+
221
+ model_name_seg = max(model_names, key=len)
222
+ return model_name_seg[0]
223
+
224
+ def get_input_id(dir_model):
225
+ # assume we already know there are seg models - this check is intended to be done prior to calling this function
226
+ fns = [fn for fn in os.listdir(dir_model) if fn.endswith('.pth') and 'net_G' in fn]
227
+
228
+ if len(fns) == 0: # typically this means the directory only contains serialized models
229
+ fns = [fn for fn in os.listdir(dir_model) if fn.endswith('.pt') and fn.startswith('G')]
230
+ model_names_seg = [fn[2:-3] for fn in fns] # [2:] drop "GS"/"G5"
231
+ else:
232
+ model_names_seg = [fn[:-4].split('_')[2][2:] for fn in fns] # [2:] drop "GS"/"G5"
233
+
234
+ if len(fns) == 0:
235
+ raise Exception('Cannot find any model file ending with .pt or .pth in directory',dir_model)
236
+
237
+ if '0' in model_names_seg:
238
+ return '0'
239
+ else:
240
+ return '1'
241
+
242
+ def init_input_and_mod_id(opt, dir_model=None):
243
+ """
244
+ Used by model classes to initialize input id and mod id under different situations.
245
+ """
246
+ mod_id_seg = None
247
+ input_id = None
248
+
249
+ if not opt.continue_train and opt.is_train:
250
+ if hasattr(opt,'mod_id_seg'): # use mod id seg from train opt file if available
251
+ mod_id_seg = opt.mod_id_seg
252
+ elif not hasattr(opt,'modalities_names'): # backward compatible with models trained before this param was introduced
253
+ mod_id_seg = opt.modalities_no + 1 # for original DeepLIIF, modalities_no is 4 and the seg mod id is 5
254
+ else:
255
+ mod_id_seg = 'S'
256
+
257
+ if opt.model in ['DeepLIIF','DeepLIIFKD']:
258
+ input_id = '0'
259
+ else: # for both continue train and test, we load existing models, so need to obtain seg mod id and input id from filenames
260
+ if hasattr(opt, 'mod_id_seg'):
261
+ mod_id_seg = opt.mod_id_seg
262
+ else:
263
+ # for contiue-training, extract mod id seg from existing files if not available
264
+ mod_id_seg = get_mod_id_seg(dir_model if dir_model is not None else os.path.join(opt.checkpoints_dir, opt.name))
265
+
266
+ if opt.model in ['DeepLIIF','DeepLIIFKD']:
267
+ input_id = get_input_id(dir_model if dir_model is not None else os.path.join(opt.checkpoints_dir, opt.name))
268
+
269
+ return mod_id_seg, input_id
270
+
271
+
272
+ import copy
273
+ def map_model_names(model_names,mod_id_seg_source,input_id_source,mod_id_seg_target,input_id_target):
274
+ """
275
+ Used for DeepLIIFKD to map model/image names from teacher model to student model,
276
+ when mod_id_seg and/or input_id is different.
277
+ """
278
+ d_res = {}
279
+ for model_name in model_names:
280
+ model_name_new = copy.deepcopy(model_name)
281
+ if len(model_name) > 2 and model_name[1] == mod_id_seg_source:
282
+ model_name_new = model_name[0]+mod_id_seg_target+model_name[2:] # replace mod id seg
283
+ if input_id_source != input_id_target: # currently only support 0 or 1 as input_id
284
+ if int(input_id_target) == 0:
285
+ model_name_new = model_name_new[:2] + str(int(model_name_new[2:])-1)
286
+ else:
287
+ model_name_new = model_name_new[:2] + str(int(model_name_new[2:])+1)
288
+ d_res[model_name] = model_name_new
289
+ # this is not a model name but the final aggregated segmentation image name
290
+ # so it cannot be obtained from model names
291
+ d_res['G'+mod_id_seg_source] = 'G'+mod_id_seg_target
292
+ return d_res
@@ -138,7 +138,7 @@ class Visualizer():
138
138
  print('Command: %s' % cmd)
139
139
  Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
140
140
 
141
- def display_current_results(self, visuals, epoch, save_result, **kwargs):
141
+ def display_current_results(self, visuals, epoch, save_result, filename=None, **kwargs):
142
142
  """Display current results on visdom; save current results to an HTML file.
143
143
 
144
144
  Parameters:
@@ -171,7 +171,7 @@ class Visualizer():
171
171
  table td {width: % dpx; height: % dpx; padding: 4px; outline: 4px solid black}
172
172
  </style>""" % (w, h) # create a table css
173
173
  # create a table of images.
174
- title = self.name
174
+ title = self.name if filename is None else filename
175
175
  label_html = ''
176
176
  label_html_row = ''
177
177
  images = []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: deepliif
3
- Version: 1.2.3
3
+ Version: 1.2.4
4
4
  Summary: DeepLIIF: Deep-Learning Inferred Multiplex Immunofluorescence for Immunohistochemical Image Quantification
5
5
  Home-page: https://github.com/nadeemlab/DeepLIIF
6
6
  Author: Parmida93
@@ -66,7 +66,7 @@ segmentation.*
66
66
 
67
67
  © This code is made available for non-commercial academic purposes.
68
68
 
69
- ![Version](https://img.shields.io/static/v1?label=latest&message=v1.2.3&color=darkgreen)
69
+ ![Version](https://img.shields.io/static/v1?label=latest&message=v1.2.4&color=darkgreen)
70
70
  [![Total Downloads](https://static.pepy.tech/personalized-badge/deepliif?period=total&units=international_system&left_color=grey&right_color=blue&left_text=total%20downloads)](https://pepy.tech/project/deepliif?&left_text=totalusers)
71
71
 
72
72
  ![overview_image](./images/overview.png)*Overview of DeepLIIF pipeline and sample input IHCs (different
@@ -1,9 +1,9 @@
1
- cli.py,sha256=luwzcSrRZMePfJ-h4Hgz2X7lYC70TUVxGfEo3LyPJgQ,58938
1
+ cli.py,sha256=hu-_-yO-ytr5gy3_Xd-kdZ7GdSUR_mISci7IE7nDKg0,63092
2
2
  deepliif/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- deepliif/postprocessing.py,sha256=Uu4axoOLgPgBgXxSVAgviuLi9cr4U_eE4KgFLbleMro,43512
3
+ deepliif/postprocessing.py,sha256=zMYlUeoz1tU7Cyd9VIxFez126CxBEcc1eBf6nFx-4Rg,43512
4
4
  deepliif/data/__init__.py,sha256=IfqVFnFSPQJZnORdRq4sNkJiylr1TaKNmhvWP_aLHdg,5492
5
5
  deepliif/data/aligned_dataset.py,sha256=CkKXj94ANSi8RdhpRQjVETFYlRMER2XErIf-87BStTE,5175
6
- deepliif/data/base_dataset.py,sha256=bQlxfY7bGSE9WPj31ZHkCxv5CAEJovjakGDCcK-aYdc,5564
6
+ deepliif/data/base_dataset.py,sha256=6ZEjIHDJ7f2JdjxZjbxu9QWnQDoIDmUQw4yPvLRmB2Y,5661
7
7
  deepliif/data/colorization_dataset.py,sha256=uDYWciSxwqZkStQ_Vte27D9x5FNhv6eR9wSPn39K3RY,2808
8
8
  deepliif/data/image_folder.py,sha256=eesP9vn__YQ-dw1KJG9J-yVUHMmJjLcIEQI552Iv2vE,2006
9
9
  deepliif/data/single_dataset.py,sha256=hWjqTkRESEMppZj_r8bi3G0hAZ5EfvXYgE_qRbpiEz4,1553
@@ -11,28 +11,28 @@ deepliif/data/template_dataset.py,sha256=PCDBnFRzRKReaeWgKUZmW0LrzRByI9adrKDJ6SN
11
11
  deepliif/data/unaligned_dataset.py,sha256=D69SxV087jKTd990UQIR4F3TahJHiSiw8i9Uz_xybt0,4697
12
12
  deepliif/models/CycleGAN_model.py,sha256=WDEa-Zgz57mVc9HbcVDXL5vfHvUDWdWXNLyz8ReH3rg,15196
13
13
  deepliif/models/DeepLIIFExt_model.py,sha256=HZaX9Z2ue0HQCFFN3guLkBcByCP70i8JvmPY02oOMyU,15022
14
- deepliif/models/DeepLIIFKD_model.py,sha256=edq9fxrDspGivuFlAYZp9B0Opp3BRIosA9e1TI_gxpc,27152
15
- deepliif/models/DeepLIIF_model.py,sha256=6vmsXcBcoALrhJLa7XGhDmLamO_WCzTDYEyVUBE482o,23857
14
+ deepliif/models/DeepLIIFKD_model.py,sha256=YMJrun6cGLyukRj4u3yvgm7Z1IOG1juxT11eyX25BRM,25985
15
+ deepliif/models/DeepLIIF_model.py,sha256=hMXE_6NuZvE8UxMrDSNGMFi_zBlW5VqBGj05qzSc5ec,30296
16
16
  deepliif/models/SDG_model.py,sha256=3opz7uEyhvVJ8fF4_Jw4ho1MBcc9OVye-ByZD_KF2j0,10142
17
- deepliif/models/__init__.py,sha256=FLMYnTyF4XvsSqN11df4a7dqFuB8-Nq4pQnTskL2DUE,34398
17
+ deepliif/models/__init__.py,sha256=l6z3aZneEA6ZwrmwDb4sS-FtKSntYNQJMVX0UNF0qTE,40409
18
18
  deepliif/models/att_unet.py,sha256=tqaFMNbGQUjXObOG309P76c7sIPxEvFR38EyuyHY40o,7116
19
- deepliif/models/base_model.py,sha256=ZQBI-wVfDdu296HzB_YzQraE9oUwfyRlAolNlrMi-4g,16858
19
+ deepliif/models/base_model.py,sha256=PNv_JwFQ1_u4MUfqTWd8IXr1JHf5_vLkCnIU3ePJftg,17116
20
20
  deepliif/models/networks.py,sha256=SclYeZ78U9ZSOhNrky764ZXB6muIqnHa6K0h_LDSCi0,36690
21
- deepliif/options/__init__.py,sha256=p2IWckf3-K-wclDWfSq5ZmynKk2lNov2Tn7WPYIO11A,8329
21
+ deepliif/options/__init__.py,sha256=TIPw7LuwvZ8yUTMBZNf3aLKM_jOiD9_REUx102oWjiQ,10336
22
22
  deepliif/options/base_options.py,sha256=m5UXY8MvjNcDisUWuiP228yoT27SsCh1bXS_Td6SwTc,9852
23
23
  deepliif/options/processing_options.py,sha256=OnNT-ytoTQzetFiMEKrWvrsrhZlupRK4smcnIk0MbqY,2947
24
24
  deepliif/options/test_options.py,sha256=4ZbQC5U-nTbUz8jvdDIbse5TK_mjw4D5yNjpVevWD5M,1114
25
25
  deepliif/options/train_options.py,sha256=5eA_oxpRj2-HiuMMvC5-HLapxNFG_JXOQ3K132JjpR8,3580
26
- deepliif/util/__init__.py,sha256=Vl_mUSCFLWZiX-eN9I-DBrbJlW29G8nPo8b5Je5pHnY,31582
26
+ deepliif/util/__init__.py,sha256=iqC3FvU7QDHdChZtf-nAaUzO61y02a7BiDmxpL679tc,35302
27
27
  deepliif/util/checks.py,sha256=xQirKbZxZErsAXc27M5miQUUyxptoIEJSDaUKv1nY7c,1371
28
28
  deepliif/util/get_data.py,sha256=HaRoQYb2u0LUgLT7ES-w35AmJ4BrlBEJWU4Cok29pxI,3749
29
29
  deepliif/util/html.py,sha256=RNAONZ4opP-bViahgmpSbHwOc6jXKQRnWRAVIaeIvac,3309
30
30
  deepliif/util/image_pool.py,sha256=M89Hc7DblRWroNP71S9mAdRn7h3DrhPFPjqFxxZYSgw,2280
31
- deepliif/util/util.py,sha256=WV2a1Rt-McmZm3BKW7TqC2oAKkvxWhZvjofGSfY6y7s,6810
32
- deepliif/util/visualizer.py,sha256=6E1sPbXdgLFB9mnPwtfEjm9O40viG4dfv5MyTpOQQpo,20210
33
- deepliif-1.2.3.dist-info/LICENSE.md,sha256=HlZw_UPS6EtJimJ_Ci7xKh-S5Iubs0Z8y8E6EZ3ZNyE,956
34
- deepliif-1.2.3.dist-info/METADATA,sha256=oQZ1gLKnysSKLZB98HB71yn-wAY8KWnpHb5uyOP2kbk,35266
35
- deepliif-1.2.3.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
36
- deepliif-1.2.3.dist-info/entry_points.txt,sha256=f70-10j2q68o_rDlsE3hspnv4ejlDnXwwGZ9JJ-3yF4,37
37
- deepliif-1.2.3.dist-info/top_level.txt,sha256=vLDK5YKmDz08E7PywuvEjAo7dM5rnIpsjR4c0ubQCnc,13
38
- deepliif-1.2.3.dist-info/RECORD,,
31
+ deepliif/util/util.py,sha256=l7QsUL8gSMJSGH5-Nin6IsjPl9HTyaKk8Z5cd-yuPjs,11055
32
+ deepliif/util/visualizer.py,sha256=BeRIEzbpx0YCn1_zFCtV1JHLMzyWed_nw65wiyKRlcc,20259
33
+ deepliif-1.2.4.dist-info/LICENSE.md,sha256=HlZw_UPS6EtJimJ_Ci7xKh-S5Iubs0Z8y8E6EZ3ZNyE,956
34
+ deepliif-1.2.4.dist-info/METADATA,sha256=dscN8jbrXPjEWzgs3q27L24ft2vqiDXiCcDoIKoN1Ac,35266
35
+ deepliif-1.2.4.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
36
+ deepliif-1.2.4.dist-info/entry_points.txt,sha256=f70-10j2q68o_rDlsE3hspnv4ejlDnXwwGZ9JJ-3yF4,37
37
+ deepliif-1.2.4.dist-info/top_level.txt,sha256=vLDK5YKmDz08E7PywuvEjAo7dM5rnIpsjR4c0ubQCnc,13
38
+ deepliif-1.2.4.dist-info/RECORD,,