def _extract_or_read_imagesets(params): """ Return a list of ImageSets, importing them via alternative means if necessary. The "Alternative Means" means via params.input.template or .directory, if the images to import haven't been specified directly. Args: params: The phil.scope_extract from dials.import Returns: A list of ImageSet objects """ # Get the experiments experiments = flatten_experiments(params.input.experiments) # Check we have some filenames if len(experiments) == 0: # FIXME Should probably make this smarter since it requires editing here # and in dials.import phil scope try: format_kwargs = { "dynamic_shadowing": params.format.dynamic_shadowing, "multi_panel": params.format.multi_panel, } except AttributeError: format_kwargs = None # Check if a template has been set and print help if not, otherwise try to # import the images based on the template input if len(params.input.template) > 0: importer = ExperimentListTemplateImporter( params.input.template, image_range=params.geometry.scan.image_range, format_kwargs=format_kwargs, ) experiments = importer.experiments if len(experiments) == 0: raise Sorry("No experiments found matching template %s" % params.input.experiments) elif len(params.input.directory) > 0: experiments = ExperimentListFactory.from_filenames( params.input.directory, format_kwargs=format_kwargs) if len(experiments) == 0: raise Sorry("No experiments found in directories %s" % params.input.directory) else: raise Sorry("No experiments found") # TODO (Nick): This looks redundant as the experiments are immediately discarded. # verify this, and remove if it is. if params.identifier_type: generate_experiment_identifiers(experiments, params.identifier_type) # Get a list of all imagesets imageset_list = experiments.imagesets() # Return the experiments return imageset_list
def __call__(self): """ Import the experiments """ # Get the experiments experiments = flatten_experiments(self.params.input.experiments) # Check we have some filenames if len(experiments) == 0: # FIXME Should probably make this smarter since it requires editing here # and in dials.import phil scope try: format_kwargs = { "dynamic_shadowing": self.params.format.dynamic_shadowing, "multi_panel": self.params.format.multi_panel, } except AttributeError: format_kwargs = None # Check if a template has been set and print help if not, otherwise try to # import the images based on the template input if len(self.params.input.template) > 0: importer = ExperimentListTemplateImporter( self.params.input.template, image_range=self.params.geometry.scan.image_range, format_kwargs=format_kwargs, ) experiments = importer.experiments if len(experiments) == 0: raise Sorry( "No experiments found matching template %s" % self.params.input.experiments ) elif len(self.params.input.directory) > 0: experiments = ExperimentListFactory.from_filenames( self.params.input.directory, format_kwargs=format_kwargs ) if len(experiments) == 0: raise Sorry( "No experiments found in directories %s" % self.params.input.directory ) else: raise Sorry("No experiments found") if self.params.identifier_type: generate_experiment_identifiers(experiments, self.params.identifier_type) # Get a list of all imagesets imageset_list = experiments.imagesets() # Return the experiments return imageset_list
def index(self): # most of this is the same as dials.algorithms.indexing.indexer.indexer_base.index(), with some stills # specific modifications (don't re-index after choose best orientation matrix, but use the indexing from # choose best orientation matrix, also don't use macrocycles) of refinement after indexing. # 2017 update: do accept multiple lattices per shot experiments = ExperimentList() while True: self.d_min = self.params.refinement_protocol.d_min_start max_lattices = self.params.multiple_lattice_search.max_lattices if max_lattices is not None and len(experiments) >= max_lattices: break if len(experiments) > 0: cutoff_fraction = ( self.params.multiple_lattice_search.recycle_unindexed_reflections_cutoff ) d_spacings = 1 / self.reflections["rlp"].norms() d_min_indexed = flex.min(d_spacings.select(self.indexed_reflections)) min_reflections_for_indexing = cutoff_fraction * len( self.reflections.select(d_spacings > d_min_indexed) ) crystal_ids = self.reflections.select(d_spacings > d_min_indexed)["id"] if (crystal_ids == -1).count(True) < min_reflections_for_indexing: logger.info( "Finish searching for more lattices: %i unindexed reflections remaining." % (min_reflections_for_indexing) ) break n_lattices_previous_cycle = len(experiments) # index multiple lattices per shot if len(experiments) == 0: new = self.find_lattices() generate_experiment_identifiers(new) experiments.extend(new) if len(experiments) == 0: raise DialsIndexError("No suitable lattice could be found.") else: try: new = self.find_lattices() generate_experiment_identifiers(new) experiments.extend(new) except Exception as e: logger.info("Indexing remaining reflections failed") logger.debug( "Indexing remaining reflections failed, exception:\n" + str(e) ) # reset reflection lattice flags # the lattice a given reflection belongs to: a value of -1 indicates # that a reflection doesn't belong to any lattice so far self.reflections["id"] = flex.int(len(self.reflections), -1) self.index_reflections(experiments, self.reflections) if len(experiments) == n_lattices_previous_cycle: # no more lattices found break if ( not self.params.stills.refine_candidates_with_known_symmetry and self.params.known_symmetry.space_group is not None ): self._apply_symmetry_post_indexing( experiments, self.reflections, n_lattices_previous_cycle ) # discard nearly overlapping lattices on the same shot if self._check_have_similar_crystal_models(experiments): break self.indexed_reflections = self.reflections["id"] > -1 if self.d_min is None: sel = self.reflections["id"] <= -1 else: sel = flex.bool(len(self.reflections), False) lengths = 1 / self.reflections["rlp"].norms() isel = (lengths >= self.d_min).iselection() sel.set_selected(isel, True) sel.set_selected(self.reflections["id"] > -1, False) self.unindexed_reflections = self.reflections.select(sel) reflections_for_refinement = self.reflections.select( self.indexed_reflections ) if len(self.params.stills.isoforms) > 0: logger.info("") logger.info("#" * 80) logger.info("Starting refinement") logger.info("#" * 80) logger.info("") isoform_experiments = ExperimentList() isoform_reflections = flex.reflection_table() # Note, changes to params after initial indexing. Cannot use tie to target when fixing the unit cell. self.all_params.refinement.reflections.outlier.algorithm = "null" self.all_params.refinement.parameterisation.crystal.fix = "cell" self.all_params.refinement.parameterisation.crystal.unit_cell.restraints.tie_to_target = ( [] ) for expt_id, experiment in enumerate(experiments): reflections = reflections_for_refinement.select( reflections_for_refinement["id"] == expt_id ) reflections["id"] = flex.int(len(reflections), 0) refiners = [] for isoform in self.params.stills.isoforms: iso_experiment = copy.deepcopy(experiment) crystal = iso_experiment.crystal if ( isoform.lookup_symbol != crystal.get_space_group().type().lookup_symbol() ): logger.info( "Crystal isoform lookup_symbol %s does not match isoform %s lookup_symbol %s" % ( crystal.get_space_group().type().lookup_symbol(), isoform.name, isoform.lookup_symbol, ) ) continue crystal.set_B(isoform.cell.fractionalization_matrix()) logger.info("Refining isoform %s" % isoform.name) refiners.append( e_refine( params=self.all_params, experiments=ExperimentList([iso_experiment]), reflections=reflections, graph_verbose=False, ) ) if len(refiners) == 0: raise DialsIndexError( "No isoforms had a lookup symbol that matched" ) positional_rmsds = [ math.sqrt(P.rmsds()[0] ** 2 + P.rmsds()[1] ** 2) for P in refiners ] logger.info( "Positional rmsds for all isoforms:" + str(positional_rmsds) ) minrmsd_mm = min(positional_rmsds) minindex = positional_rmsds.index(minrmsd_mm) logger.info( "The smallest rmsd is %5.1f um from isoform %s" % ( 1000.0 * minrmsd_mm, self.params.stills.isoforms[minindex].name, ) ) if self.params.stills.isoforms[minindex].rmsd_target_mm is not None: logger.info( "Asserting %f < %f" % ( minrmsd_mm, self.params.stills.isoforms[minindex].rmsd_target_mm, ) ) assert ( minrmsd_mm < self.params.stills.isoforms[minindex].rmsd_target_mm ) logger.info( "Acceptable rmsd for isoform %s." % (self.params.stills.isoforms[minindex].name) ) if len(self.params.stills.isoforms) == 2: logger.info( "Rmsd gain over the other isoform %5.1f um." % (1000.0 * abs(positional_rmsds[0] - positional_rmsds[1])) ) R = refiners[minindex] # Now one last check to see if direct beam is out of bounds if self.params.stills.isoforms[minindex].beam_restraint is not None: from scitbx import matrix refined_beam = matrix.col( R.get_experiments()[0] .detector[0] .get_beam_centre_lab(experiments[0].beam.get_s0())[0:2] ) known_beam = matrix.col( self.params.stills.isoforms[minindex].beam_restraint ) logger.info( "Asserting difference in refined beam center and expected beam center %f < %f" % ( (refined_beam - known_beam).length(), self.params.stills.isoforms[minindex].rmsd_target_mm, ) ) assert ( (refined_beam - known_beam).length() < self.params.stills.isoforms[minindex].rmsd_target_mm ) # future--circle of confusion could be given as a separate length in mm instead of reusing rmsd_target experiment = R.get_experiments()[0] experiment.crystal.identified_isoform = self.params.stills.isoforms[ minindex ].name isoform_experiments.append(experiment) reflections["id"] = flex.int(len(reflections), expt_id) isoform_reflections.extend(reflections) experiments = isoform_experiments reflections_for_refinement = isoform_reflections if self.params.refinement_protocol.mode == "repredict_only": from dials.algorithms.indexing.nave_parameters import NaveParameters from dials.algorithms.refinement.prediction.managed_predictors import ( ExperimentsPredictorFactory, ) refined_experiments, refined_reflections = ( experiments, reflections_for_refinement, ) ref_predictor = ExperimentsPredictorFactory.from_experiments( experiments, force_stills=True, spherical_relp=self.all_params.refinement.parameterisation.spherical_relp_model, ) ref_predictor(refined_reflections) refined_reflections["delpsical2"] = ( refined_reflections["delpsical.rad"] ** 2 ) for expt_id in range(len(refined_experiments)): refls = refined_reflections.select( refined_reflections["id"] == expt_id ) nv = NaveParameters( params=self.all_params, experiments=refined_experiments[expt_id : expt_id + 1], reflections=refls, refinery=None, graph_verbose=False, ) experiments[expt_id].crystal = nv() ref_predictor = ExperimentsPredictorFactory.from_experiments( experiments, force_stills=True, spherical_relp=self.all_params.refinement.parameterisation.spherical_relp_model, ) ref_predictor(refined_reflections) elif self.params.refinement_protocol.mode is None: refined_experiments, refined_reflections = ( experiments, reflections_for_refinement, ) else: try: refined_experiments, refined_reflections = self.refine( experiments, reflections_for_refinement ) except Exception as e: s = str(e) if len(experiments) == 1: raise DialsIndexRefineError(e.message) logger.info("Refinement failed:") logger.info(s) del experiments[-1] break self._unit_cell_volume_sanity_check(experiments, refined_experiments) self.refined_reflections = refined_reflections.select( refined_reflections["id"] > -1 ) for i, expt in enumerate(self.experiments): ref_sel = self.refined_reflections.select( self.refined_reflections["imageset_id"] == i ) ref_sel = ref_sel.select(ref_sel["id"] >= 0) for i_expt in set(ref_sel["id"]): refined_expt = refined_experiments[i_expt] expt.detector = refined_expt.detector expt.beam = refined_expt.beam expt.goniometer = refined_expt.goniometer expt.scan = refined_expt.scan refined_expt.imageset = expt.imageset if not ( self.all_params.refinement.parameterisation.beam.fix == "all" and self.all_params.refinement.parameterisation.detector.fix == "all" ): # Experimental geometry may have changed - re-map centroids to # reciprocal space self.reflections.map_centroids_to_reciprocal_space(self.experiments) # update for next cycle experiments = refined_experiments self.refined_experiments = refined_experiments if self.refined_experiments is None: raise DialsIndexRefineError("None of the experiments could refine.") # discard experiments with zero reflections after refinement id_set = set(self.refined_reflections["id"]) if len(id_set) < len(self.refined_experiments): filtered_refined_reflections = flex.reflection_table() for i in range(len(self.refined_experiments)): if i not in id_set: del self.refined_experiments[i] for old, new in zip(sorted(id_set), range(len(id_set))): subset = self.refined_reflections.select( self.refined_reflections["id"] == old ) subset["id"] = flex.int(len(subset), new) filtered_refined_reflections.extend(subset) self.refined_reflections = filtered_refined_reflections if len(self.refined_experiments) > 1: from dials.algorithms.indexing.compare_orientation_matrices import ( rotation_matrix_differences, ) logger.info( rotation_matrix_differences(self.refined_experiments.crystals()) ) logger.info("Final refined crystal models:") for i, crystal_model in enumerate(self.refined_experiments.crystals()): n_indexed = 0 for _ in experiments.where(crystal=crystal_model): n_indexed += (self.reflections["id"] == i).count(True) logger.info("model %i (%i reflections):" % (i + 1, n_indexed)) logger.info(crystal_model) if ( "xyzcal.mm" in self.refined_reflections ): # won't be there if refine_all_candidates = False and no isoforms self._xyzcal_mm_to_px(self.experiments, self.refined_reflections)
def index(self): experiments = ExperimentList() had_refinement_error = False have_similar_crystal_models = False while True: if had_refinement_error or have_similar_crystal_models: break max_lattices = self.params.multiple_lattice_search.max_lattices if max_lattices is not None and len(experiments) >= max_lattices: break if len(experiments) > 0: cutoff_fraction = (self.params.multiple_lattice_search. recycle_unindexed_reflections_cutoff) d_spacings = 1 / self.reflections["rlp"].norms() d_min_indexed = flex.min( d_spacings.select(self.indexed_reflections)) min_reflections_for_indexing = cutoff_fraction * len( self.reflections.select(d_spacings > d_min_indexed)) crystal_ids = self.reflections.select( d_spacings > d_min_indexed)["id"] if (crystal_ids == -1).count(True) < min_reflections_for_indexing: logger.info( "Finish searching for more lattices: %i unindexed reflections remaining." % ((crystal_ids == -1).count(True))) break n_lattices_previous_cycle = len(experiments) if self.d_min is None: self.d_min = self.params.refinement_protocol.d_min_start if len(experiments) == 0: new_expts = self.find_lattices() generate_experiment_identifiers(new_expts) experiments.extend(new_expts) else: try: new = self.find_lattices() generate_experiment_identifiers(new) experiments.extend(new) except DialsIndexError: logger.info("Indexing remaining reflections failed") if self.params.refinement_protocol.d_min_step is libtbx.Auto: n_cycles = self.params.refinement_protocol.n_macro_cycles if self.d_min is None or n_cycles == 1: self.params.refinement_protocol.d_min_step = 0 else: d_spacings = 1 / self.reflections["rlp"].norms() d_min_all = flex.min(d_spacings) self.params.refinement_protocol.d_min_step = ( self.d_min - d_min_all) / (n_cycles - 1) logger.info("Using d_min_step %.1f" % self.params.refinement_protocol.d_min_step) if len(experiments) == 0: raise DialsIndexError("No suitable lattice could be found.") elif len(experiments) == n_lattices_previous_cycle: # no more lattices found break for i_cycle in range( self.params.refinement_protocol.n_macro_cycles): if (i_cycle > 0 and self.d_min is not None and self.params.refinement_protocol.d_min_step > 0): d_min = self.d_min - self.params.refinement_protocol.d_min_step d_min = max(d_min, 0) if self.params.refinement_protocol.d_min_final is not None: d_min = max( d_min, self.params.refinement_protocol.d_min_final) if d_min >= 0: self.d_min = d_min logger.info("Increasing resolution to %.2f Angstrom" % d_min) # reset reflection lattice flags # the lattice a given reflection belongs to: a value of -1 indicates # that a reflection doesn't belong to any lattice so far self.reflections["id"] = flex.int(len(self.reflections), -1) self.index_reflections(experiments, self.reflections) if i_cycle == 0 and self.params.known_symmetry.space_group is not None: self._apply_symmetry_post_indexing( experiments, self.reflections, n_lattices_previous_cycle) logger.info("\nIndexed crystal models:") self.show_experiments(experiments, self.reflections, d_min=self.d_min) if self._check_have_similar_crystal_models(experiments): have_similar_crystal_models = True break logger.info("") logger.info("#" * 80) logger.info("Starting refinement (macro-cycle %i)" % (i_cycle + 1)) logger.info("#" * 80) logger.info("") self.indexed_reflections = self.reflections["id"] > -1 sel = flex.bool(len(self.reflections), False) lengths = 1 / self.reflections["rlp"].norms() if self.d_min is not None: isel = (lengths <= self.d_min).iselection() sel.set_selected(isel, True) sel.set_selected(self.reflections["id"] == -1, True) self.reflections.unset_flags(sel, self.reflections.flags.indexed) self.unindexed_reflections = self.reflections.select(sel) reflections_for_refinement = self.reflections.select( self.indexed_reflections) if self.params.refinement_protocol.mode == "repredict_only": refined_experiments, refined_reflections = ( experiments, reflections_for_refinement, ) from dials.algorithms.refinement.prediction.managed_predictors import ( ExperimentsPredictorFactory, ) ref_predictor = ExperimentsPredictorFactory.from_experiments( experiments, spherical_relp=self.all_params.refinement. parameterisation.spherical_relp_model, ) ref_predictor(refined_reflections) else: try: refined_experiments, refined_reflections = self.refine( experiments, reflections_for_refinement) except (DialsRefineConfigError, DialsRefineRuntimeError) as e: if len(experiments) == 1: raise DialsIndexRefineError(str(e)) had_refinement_error = True logger.info("Refinement failed:") logger.info(e) del experiments[-1] # remove experiment id from the reflections associated # with this deleted experiment - indexed flag removed # below last = len(experiments) sel = refined_reflections["id"] == last logger.info("Removing %d reflections with id %d" % (sel.count(True), last)) refined_reflections["id"].set_selected(sel, -1) break self._unit_cell_volume_sanity_check(experiments, refined_experiments) self.refined_reflections = refined_reflections self.refined_reflections.unset_flags( self.refined_reflections["id"] < 0, self.refined_reflections.flags.indexed, ) for i, expt in enumerate(self.experiments): ref_sel = self.refined_reflections.select( self.refined_reflections["imageset_id"] == i) ref_sel = ref_sel.select(ref_sel["id"] >= 0) for i_expt in set(ref_sel["id"]): refined_expt = refined_experiments[i_expt] expt.detector = refined_expt.detector expt.beam = refined_expt.beam expt.goniometer = refined_expt.goniometer expt.scan = refined_expt.scan refined_expt.imageset = expt.imageset if not (self.all_params.refinement.parameterisation.beam.fix == "all" and self.all_params.refinement. parameterisation.detector.fix == "all"): # Experimental geometry may have changed - re-map centroids to # reciprocal space self.reflections.map_centroids_to_reciprocal_space( self.experiments) # update for next cycle experiments = refined_experiments self.refined_experiments = refined_experiments logger.info("\nRefined crystal models:") self.show_experiments(self.refined_experiments, self.reflections, d_min=self.d_min) if (i_cycle >= 2 and self.d_min == self.params.refinement_protocol.d_min_final): logger.info( "Target d_min_final reached: finished with refinement") break if self.refined_experiments is None: raise DialsIndexRefineError( "None of the experiments could refine.") if len(self.refined_experiments) > 1: from dials.algorithms.indexing.compare_orientation_matrices import ( rotation_matrix_differences, ) logger.info( rotation_matrix_differences( self.refined_experiments.crystals())) self._xyzcal_mm_to_px(self.refined_experiments, self.refined_reflections)
def __call__(self, imageset_list): """ Transform the metadata """ # Import the lookup data lookup = self.import_lookup_data(self.params) # Convert all to ImageGrid if self.params.input.as_grid_scan: imageset_list = self.convert_to_grid_scan(imageset_list, self.params) # Create the experiments experiments = ExperimentList() # Loop through imagesets for imageset in imageset_list: # Set the external lookups imageset = self.update_lookup(imageset, lookup) # Update the geometry for updater in self.update_geometry: imageset = updater(imageset) # Check beam and detector are present if imageset.get_beam() is None or imageset.get_detector() is None: raise Sorry( """ Imageset contains no beam or detector model. This means you will be unable to process your data. Possible causes of this error are: - A problem reading the images with one of the dxtbx format classes - A lack of header information in the file itself. You can override this by specifying the metadata as geometry parameters """ ) # Check if dx and dy are set if [ imageset.external_lookup.dx.filename, imageset.external_lookup.dy.filename, ].count(None) == 0: imageset.update_detector_px_mm_data() elif [ imageset.external_lookup.dx.filename, imageset.external_lookup.dy.filename, ].count(None) == 1: raise Sorry( """ Only 1 offset map is set. Need to set both dx and d """ ) # Append to new imageset list if isinstance(imageset, ImageSequence): if imageset.get_scan().is_still(): # make lots of experiments all pointing at one # image set # check if user has overridden the input - if yes, recall # that these are in people numbers (1...) and are inclusive if self.params.geometry.scan.image_range: user_start, user_end = self.params.geometry.scan.image_range offset = imageset.get_scan().get_array_range()[0] start, end = user_start - 1, user_end else: start, end = imageset.get_scan().get_array_range() offset = 0 for j in range(start, end): subset = imageset[j - offset : j - offset + 1] experiments.append( Experiment( imageset=imageset, beam=imageset.get_beam(), detector=imageset.get_detector(), goniometer=imageset.get_goniometer(), scan=subset.get_scan(), crystal=None, ) ) else: # have just one experiment experiments.append( Experiment( imageset=imageset, beam=imageset.get_beam(), detector=imageset.get_detector(), goniometer=imageset.get_goniometer(), scan=imageset.get_scan(), crystal=None, ) ) else: for i in range(len(imageset)): experiments.append( Experiment( imageset=imageset[i : i + 1], beam=imageset.get_beam(i), detector=imageset.get_detector(i), goniometer=imageset.get_goniometer(i), scan=imageset.get_scan(i), crystal=None, ) ) if self.params.identifier_type: generate_experiment_identifiers(experiments, self.params.identifier_type) # Return the experiments return experiments
def run(self, args=None): """Execute the script.""" # Parse the command line params, options = self.parser.parse_args(args=args, show_diff_phil=False) if __name__ == "__main__": # Configure the logging log.config(verbosity=options.verbose, logfile=params.output.log) logger.info(dials_version()) # Log the diff phil diff_phil = self.parser.diff_phil.as_str() if diff_phil != "": logger.info("The following parameters have been modified:\n") logger.info(diff_phil) # Ensure we have a data block experiments = flatten_experiments(params.input.experiments) # did input have identifier? had_identifiers = False if all(i != "" for i in experiments.identifiers()): had_identifiers = True else: generate_experiment_identifiers( experiments ) # add identifier e.g. if coming straight from images if len(experiments) == 0: self.parser.print_help() return # If maximum_trusted_value assigned, use this temporarily for the # spot finding if params.maximum_trusted_value is not None: logger.info("Overriding maximum trusted value to %.1f", params.maximum_trusted_value) input_trusted_ranges = {} for _d, detector in enumerate(experiments.detectors()): for _p, panel in enumerate(detector): trusted = panel.get_trusted_range() input_trusted_ranges[(_d, _p)] = trusted panel.set_trusted_range( (trusted[0], params.maximum_trusted_value)) # Loop through all the imagesets and find the strong spots reflections = flex.reflection_table.from_observations( experiments, params) # Add n_signal column - before deleting shoeboxes good = MaskCode.Foreground | MaskCode.Valid reflections["n_signal"] = reflections["shoebox"].count_mask_values( good) # Delete the shoeboxes if not params.output.shoeboxes: del reflections["shoebox"] # ascii spot count per image plot - per imageset imagesets = [] for i, experiment in enumerate(experiments): if experiment.imageset not in imagesets: imagesets.append(experiment.imageset) for imageset in imagesets: selected = flex.bool(reflections.nrows(), False) for i, experiment in enumerate(experiments): if experiment.imageset is not imageset: continue selected.set_selected(reflections["id"] == i, True) ascii_plot = spot_counts_per_image_plot( reflections.select(selected)) if len(ascii_plot): logger.info( "\nHistogram of per-image spot count for imageset %i:" % i) logger.info(ascii_plot) # Save the reflections to file logger.info("\n" + "-" * 80) # If started with images and not saving experiments, then remove id mapping # as the experiment linked to will no longer exists after exit. if not had_identifiers: if not params.output.experiments: for k in reflections.experiment_identifiers().keys(): del reflections.experiment_identifiers()[k] reflections.as_file(params.output.reflections) logger.info("Saved {} reflections to {}".format( len(reflections), params.output.reflections)) # Reset the trusted ranges if params.maximum_trusted_value is not None: for _d, detector in enumerate(experiments.detectors()): for _p, panel in enumerate(detector): trusted = input_trusted_ranges[(_d, _p)] panel.set_trusted_range(trusted) # Save the experiments if params.output.experiments: logger.info("Saving experiments to {}".format( params.output.experiments)) experiments.as_file(params.output.experiments) # Print some per image statistics if params.per_image_statistics: for i, experiment in enumerate(experiments): logger.info("Number of centroids per image for imageset %i:", i) refl = reflections.select(reflections["id"] == i) refl.centroid_px_to_mm([experiment]) refl.map_centroids_to_reciprocal_space([experiment]) stats = per_image_analysis.stats_per_image( experiment, refl, resolution_analysis=False) logger.info(str(stats)) if params.output.experiments: return experiments, reflections else: return reflections
def run(self, args=None): """Execute the script.""" from dials.util.options import reflections_and_experiments_from_files # Parse the command line params, options = self.parser.parse_args(args, show_diff_phil=True) reflections, experiments = reflections_and_experiments_from_files( params.input.reflections, params.input.experiments ) # Try to load the models and data slice_exps = len(experiments) > 0 slice_refs = len(reflections) > 0 # Catch case of nothing to do if not slice_exps and not slice_refs: print("No suitable input provided") self.parser.print_help() return if reflections: if len(reflections) > 1: raise Sorry("Only one reflections list can be imported at present") reflections = reflections[0] # calculate frame numbers if needed if experiments: reflections = calculate_frame_numbers(reflections, experiments) # if we still don't have the right column give up if "xyzobs.px.value" not in reflections: raise Sorry( "These reflections do not have frame numbers set, and " "there are no experiments provided to calculate these." ) # set trivial case where no scan range is provided at all if not params.image_range: params.image_range = [None] # check if slicing into blocks if params.block_size is not None: if not slice_exps: raise Sorry( "For slicing into blocks, an experiment file must be provided" ) if len(experiments) > 1: raise Sorry("For slicing into blocks please provide a single scan only") scan = experiments[0].scan # Having extracted the scan, calculate the blocks params.image_range = calculate_block_ranges(scan, params.block_size) # Do the slicing then recombine sliced = [ slice_experiments(experiments, [sr])[0] for sr in params.image_range ] generate_experiment_identifiers(sliced) sliced_experiments = ExperimentList(sliced) # slice reflections if present if slice_refs: sliced = [ slice_reflections(reflections, [sr]) for sr in params.image_range ] sliced_reflections = flex.reflection_table() identifiers = sliced_experiments.identifiers() # resetting experiment identifiers for i, rt in enumerate(sliced): for k in rt.experiment_identifiers().keys(): del rt.experiment_identifiers()[k] rt["id"] = flex.int(rt.size(), i) # set id rt.experiment_identifiers()[i] = identifiers[i] sliced_reflections.extend(rt) else: # slice each dataset into the requested subset if slice_exps: sliced_experiments = slice_experiments(experiments, params.image_range) if slice_refs: sliced_reflections = slice_reflections(reflections, params.image_range) # Save sliced experiments if slice_exps: output_experiments_filename = params.output.experiments_filename if output_experiments_filename is None: # take first filename as template bname = basename(params.input.experiments[0].filename) bname = splitext(bname)[0] if not bname: bname = "experiments" if len(params.image_range) == 1 and params.image_range[0] is not None: ext = "_{}_{}.expt".format(*params.image_range[0]) else: ext = "_sliced.expt" output_experiments_filename = bname + ext print(f"Saving sliced experiments to {output_experiments_filename}") sliced_experiments.as_file(output_experiments_filename) # Save sliced reflections if slice_refs: output_reflections_filename = params.output.reflections_filename if output_reflections_filename is None: # take first filename as template bname = basename(params.input.reflections[0].filename) bname = splitext(bname)[0] if not bname: bname = "reflections" if len(params.image_range) == 1 and params.image_range[0] is not None: ext = "_{}_{}.refl".format(*params.image_range[0]) else: ext = "_sliced.refl" output_reflections_filename = bname + ext print(f"Saving sliced reflections to {output_reflections_filename}") sliced_reflections.as_file(output_reflections_filename) return