MCPcopy Create free account
hub / github.com/AIRMEC/HECTOR / extract_save_features

Function extract_save_features

extract_features.py:576–642  ·  view source on GitHub ↗
(args)

Source from the content-addressed store, hash-verified

574 return np.asarray(features_), np.asarray(coords_)
575
576def extract_save_features(args):
577 # Derive the slide ID from its name.
578 slide_id, _ = os.path.splitext(os.path.basename(args.input_slide))
579 wip_file_path = os.path.join(args.output_dir, slide_id + "_wip.h5")
580 output_file_path = os.path.join(args.output_dir, slide_id + "_features.h5")
581
582 os.makedirs(args.output_dir, exist_ok=True)
583
584 # Check if the _features output file already exist. If so, we terminate to avoid
585 # overwriting it by accident. This also simplifies resuming bulk batch jobs.
586 if os.path.exists(output_file_path):
587 raise Exception(f"{output_file_path} already exists")
588
589 # Open the slide for reading.
590 wsi = openslide.open_slide(args.input_slide)
591
592 # Decide on which slide level we want to base the segmentation.
593 seg_level = wsi.get_best_level_for_downsample(64)
594
595 # Run the segmentation and tiling procedure.
596 start_time = time.time()
597 tissue_mask_scaled = create_tissue_mask(wsi, seg_level, method=args.method)
598 filtered_tiles = create_tissue_tiles(wsi, tissue_mask_scaled, args.tile_size)
599
600 # Build a figure for quality control purposes, to check if the tiles are where we expect them.
601 qc_img = make_tile_QC_fig(filtered_tiles, wsi, seg_level, 2)
602 qc_img_target_width = 1920
603 qc_img = qc_img.resize((qc_img_target_width, int(qc_img.height / (qc_img.width / qc_img_target_width))))
604 qc_img_file_path = os.path.join(args.output_dir, f"{slide_id}_features_QC.png")
605 qc_img.save(qc_img_file_path)
606 print(f"Finished creating {len(filtered_tiles)} tissue tiles in {time.time() - start_time}s")
607
608 # Save QC figure.
609 qc_img_file_path = os.path.join(
610 args.output_dir, f"{slide_id}_N{len(mergedpatches)}mergedpatches_distThreshold{args.dist_threshold}_corrThreshold{args.corr_threshold}.png"
611 )
612
613 # Extract the rectangles, and compute the feature vectors. Example using EsVIT.
614 device = torch.device("cuda")
615 model, _, depths = load_encoder_esVIT(args, device)
616
617 features, coords = extract_features(
618 model,
619 device,
620 wsi,
621 filtered_tiles,
622 args.workers,
623 args.out_size,
624 args.batch_size,
625 n_last_blocks = args.n_last_blocks,
626 avgpool_patchtokens = args.avgpool_patchtokens,
627 depths = depths,
628 )
629
630 print(f'Number of features N={len(features)}')
631 # Merging nearby patches with similar semantic.
632 mergedpatches = mergedpatch_gen(features, coords, dist_threshold=args.dist_threshold, corr_threshold=args.corr_threshold)
633 print(f'Merging step => N={len(mergedpatches)}')

Callers 1

Calls 6

load_encoder_esVITFunction · 0.90
create_tissue_maskFunction · 0.85
create_tissue_tilesFunction · 0.85
make_tile_QC_figFunction · 0.85
extract_featuresFunction · 0.85
mergedpatch_genFunction · 0.85

Tested by

no test coverage detected