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)