comparison qupath_roi_splitter.py @ 2:7bee859bbd11 draft

planemo upload for repository hhttps://github.com/npinter/ROIsplitter commit 7391296e0c7c8d48b42a129d154b50b29fd41737
author galaxyp
date Thu, 11 Apr 2024 07:52:58 +0000 (9 months ago)
parents 064b53fd3131
children 24ccdcfbabac
comparison
equal deleted inserted replaced
1:064b53fd3131 2:7bee859bbd11
4 import geojson 4 import geojson
5 import numpy as np 5 import numpy as np
6 import pandas as pd 6 import pandas as pd
7 7
8 8
9 def draw_poly(input_df, input_img, col=(0, 0, 0)): 9 def draw_poly(input_df, input_img, col=(0, 0, 0), fill=False):
10 s = np.array(input_df) 10 s = np.array(input_df)
11 output_img = cv2.fillPoly(input_img, pts=np.int32([s]), color=col) 11 if fill:
12 output_img = cv2.fillPoly(input_img, pts=np.int32([s]), color=col)
13 else:
14 output_img = cv2.polylines(input_img, np.int32([s]), True, color=col, thickness=1)
12 return output_img 15 return output_img
16
17
18 def draw_roi(input_roi, input_img, fill):
19 if len(input_roi["geometry"]["coordinates"]) == 1:
20 # Polygon w/o holes
21 input_img = draw_poly(input_roi["geometry"]["coordinates"][0], input_img, fill=fill)
22 else:
23 first_roi = True
24 for sub_roi in input_roi["geometry"]["coordinates"]:
25 # Polygon with holes
26 if not isinstance(sub_roi[0][0], list):
27 if first_roi:
28 input_img = draw_poly(sub_roi, input_img, fill=fill)
29 first_roi = False
30 else:
31 # holes in ROI
32 input_img = draw_poly(sub_roi, input_img, col=(255, 255, 255), fill=fill)
33 else:
34 # MultiPolygon with holes
35 for sub_coord in sub_roi:
36 if first_roi:
37 input_img = draw_poly(sub_coord, input_img, fill=fill)
38 first_roi = False
39 else:
40 # holes in ROI
41 input_img = draw_poly(sub_coord, input_img, col=(255, 255, 255), fill=fill)
42
43 return input_img
13 44
14 45
15 def split_qupath_roi(in_roi): 46 def split_qupath_roi(in_roi):
16 with open(in_roi) as file: 47 with open(in_roi) as file:
17 qupath_roi = geojson.load(file) 48 qupath_roi = geojson.load(file)
26 # create numpy array with white background 57 # create numpy array with white background
27 img = np.zeros((dim_plt[1], dim_plt[0], 3), dtype="uint8") 58 img = np.zeros((dim_plt[1], dim_plt[0], 3), dtype="uint8")
28 img.fill(255) 59 img.fill(255)
29 60
30 for i, roi in enumerate(qupath_roi["features"]): 61 for i, roi in enumerate(qupath_roi["features"]):
31 if roi["properties"]["classification"]["name"] == cell_type: 62 if not args.all:
32 if len(roi["geometry"]["coordinates"]) == 1: 63 if "classification" not in roi["properties"]:
33 # Polygon w/o holes 64 continue
34 img = draw_poly(roi["geometry"]["coordinates"][0], img) 65 if roi["properties"]["classification"]["name"] == cell_type:
35 else: 66 img = draw_roi(roi, img, args.fill)
36 first_roi = True 67 else:
37 for sub_roi in roi["geometry"]["coordinates"]: 68 img = draw_roi(roi, img, args.fill)
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 69
56 # get all black pixel 70 # get all black pixel
57 coords_arr = np.column_stack(np.where(img == (0, 0, 0))) 71 coords_arr = np.column_stack(np.where(img == (0, 0, 0)))
58 72
59 # remove duplicated rows 73 # remove duplicated rows
61 75
62 # remove last column 76 # remove last column
63 coords_arr_xy = np.delete(coords_arr_xy, 2, axis=1) 77 coords_arr_xy = np.delete(coords_arr_xy, 2, axis=1)
64 78
65 # to pandas and rename columns to x and y 79 # to pandas and rename columns to x and y
66 coords_df = pd.DataFrame(coords_arr_xy, columns=['x', 'y']) 80 coords_df = pd.DataFrame(coords_arr_xy, columns=['y', 'x'])
81
82 # reorder columns
83 coords_df = coords_df[['x', 'y']]
67 84
68 # drop duplicates 85 # drop duplicates
69 coords_df = coords_df.drop_duplicates( 86 coords_df = coords_df.drop_duplicates(
70 subset=['x', 'y'], 87 subset=['x', 'y'],
71 keep='last').reset_index(drop=True) 88 keep='last').reset_index(drop=True)
74 91
75 92
76 if __name__ == "__main__": 93 if __name__ == "__main__":
77 parser = argparse.ArgumentParser(description="Split ROI coordinates of QuPath TMA annotation by cell type (classfication)") 94 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)") 95 parser.add_argument("--qupath_roi", default=False, help="Input QuPath annotation (GeoJSON file)")
96 parser.add_argument("--fill", action="store_true", required=False, help="Fill pixels in ROIs")
79 parser.add_argument('--version', action='version', version='%(prog)s 0.1.0') 97 parser.add_argument('--version', action='version', version='%(prog)s 0.1.0')
98 parser.add_argument("--all", action="store_true", required=False, help="Extracts all ROIs")
80 args = parser.parse_args() 99 args = parser.parse_args()
81 100
82 if args.qupath_roi: 101 if args.qupath_roi:
83 split_qupath_roi(args.qupath_roi) 102 split_qupath_roi(args.qupath_roi)