def map_points_to_reciprocal_space(self): goniometer = self.imagesets[0].get_goniometer() if self.goniometer_orig is not None and not self.settings.reverse_phi: self.imagesets[0].set_goniometer(self.goniometer_orig) self.goniometer_orig = None elif goniometer is not None and self.settings.reverse_phi: self.goniometer_orig = copy.deepcopy(goniometer) goniometer.set_rotation_axis([-i for i in goniometer.get_rotation_axis()]) from dials.algorithms.indexing import indexer from dials.array_family import flex reflections = flex.reflection_table() for i, imageset in enumerate(self.imagesets): if 'imageset_id' in self.reflections_input: sel = (self.reflections_input['imageset_id'] == i) else: sel = (self.reflections_input['id'] == i) if isinstance(self.reflections_input['id'], flex.size_t): self.reflections_input['id'] = self.reflections_input['id'].as_int() refl = indexer.indexer_base.map_spots_pixel_to_mm_rad( self.reflections_input.select(sel), imageset.get_detector(), imageset.get_scan()) indexer.indexer_base.map_centroids_to_reciprocal_space( refl, imageset.get_detector(), imageset.get_beam(), imageset.get_goniometer()) reflections.extend(refl) self.reflections = reflections
def generate_reflections(detector, beam, scan, experiment, num): from random import randint, seed from scitbx import matrix from dials.array_family import flex from dials.algorithms.shoebox import MaskCode seed(0) assert len(detector) == 1 beam_vector = flex.vec3_double(num) xyzcal_px = flex.vec3_double(num) xyzcal_mm = flex.vec3_double(num) panel = flex.size_t(num) s0_length = matrix.col(beam.get_s0()).length() for i in range(num): x = randint(0, 2000) y = randint(0, 2000) z = randint(0, 8) s1 = detector[0].get_pixel_lab_coord((x, y)) s1 = matrix.col(s1).normalize() * s0_length phi = scan.get_angle_from_array_index(z, deg=False) beam_vector[i] = s1 xyzcal_px[i] = (x, y, z) (x, y) = detector[0].pixel_to_millimeter((x, y)) xyzcal_mm[i] = (x, y, phi) panel[i] = 0 sigma_b = experiment[0].beam.get_sigma_divergence(deg=False) try: sigma_m = experiment[0].crystal.get_mosaicity(deg=False) except AttributeError: sigma_m = 0 rlist = flex.reflection_table() rlist["id"] = flex.int(len(beam_vector), 0) rlist["s1"] = beam_vector rlist["panel"] = panel rlist["xyzcal.px"] = xyzcal_px rlist["xyzcal.mm"] = xyzcal_mm rlist["bbox"] = rlist.compute_bbox(experiment) index = [] image_size = experiment[0].detector[0].get_image_size() array_range = experiment[0].scan.get_array_range() bbox = rlist["bbox"] for i in range(len(rlist)): x0, x1, y0, y1, z0, z1 = bbox[i] if ( x0 < 0 or x1 > image_size[0] or y0 < 0 or y1 > image_size[1] or z0 < array_range[0] or z1 > array_range[1] ): index.append(i) rlist.del_selected(flex.size_t(index)) rlist["shoebox"] = flex.shoebox(rlist["panel"], rlist["bbox"]) rlist["shoebox"].allocate_with_value(MaskCode.Valid) return rlist
def index_with_known_orientation(self, datablock, reflections): ''' Copy of the index function from stills_process to force IOTA to use stills_indexer during known_orientation ''' from dials.algorithms.indexing.stills_indexer import stills_indexer from time import time import copy st = time() imagesets = datablock.extract_imagesets() params = copy.deepcopy(self.params) # don't do scan-varying refinement during indexing params.refinement.parameterisation.scan_varying = False if hasattr(self, 'known_crystal_models'): known_crystal_models = self.known_crystal_models else: known_crystal_models = None if params.indexing.stills.method_list is None: idxr = stills_indexer.from_parameters( reflections, imagesets, known_crystal_models=known_crystal_models, params=params) idxr.index() else: indexing_error = None for method in params.indexing.stills.method_list: params.indexing.method = method try: idxr = stills_indexer.from_parameters( reflections, imagesets, params=params) idxr.index() except Exception as e: logger.info("Couldn't index using method %s"%method) if indexing_error is None: if e is None: e = Exception("Couldn't index using method %s"%method) indexing_error = e else: indexing_error = None break if indexing_error is not None: raise indexing_error indexed = idxr.refined_reflections experiments = idxr.refined_experiments if known_crystal_models is not None: from dials.array_family import flex filtered = flex.reflection_table() for idx in set(indexed['miller_index']): sel = indexed['miller_index'] == idx if sel.count(True) == 1: filtered.extend(indexed.select(sel)) print("Filtered duplicate reflections, %d out of %d remaining"%(len(filtered),len(indexed))) indexed = filtered return experiments, indexed
def generate_reflections(self, num): from random import randint, seed from scitbx import matrix from dials.array_family import flex from dials.algorithms.shoebox import MaskCode seed(0) assert(len(self.detector) == 1) beam_vector = flex.vec3_double(num) xyzcal_px = flex.vec3_double(num) xyzcal_mm = flex.vec3_double(num) panel = flex.size_t(num) s0_length = matrix.col(self.beam.get_s0()).length() for i in range(num): x = randint(0, 2000) y = randint(0, 2000) z = randint(0, 8) s1 = self.detector[0].get_pixel_lab_coord((x, y)) s1 = matrix.col(s1).normalize() * s0_length phi = self.scan.get_angle_from_array_index(z, deg=False) beam_vector[i] = s1 xyzcal_px[i] = (x, y, z) (x, y) = self.detector[0].pixel_to_millimeter((x, y)) xyzcal_mm[i] = (x, y, phi) panel[i] = 0 sigma_b = self.experiment[0].beam.get_sigma_divergence(deg=False) sigma_m = self.experiment[0].crystal.get_mosaicity(deg=False) rlist = flex.reflection_table() rlist['id'] = flex.int(len(beam_vector), 0) rlist['s1'] = beam_vector rlist['panel'] = panel rlist['xyzcal.px'] = xyzcal_px rlist['xyzcal.mm'] = xyzcal_mm rlist['bbox'] = rlist.compute_bbox(self.experiment) index = [] image_size = self.experiment[0].detector[0].get_image_size() array_range = self.experiment[0].scan.get_array_range() bbox = rlist['bbox'] for i in range(len(rlist)): x0, x1, y0, y1, z0, z1 = bbox[i] if (x0 < 0 or x1 > image_size[0] or y0 < 0 or y1 > image_size[1] or z0 < array_range[0] or z1 > array_range[1]): index.append(i) rlist.del_selected(flex.size_t(index)) rlist['shoebox'] = flex.shoebox( rlist['panel'], rlist['bbox']) rlist['shoebox'].allocate_with_value(MaskCode.Valid) return rlist
def generate_single_central_non_negative_profiles(self): from dials.array_family import flex rlist = flex.reflection_table(1) profile = gaussian(self.grid_size, 1000, (4, 4, 4), (1.5, 1.5, 1.5)) x = 500 y = 500 z = 5 xyz = flex.vec3_double(1) xyz[0] = (x, y, z) profiles = [profile.deep_copy()] rlist['xyzcal.px'] = xyz return rlist, profiles, profile
def map_points_to_reciprocal_space(self): from dials.algorithms.indexing import indexer from dials.array_family import flex import copy reflections = flex.reflection_table() for i, imageset in enumerate(self.imagesets): if 'imageset_id' in self.reflections_input: sel = (self.reflections_input['imageset_id'] == i) else: sel = (self.reflections_input['id'] == i) if isinstance(self.reflections_input['id'], flex.size_t): self.reflections_input['id'] = self.reflections_input[ 'id'].as_int() # 155 handle data from predictions *only* if that is what we have if 'xyzobs.px.value' in self.reflections_input: refl = indexer.indexer_base.map_spots_pixel_to_mm_rad( self.reflections_input.select(sel), imageset.get_detector(), imageset.get_scan()) goniometer = copy.deepcopy(imageset.get_goniometer()) if self.settings.reverse_phi: goniometer.set_rotation_axis( [-i for i in goniometer.get_rotation_axis()]) indexer.indexer_base.map_centroids_to_reciprocal_space( refl, imageset.get_detector(), imageset.get_beam(), goniometer) else: # work on xyzcal.mm refl = self.reflections_input.select(sel) goniometer = copy.deepcopy(imageset.get_goniometer()) if self.settings.reverse_phi: goniometer.set_rotation_axis( [-i for i in goniometer.get_rotation_axis()]) indexer.indexer_base.map_centroids_to_reciprocal_space( refl, imageset.get_detector(), imageset.get_beam(), goniometer, calculated=True) reflections.extend(refl) self.reflections = reflections
def generate_identical_non_negative_profiles(self): from dials.array_family import flex from random import uniform rlist = flex.reflection_table(1000) profile = gaussian(self.grid_size, 1000, (4, 4, 4), (1.5, 1.5, 1.5)) xyz = flex.vec3_double(1000) profiles = [] for i in range(1000): x = uniform(0, 1000) y = uniform(0, 1000) z = uniform(0, 10) xyz[i] = (x, y, z) profiles.append(profile.deep_copy()) rlist['xyzcal.px'] = xyz return rlist, profiles, profile
def map_points_to_reciprocal_space(self): from dials.algorithms.indexing import indexer from dials.array_family import flex import copy reflections = flex.reflection_table() for i, imageset in enumerate(self.imagesets): if 'imageset_id' in self.reflections_input: sel = (self.reflections_input['imageset_id'] == i) else: sel = (self.reflections_input['id'] == i) if isinstance(self.reflections_input['id'], flex.size_t): self.reflections_input['id'] = self.reflections_input['id'].as_int() # 155 handle data from predictions *only* if that is what we have if 'xyzobs.px.value' in self.reflections_input: refl = indexer.indexer_base.map_spots_pixel_to_mm_rad( self.reflections_input.select(sel), imageset.get_detector(), imageset.get_scan()) goniometer = copy.deepcopy(imageset.get_goniometer()) if self.settings.reverse_phi: goniometer.set_rotation_axis( [-i for i in goniometer.get_rotation_axis()]) indexer.indexer_base.map_centroids_to_reciprocal_space( refl, imageset.get_detector(), imageset.get_beam(), goniometer) else: # work on xyzcal.mm refl = self.reflections_input.select(sel) goniometer = copy.deepcopy(imageset.get_goniometer()) if self.settings.reverse_phi: goniometer.set_rotation_axis( [-i for i in goniometer.get_rotation_axis()]) indexer.indexer_base.map_centroids_to_reciprocal_space( refl, imageset.get_detector(), imageset.get_beam(), goniometer, calculated=True) reflections.extend(refl) self.reflections = reflections
def _select_reflections_for_sigma_calc(reflections, min_number_of_refl=10000): """Determine a subset of reflections to use for sigma_m calculation.""" from dials.array_family import flex n_ref = reflections.size() if n_ref > min_number_of_refl: # ideally use well-sampled selection from refinement used_in_ref = reflections.get_flags( reflections.flags.used_in_refinement) n_used_in_ref = used_in_ref.count(True) if n_used_in_ref > min_number_of_refl: selected_reflections = reflections.select(used_in_ref) logger.debug( "Using %s reflections with used_in_refinement flag for sigma calculation", n_used_in_ref, ) # handle case where used_in_refl not set/data not refined else: # more than min_no of refls, but refinement didn't use more than # min_no: still use the ones from refinement and 'top up' if n_used_in_ref: selected_reflections = reflections.select(used_in_ref) other_refls = reflections.select(~used_in_ref) else: selected_reflections = flex.reflection_table() other_refls = reflections # top up with every nth reflection needed to make up the number needed n_sel = selected_reflections.size() n_other = other_refls.size() step_size = int(math.floor(n_other / (min_number_of_refl - n_sel))) sel = flex.size_t(i for i in range(0, n_other, step_size)) selected_reflections.extend(other_refls.select(sel)) logger.debug( "Using %s reflections for sigma calculation", selected_reflections.size(), ) return selected_reflections logger.debug("Using all suitable reflections for sigma calculation") return reflections
def generate_systematically_offset_profiles(self): from dials.array_family import flex from random import uniform rlist = flex.reflection_table(1000) xyz = flex.vec3_double(1000) profiles = [] for i in range(1000): x = uniform(0, 1000) y = uniform(0, 1000) z = uniform(0, 10) offset = -4.5 + 9 * x / 1000.0 profile = gaussian(self.grid_size, 1000, (4 + offset, 4, 4), (1.5, 1.5, 1.5)) xyz[i] = (x, y, z) profiles.append(profile) rlist['xyzcal.px'] = xyz return rlist, profiles
def run(self, flags, sweep=None, shoeboxes=None, **kwargs): from dials.array_family import flex from dials.algorithms.shoebox import MaskCode from dials.algorithms.background.simple import Linear2dModeller bg_code = MaskCode.Valid | MaskCode.BackgroundUsed fg_code = MaskCode.Valid | MaskCode.Foreground strong_code = MaskCode.Valid | MaskCode.Strong modeller = Linear2dModeller() expanded_shoeboxes = flex.shoebox() detector = sweep.get_detector() zoffset = 0 if sweep.get_scan() is not None: zoffset = sweep.get_scan().get_array_range()[0] from libtbx.containers import OrderedDict class image_data_cache(object): def __init__(self, imageset, size=10): self.imageset = imageset self.size = size self._image_data = OrderedDict() def __getitem__(self, i): image_data = self._image_data.get(i) if image_data is None: image_data = self.imageset.get_raw_data(i) if len(self._image_data) >= self.size: # remove the oldest entry in the cache del self._image_data[self._image_data.keys()[0]] self._image_data[i] = image_data return image_data cache = image_data_cache(sweep) #cache = sweep # sort shoeboxes by centroid z frame = shoeboxes.centroid_all().position_frame() perm = flex.sort_permutation(frame) shoeboxes = shoeboxes.select(perm) buffer_size = 1 bg_plus_buffer = self.background_size + buffer_size import time t0 = time.time() for i, shoebox in enumerate(shoeboxes): if not flags[perm[i]]: continue panel = detector[shoebox.panel] trusted_range = panel.get_trusted_range() max_x, max_y = panel.get_image_size() bbox = shoebox.bbox x1, x2, y1, y2, z1, z2 = bbox # expand the bbox with a background region around the spotfinder shoebox # perhaps also should use a buffer zone between the shoebox and the # background region expanded_bbox = (max(0, x1-bg_plus_buffer), min(max_x, x2+bg_plus_buffer), max(0, y1-bg_plus_buffer), min(max_y, y2+bg_plus_buffer), z1, z2) shoebox.bbox = expanded_bbox t1 = time.time() info("Time expand_shoebox: %s" %(t1-t0)) rlist = flex.reflection_table() rlist['shoebox'] = shoeboxes rlist['shoebox'].allocate() rlist['panel'] = shoeboxes.panels() rlist['bbox'] = shoeboxes.bounding_boxes() t0 = time.time() rlist.extract_shoeboxes(sweep) t1 = time.time() shoeboxes = rlist['shoebox'] shoeboxes.flatten() t0 = time.time() for i, shoebox in enumerate(shoeboxes): if not flags[perm[i]]: continue panel = detector[shoebox.panel] trusted_range = panel.get_trusted_range() max_x, max_y = panel.get_image_size() ex1, ex2, ey1, ey2, ez1, ez2 = shoebox.bbox data = shoebox.data mask = flex.bool(data.accessor(), False) for i_y, y in enumerate(range(ey1, ey2)): for i_x, x in enumerate(range(ex1, ex2)): value = data[0, i_y, i_x] if (y >= (ey1+buffer_size) and y < (ey2-buffer_size) and x >= (ex1+buffer_size) and x < (ex2-buffer_size)): mask[0, i_y, i_x] = False # foreground elif (value > trusted_range[0] and value < trusted_range[1]): mask[0, i_y, i_x] = True # background model = modeller.create(data.as_double(), mask) d, a, b = model.params()[:3] c = -1 if abs(a) > self.gradient_cutoff or abs(b) > self.gradient_cutoff: flags[perm[i]] = False # FIXME should this commented out section be removed? #if abs(a) < self.gradient_cutoff and abs(b) < self.gradient_cutoff: #flags[i] = False #if x2-x1 > 10 or y2-y1 > 10: #print a, b, d, flags[perm[i]] #bg = flex.double(data.accessor()) #for x in range(ex2-ex1): #for y in range(ey2-ey1): #z = a * x + b * y + d #bg[0,y,x] = z #model = modeller.create(data-bg, mask) #d, a, b = model.params()[:3] #c = -1 #bg2 = flex.double(data.accessor()) #for x in range(ex2-ex1): #for y in range(ey2-ey1): #z = a * x + b * y + d #bg2[0,y,x] = z ##print a, b, d #from matplotlib import pyplot #fig, axes = pyplot.subplots(nrows=1, ncols=5) #im0 = axes[0].imshow(data.as_numpy_array()[i_z,:,:], interpolation='none') #im1 = axes[1].imshow(mask.as_numpy_array()[i_z,:,:], interpolation='none') #im2 = axes[2].imshow(bg.as_numpy_array()[i_z,:,:], interpolation='none') #im3 = axes[3].imshow((data-bg).as_numpy_array()[i_z,:,:], interpolation='none') #im4 = axes[4].imshow(bg2.as_numpy_array()[i_z,:,:], interpolation='none') ##pyplot.colorbar(im0) ##pyplot.colorbar(im1) ##pyplot.colorbar(im2) ##pyplot.colorbar(im3) #pyplot.show() #from matplotlib import pyplot #fig, axes = pyplot.subplots(nrows=1, ncols=2) #im0 = axes[0].imshow(data.as_numpy_array()[i_z,:,:], interpolation='none') #im1 = axes[1].imshow(bg.as_numpy_array()[i_z,:,:], interpolation='none') #pyplot.colorbar(im1) #pyplot.show() t1 = time.time() #print "Time fit_bg: %s" %(t1-t0) return flags
def run(self, flags, sweep=None, shoeboxes=None, **kwargs): from dials.array_family import flex from dials.algorithms.shoebox import MaskCode from dials.algorithms.background.simple import Linear2dModeller bg_code = MaskCode.Valid | MaskCode.BackgroundUsed fg_code = MaskCode.Valid | MaskCode.Foreground strong_code = MaskCode.Valid | MaskCode.Strong modeller = Linear2dModeller() expanded_shoeboxes = flex.shoebox() detector = sweep.get_detector() zoffset = 0 if sweep.get_scan() is not None: zoffset = sweep.get_scan().get_array_range()[0] from libtbx.containers import OrderedDict class image_data_cache(object): def __init__(self, imageset, size=10): self.imageset = imageset self.size = size self._image_data = OrderedDict() def __getitem__(self, i): image_data = self._image_data.get(i) if image_data is None: image_data = self.imageset.get_raw_data(i) if len(self._image_data) >= self.size: # remove the oldest entry in the cache del self._image_data[self._image_data.keys()[0]] self._image_data[i] = image_data return image_data cache = image_data_cache(sweep) #cache = sweep # sort shoeboxes by centroid z frame = shoeboxes.centroid_all().position_frame() perm = flex.sort_permutation(frame) shoeboxes = shoeboxes.select(perm) buffer_size = 1 bg_plus_buffer = self.background_size + buffer_size import time t0 = time.time() for i, shoebox in enumerate(shoeboxes): if not flags[perm[i]]: continue panel = detector[shoebox.panel] trusted_range = panel.get_trusted_range() max_x, max_y = panel.get_image_size() bbox = shoebox.bbox x1, x2, y1, y2, z1, z2 = bbox # expand the bbox with a background region around the spotfinder shoebox # perhaps also should use a buffer zone between the shoebox and the # background region expanded_bbox = (max(0, x1 - bg_plus_buffer), min(max_x, x2 + bg_plus_buffer), max(0, y1 - bg_plus_buffer), min(max_y, y2 + bg_plus_buffer), z1, z2) shoebox.bbox = expanded_bbox t1 = time.time() logger.info("Time expand_shoebox: %s" % (t1 - t0)) rlist = flex.reflection_table() rlist['shoebox'] = shoeboxes rlist['shoebox'].allocate() rlist['panel'] = shoeboxes.panels() rlist['bbox'] = shoeboxes.bounding_boxes() t0 = time.time() rlist.extract_shoeboxes(sweep) t1 = time.time() shoeboxes = rlist['shoebox'] shoeboxes.flatten() t0 = time.time() for i, shoebox in enumerate(shoeboxes): if not flags[perm[i]]: continue panel = detector[shoebox.panel] trusted_range = panel.get_trusted_range() max_x, max_y = panel.get_image_size() ex1, ex2, ey1, ey2, ez1, ez2 = shoebox.bbox data = shoebox.data mask = flex.bool(data.accessor(), False) for i_y, y in enumerate(range(ey1, ey2)): for i_x, x in enumerate(range(ex1, ex2)): value = data[0, i_y, i_x] if (y >= (ey1 + buffer_size) and y < (ey2 - buffer_size) and x >= (ex1 + buffer_size) and x < (ex2 - buffer_size)): mask[0, i_y, i_x] = False # foreground elif value > trusted_range[0] and value < trusted_range[1]: mask[0, i_y, i_x] = True # background model = modeller.create(data.as_double(), mask) d, a, b = model.params()[:3] c = -1 if abs(a) > self.gradient_cutoff or abs(b) > self.gradient_cutoff: flags[perm[i]] = False t1 = time.time() return flags
def run(self, flags, sweep=None, shoeboxes=None, **kwargs): from dials.array_family import flex from dials.algorithms.shoebox import MaskCode from dials.algorithms.background.simple import Linear2dModeller bg_code = MaskCode.Valid | MaskCode.BackgroundUsed fg_code = MaskCode.Valid | MaskCode.Foreground strong_code = MaskCode.Valid | MaskCode.Strong modeller = Linear2dModeller() expanded_shoeboxes = flex.shoebox() detector = sweep.get_detector() zoffset = 0 if sweep.get_scan() is not None: zoffset = sweep.get_scan().get_array_range()[0] from libtbx.containers import OrderedDict class image_data_cache(object): def __init__(self, imageset, size=10): self.imageset = imageset self.size = size self._image_data = OrderedDict() def __getitem__(self, i): image_data = self._image_data.get(i) if image_data is None: image_data = self.imageset.get_raw_data(i) if len(self._image_data) >= self.size: # remove the oldest entry in the cache del self._image_data[self._image_data.keys()[0]] self._image_data[i] = image_data return image_data cache = image_data_cache(sweep) #cache = sweep # sort shoeboxes by centroid z frame = shoeboxes.centroid_all().position_frame() perm = flex.sort_permutation(frame) shoeboxes = shoeboxes.select(perm) buffer_size = 1 bg_plus_buffer = self.background_size + buffer_size import time t0 = time.time() for i, shoebox in enumerate(shoeboxes): if not flags[perm[i]]: continue panel = detector[shoebox.panel] trusted_range = panel.get_trusted_range() max_x, max_y = panel.get_image_size() bbox = shoebox.bbox x1, x2, y1, y2, z1, z2 = bbox # expand the bbox with a background region around the spotfinder shoebox # perhaps also should use a buffer zone between the shoebox and the # background region expanded_bbox = (max(0, x1-bg_plus_buffer), min(max_x, x2+bg_plus_buffer), max(0, y1-bg_plus_buffer), min(max_y, y2+bg_plus_buffer), z1, z2) shoebox.bbox = expanded_bbox t1 = time.time() logger.info("Time expand_shoebox: %s" %(t1-t0)) rlist = flex.reflection_table() rlist['shoebox'] = shoeboxes rlist['shoebox'].allocate() rlist['panel'] = shoeboxes.panels() rlist['bbox'] = shoeboxes.bounding_boxes() t0 = time.time() rlist.extract_shoeboxes(sweep) t1 = time.time() shoeboxes = rlist['shoebox'] shoeboxes.flatten() t0 = time.time() for i, shoebox in enumerate(shoeboxes): if not flags[perm[i]]: continue panel = detector[shoebox.panel] trusted_range = panel.get_trusted_range() max_x, max_y = panel.get_image_size() ex1, ex2, ey1, ey2, ez1, ez2 = shoebox.bbox data = shoebox.data mask = flex.bool(data.accessor(), False) for i_y, y in enumerate(range(ey1, ey2)): for i_x, x in enumerate(range(ex1, ex2)): value = data[0, i_y, i_x] if (y >= (ey1+buffer_size) and y < (ey2-buffer_size) and x >= (ex1+buffer_size) and x < (ex2-buffer_size)): mask[0, i_y, i_x] = False # foreground elif value > trusted_range[0] and value < trusted_range[1]: mask[0, i_y, i_x] = True # background model = modeller.create(data.as_double(), mask) d, a, b = model.params()[:3] c = -1 if abs(a) > self.gradient_cutoff or abs(b) > self.gradient_cutoff: flags[perm[i]] = False t1 = time.time() return flags