Mercurial > repos > galaxyp > qupath_roi_splitter
comparison qupath_roi_splitter.py @ 0:b5e9cebb27e3 draft
planemo upload for repository hhttps://github.com/npinter/ROIsplitter commit cdf3e9652b10c7a0b179202129a797e32fd95909
author | galaxyp |
---|---|
date | Tue, 25 Apr 2023 09:30:06 +0000 |
parents | |
children | 064b53fd3131 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:b5e9cebb27e3 |
---|---|
1 import argparse | |
2 | |
3 import cv2 | |
4 import geojson | |
5 import numpy as np | |
6 import pandas as pd | |
7 | |
8 | |
9 def draw_poly(input_df, input_img, col=(0, 0, 0)): | |
10 s = np.array(input_df) | |
11 output_img = cv2.fillPoly(input_img, pts=np.int32([s]), color=col) | |
12 return output_img | |
13 | |
14 | |
15 def split_qupath_roi(in_roi): | |
16 with open(in_roi) as file: | |
17 qupath_roi = geojson.load(file) | |
18 | |
19 # HE dimensions | |
20 dim_plt = [qupath_roi["dim"]["width"], qupath_roi["dim"]["height"]] | |
21 | |
22 tma_name = qupath_roi["name"] | |
23 cell_types = [ct.rsplit(" - ", 1)[-1] for ct in qupath_roi["featureNames"]] | |
24 | |
25 # create numpy array with white background | |
26 img = np.zeros((dim_plt[1], dim_plt[0], 3), dtype="uint8") | |
27 img.fill(255) | |
28 | |
29 for cell_type in cell_types: | |
30 for i, roi in enumerate(qupath_roi["features"]): | |
31 if roi["properties"]["classification"]["name"] == cell_type: | |
32 if len(roi["geometry"]["coordinates"]) == 1: | |
33 # Polygon w/o holes | |
34 img = draw_poly(roi["geometry"]["coordinates"][0], img) | |
35 else: | |
36 first_roi = True | |
37 for sub_roi in roi["geometry"]["coordinates"]: | |
38 # Polygon with holes | |
39 if not isinstance(sub_roi[0][0], list): | |
40 if first_roi: | |
41 img = draw_poly(sub_roi, img) | |
42 first_roi = False | |
43 else: | |
44 # holes in ROI | |
45 img = draw_poly(sub_roi, img, col=(255, 255, 255)) | |
46 else: | |
47 # MultiPolygon with holes | |
48 for sub_coord in sub_roi: | |
49 if first_roi: | |
50 img = draw_poly(sub_coord, img) | |
51 first_roi = False | |
52 else: | |
53 # holes in ROI | |
54 img = draw_poly(sub_coord, img, col=(255, 255, 255)) | |
55 | |
56 # get all black pixel | |
57 coords_arr = np.column_stack(np.where(img == (0, 0, 0))) | |
58 | |
59 # remove duplicated rows | |
60 coords_arr_xy = coords_arr[coords_arr[:, 2] == 0] | |
61 | |
62 # remove last column | |
63 coords_arr_xy = np.delete(coords_arr_xy, 2, axis=1) | |
64 | |
65 # to pandas and rename columns to x and y | |
66 coords_df = pd.DataFrame(coords_arr_xy, columns=['x', 'y']) | |
67 | |
68 # drop duplicates | |
69 coords_df = coords_df.drop_duplicates( | |
70 subset=['x', 'y'], | |
71 keep='last').reset_index(drop=True) | |
72 | |
73 coords_df.to_csv("{}_{}.txt".format(tma_name, cell_type), sep='\t', index=False) | |
74 | |
75 | |
76 if __name__ == "__main__": | |
77 parser = argparse.ArgumentParser(description="Split ROI coordinates of QuPath TMA annotation by cell type (classfication)") | |
78 parser.add_argument("--qupath_roi", default=False, help="Input QuPath annotation (GeoJSON file)") | |
79 parser.add_argument('--version', action='version', version='%(prog)s 0.1.0') | |
80 args = parser.parse_args() | |
81 | |
82 if args.qupath_roi: | |
83 split_qupath_roi(args.qupath_roi) |