Skip to content

Commit 6e9fce8

Browse files
authored
Merge pull request #32 from AllenInstitute/filter_by_rectangle
Filter by rectangle
2 parents 3d35a9f + 8b515c6 commit 6e9fce8

File tree

1 file changed

+180
-0
lines changed

1 file changed

+180
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import renderapi
2+
import json
3+
import numpy as np
4+
from functools import partial
5+
import os
6+
import pathos.multiprocessing as mp
7+
from shapely import geometry
8+
from ..module.render_module import RenderModule, RenderParameters
9+
from argschema.fields import Str, InputDir, Int
10+
11+
example_json = {
12+
"render":{
13+
"host":"ibs-forrestc-ux1",
14+
"port":80,
15+
"owner":"Small_volumes_2018",
16+
"project":"M367240_D_SSTPV_smallvol",
17+
"client_scripts":"/pipeline/render/render-ws-java-client/src/main/scripts"
18+
},
19+
"stack":"BIG_ROT_FA12_RA00_STI_DCV_FF_Session1",
20+
#"polygon_dir":"/nas3/data/M247514_Rorb_1/processed/shape_polygons",
21+
"minX": 0,
22+
"minY": 0,
23+
"maxX": 10,
24+
"maxY": 10,
25+
"matchcollection":"M367240_D_SSTPV_smallvol_DAPI_1_3D_v9_r0",
26+
"targetmatchcollection":"M367240_D_SSTPV_smallvol_DAPI_1_3D_v9_r0_FIL"
27+
}
28+
29+
30+
31+
class FilterPointMatchParameters(RenderParameters):
32+
stack = Str(required=True,
33+
description='stack sectionPolygons are based upon')
34+
35+
minX = Int(required=True,
36+
description='MinX')
37+
minY = Int(required=True,
38+
description='MinY')
39+
maxX = Int(required=True,
40+
description='MaxX')
41+
maxY = Int(required=True,
42+
description='MaxY')
43+
44+
matchcollection = Str(required=True,
45+
description='match collection to filter')
46+
47+
targetmatchcollection = Str(required=True,
48+
description='match collection to output to')
49+
50+
def mask_points(points,mask):
51+
p = np.array(points).T
52+
return p[mask,:].T.tolist()
53+
54+
def mask_match(match,mask):
55+
if np.sum(mask)==0:
56+
return None
57+
match['matches']['p']=mask_points(match['matches']['p'],mask)
58+
match['matches']['q']=mask_points(match['matches']['q'],mask)
59+
w = np.array(match['matches']['w'])
60+
match['matches']['w']=w[mask].tolist()
61+
return match
62+
63+
def find_inside_points(r,stack,matchp,ts,poly):
64+
local_points=np.array(matchp).T
65+
world_points = r.run(renderapi.coordinate.local_to_world_coordinates_array,stack,local_points,ts.tileId,ts.z)
66+
worldPoints = [geometry.Point(x,y) for x,y in world_points]
67+
isInside = map(lambda x: x.within(poly),worldPoints)
68+
return np.array(isInside)
69+
70+
def filter_match(r,match,stack,polyp,polyq,tsp,tsq):
71+
insidep = find_inside_points(r,stack,match['matches']['p'],tsp,polyp)
72+
insideq = find_inside_points(r,stack,match['matches']['q'],tsq,polyq)
73+
insideboth = insidep & insideq
74+
newmatch = mask_match(match,insideboth)
75+
return newmatch
76+
77+
def filter_matches(r,stack,fromcollection,tocollection,polydict,pgroup):
78+
matches=r.run(renderapi.pointmatch.get_matches_with_group,fromcollection,pgroup)
79+
new_matches = []
80+
try:
81+
polyp = polydict[pgroup]
82+
z = r.run(renderapi.stack.get_z_value_for_section,stack,pgroup)
83+
tilespecs = r.run(renderapi.tilespec.get_tile_specs_from_z,stack,z)
84+
tiledict = {}
85+
for ts in tilespecs:
86+
tiledict[ts.tileId]=ts
87+
qgroups = set([match['qGroupId'] for match in matches])
88+
89+
for qgroup in qgroups:
90+
z = r.run(renderapi.stack.get_z_value_for_section,stack,qgroup)
91+
tilespecs=r.run(renderapi.tilespec.get_tile_specs_from_z,stack,z)
92+
for ts in tilespecs:
93+
tiledict[ts.tileId]=ts
94+
for match in matches:
95+
qgroup = match['pGroupId']
96+
polyq = polydict[qgroup]
97+
new_match = filter_match(r,match,stack,polyp,polyq,tiledict[match['pId']],tiledict[match['qId']])
98+
if new_match is not None:
99+
new_matches.append(match)
100+
#print(json.dumps(new_matches))
101+
#print tocollection
102+
renderapi.pointmatch.import_matches(tocollection,new_matches,render=r)
103+
104+
#return r.run(renderapi.pointmatch.import_matches,tocollection,json.dumps(new_matches))
105+
except:
106+
print "Exception"
107+
108+
109+
def create_polydict(r,stack,mask_dir):
110+
sectionData=r.run(renderapi.stack.get_sectionData_for_stack,stack)
111+
sectionIds=[sd['sectionId'] for sd in sectionData]
112+
polydict = {}
113+
for sectionId in sectionIds:
114+
z = r.run(renderapi.stack.get_z_value_for_section,stack,sectionId)
115+
polyfile = os.path.join(mask_dir,'polygon_%05d.json'%z)
116+
polyjson = json.load(open(polyfile,'r'))
117+
poly = geometry.shape(polyjson['roi'])
118+
polydict[sectionId]=poly
119+
return polydict
120+
121+
def create_polydict_coords(r,stack,minX,minY,maxX,maxY):
122+
#sectionData=r.run(renderapi.stack.get_sectionData_for_stack,stack)
123+
sectionData = renderapi.stack.get_stack_sectionData(stack,render=r)
124+
sectionIds=[sd['sectionId'] for sd in sectionData]
125+
polydict = {}
126+
for sectionId in sectionIds:
127+
z = r.run(renderapi.stack.get_z_value_for_section,stack,sectionId)
128+
#polyfile = os.path.join(mask_dir,'polygon_%05d.json'%z)
129+
#polyjson = json.load(open(polyfile,'r'))
130+
#poly = geometry.shape(polyjson['roi'])
131+
poly = geometry.box(minX,minY,maxX,maxY)
132+
polydict[sectionId]=poly
133+
return polydict
134+
135+
def create_zdict(r,stack):
136+
#sectionData=r.run(renderapi.stack.get_sectionData_for_stack,stack)
137+
sectionData = renderapi.stack.get_stack_sectionData(stack,render=r)
138+
sectionIds=[sd['sectionId'] for sd in sectionData]
139+
zdict={}
140+
for sectionId in sectionIds:
141+
z = r.run(renderapi.stack.get_z_value_for_section,stack,sectionId)
142+
zdict[sectionId]=z
143+
return zdict
144+
145+
class FilterPointMatch(RenderModule):
146+
def __init__(self,schema_type=None,*args,**kwargs):
147+
if schema_type is None:
148+
schema_type = FilterPointMatchParameters
149+
super(FilterPointMatch,self).__init__(schema_type=schema_type,*args,**kwargs)
150+
def run(self):
151+
#self.logger.error("WARNING NOT TESTED, TALK TO FORREST IF BROKEN OR WORKS")
152+
153+
stack = self.args['stack']
154+
#polygonfolder = self.args['polygon_dir']
155+
matchcollection = self.args['matchcollection']
156+
targetmatchcollection =self.args['targetmatchcollection']
157+
minX = self.args['minX']
158+
minY = self.args['minY']
159+
maxX = self.args['maxX']
160+
maxY = self.args['maxY']
161+
162+
#define a dictionary of z values for each sectionId
163+
zdict = create_zdict(self.render,stack)
164+
165+
#define a dictionary of polygons for each sectionId
166+
polydict = create_polydict_coords(self.render,stack,minX,minY,maxX,maxY)
167+
168+
#get the set of starting sectionIds for the point match database
169+
pgroups = self.render.run(renderapi.pointmatch.get_match_groupIds_from_only,matchcollection)
170+
171+
#define a partial function on filter_matches that takes in a single sectionId
172+
mypartial=partial(filter_matches,self.render,stack,matchcollection,targetmatchcollection,polydict)
173+
174+
#res = pool.map(mypartial,pgroups)
175+
for pgroup in pgroups:
176+
mypartial(pgroup)
177+
178+
if __name__ == "__main__":
179+
mod = FilterPointMatch(input_data= example_json)
180+
mod.run()

0 commit comments

Comments
 (0)