def exercise_polygon(): from dials.util import is_inside_polygon from scitbx.array_family import flex poly = flex.vec2_double(((0,0), (1,0), (1,1), (0,1))) assert is_inside_polygon(poly, 0, 0) assert is_inside_polygon(poly, 0.5, 0.5) assert not is_inside_polygon(poly, 1, 1.01) points = flex.vec2_double(((0.3, 0.8), (0.3, 1.5), (-8,9), (0.00001, 0.9999))) assert list(is_inside_polygon(poly, points)) == [True, False, False, True]
def filter_shadowed_reflections(experiments, reflections): from dials.util import mask_untrusted_polygon from dials.util import is_inside_polygon shadowed = flex.bool(reflections.size(), False) for expt_id in range(len(experiments)): expt = experiments[expt_id] imgset = expt.imageset masker = imgset.reader().get_format().get_goniometer_shadow_masker() detector = expt.detector sel = reflections['id'] == expt_id isel = sel.iselection() x,y,z = reflections['xyzcal.px'].select(isel).parts() start, end = expt.scan.get_array_range() for i in range(start, end): shadow = masker.project_extrema( detector, expt.scan.get_angle_from_array_index(i)) img_sel = (z >= i) & (z < (i+1)) img_isel = img_sel.iselection() for p_id in range(len(detector)): panel = reflections['panel'].select(img_isel) if shadow[p_id].size() < 4: continue panel_isel = img_isel.select(panel == p_id) inside = is_inside_polygon( shadow[p_id], flex.vec2_double(x.select(isel.select(panel_isel)), y.select(isel.select(panel_isel)))) shadowed.set_selected(panel_isel, inside) return shadowed
def project_extrema(self, detector, scan_angle): from dials.util import is_inside_polygon coords = self.extrema_at_scan_angle(scan_angle) shadow_boundary = [] for p_id, p in enumerate(detector): # project coordinates onto panel plane a = p.get_D_matrix() * coords x, y, z = a.parts() valid = z > 0 x.set_selected(valid, x.select(valid) / z.select(valid)) y.set_selected(valid, y.select(valid) / z.select(valid)) if valid.count(True) < 3: # no shadow projected onto this panel shadow_boundary.append(flex.vec2_double()) continue # Compute convex hull of shadow points points = flex.vec2_double(x.select(valid), y.select(valid)) shadow = flex.vec2_double(convex_hull(points)) shadow *= 1 / p.get_pixel_size()[0] shadow_orig = shadow.deep_copy() for i in (0, p.get_image_size()[0]): points = flex.vec2_double( flex.double(p.get_image_size()[1], i), flex.double_range(0, p.get_image_size()[1])) inside = is_inside_polygon(shadow_orig, points) # only add those points needed to define vertices of shadow inside_isel = inside.iselection() outside_isel = (~inside).iselection() while inside_isel.size(): j = inside_isel[0] shadow.append(points[j]) outside_isel = outside_isel.select(outside_isel > j) if outside_isel.size() == 0: shadow.append(points[inside_isel[-1]]) break sel = inside_isel >= outside_isel[0] if sel.count(True) == 0: shadow.append(points[inside_isel[-1]]) break inside_isel = inside_isel.select(sel) for i in (0, p.get_image_size()[1]): points = flex.vec2_double( flex.double_range(0, p.get_image_size()[0]), flex.double(p.get_image_size()[0], i)) inside = is_inside_polygon(shadow_orig, points) # only add those points needed to define vertices of shadow inside_isel = inside.iselection() outside_isel = (~inside).iselection() while inside_isel.size(): j = inside_isel[0] shadow.append(points[j]) outside_isel = outside_isel.select(outside_isel > j) if outside_isel.size() == 0: shadow.append(points[inside_isel[-1]]) break sel = inside_isel >= outside_isel[0] if sel.count(True) == 0: shadow.append(points[inside_isel[-1]]) break inside_isel = inside_isel.select(sel) # Select only those vertices that are within the panel dimensions n_px = p.get_image_size() x, y = shadow.parts() valid = (x >= 0) & (x <= n_px[0]) & (y >= 0) & (y <= n_px[1]) shadow = shadow.select(valid) # sort vertices clockwise from centre of mass from scitbx.math import principal_axes_of_inertia_2d com = principal_axes_of_inertia_2d(shadow).center_of_mass() sx, sy = shadow.parts() shadow = shadow.select( flex.sort_permutation(flex.atan2(sy - com[1], sx - com[0]))) shadow_boundary.append(shadow) return shadow_boundary
def project_extrema(self, detector, scan_angle): from dials.util import is_inside_polygon coords = self.extrema_at_scan_angle(scan_angle) shadow_boundary = [] for p_id, p in enumerate(detector): # project coordinates onto panel plane a = p.get_D_matrix() * coords x, y, z = a.parts() valid = z > 0 x.set_selected(valid, x.select(valid)/z.select(valid)) y.set_selected(valid, y.select(valid)/z.select(valid)) if valid.count(True) < 3: # no shadow projected onto this panel shadow_boundary.append(flex.vec2_double()) continue # Compute convex hull of shadow points points = flex.vec2_double(x.select(valid), y.select(valid)) shadow = flex.vec2_double(convex_hull(points)) shadow *= 1/p.get_pixel_size()[0] shadow_orig = shadow.deep_copy() for i in (0, p.get_image_size()[0]): points = flex.vec2_double(flex.double(p.get_image_size()[1], i), flex.double_range(0, p.get_image_size()[1])) inside = is_inside_polygon(shadow_orig, points) # only add those points needed to define vertices of shadow inside_isel = inside.iselection() outside_isel = (~inside).iselection() while inside_isel.size(): j = inside_isel[0] shadow.append(points[j]) outside_isel = outside_isel.select(outside_isel > j) if outside_isel.size() == 0: shadow.append(points[inside_isel[-1]]) break sel = inside_isel >= outside_isel[0] if sel.count(True) == 0: shadow.append(points[inside_isel[-1]]) break inside_isel = inside_isel.select(sel) for i in (0, p.get_image_size()[1]): points = flex.vec2_double(flex.double_range(0, p.get_image_size()[0]), flex.double(p.get_image_size()[0], i)) inside = is_inside_polygon(shadow_orig, points) # only add those points needed to define vertices of shadow inside_isel = inside.iselection() outside_isel = (~inside).iselection() while inside_isel.size(): j = inside_isel[0] shadow.append(points[j]) outside_isel = outside_isel.select(outside_isel > j) if outside_isel.size() == 0: shadow.append(points[inside_isel[-1]]) break sel = inside_isel >= outside_isel[0] if sel.count(True) == 0: shadow.append(points[inside_isel[-1]]) break inside_isel = inside_isel.select(sel) # Select only those vertices that are within the panel dimensions n_px = p.get_image_size() x, y = shadow.parts() valid = (x >= 0) & (x <= n_px[0]) & (y >= 0) & (y <= n_px[1]) shadow = shadow.select(valid) # sort vertices clockwise from centre of mass from scitbx.math import principal_axes_of_inertia_2d com = principal_axes_of_inertia_2d(shadow).center_of_mass() sx, sy = shadow.parts() shadow = shadow.select( flex.sort_permutation(flex.atan2(sy-com[1],sx-com[0]))) shadow_boundary.append(shadow) return shadow_boundary