Beispiel #1
0
def tst_set_mosflm_beam_centre(detector):
  from scitbx import matrix
  from dxtbx.model import Beam
  wavelength = 1
  panel = detector[0]
  detector_normal = matrix.col(panel.get_normal())
  origin = matrix.col(panel.get_origin())
  fast_axis = matrix.col(panel.get_fast_axis())
  slow_axis = matrix.col(panel.get_slow_axis())
  image_size = panel.get_image_size_mm()

  s0 = (1.0/wavelength) * detector_normal
  beam = Beam(-s0.normalize(), wavelength)

  beam_centre = matrix.col(panel.get_beam_centre(beam.get_s0()))
  origin_shift = matrix.col((1, 0.5))
  new_beam_centre = beam_centre + origin_shift

  new_mosflm_beam_centre = tuple(reversed(new_beam_centre))

  from dxtbx.model.detector_helpers import set_mosflm_beam_centre
  set_mosflm_beam_centre(detector, beam, new_mosflm_beam_centre)

  assert (matrix.col(panel.get_beam_centre(beam.get_s0())) -
          matrix.col(tuple(reversed(new_mosflm_beam_centre)))).length() < 1e-6

  print 'OK'
Beispiel #2
0
 def set_beam_centre(self, beam_centre):
     try:
         set_mosflm_beam_centre(self.get_detector(), self.get_beam_obj(),
                                beam_centre)
         self._fp_beam_prov = "user"
     except AssertionError as e:
         logger.debug("Error setting mosflm beam centre: %s" % e)
Beispiel #3
0
def tst_set_mosflm_beam_centre(detector):
    from scitbx import matrix
    from dxtbx.model import Beam
    wavelength = 1
    panel = detector[0]
    detector_normal = matrix.col(panel.get_normal())
    origin = matrix.col(panel.get_origin())
    fast_axis = matrix.col(panel.get_fast_axis())
    slow_axis = matrix.col(panel.get_slow_axis())
    image_size = panel.get_image_size_mm()

    s0 = (1.0 / wavelength) * detector_normal
    beam = Beam(-s0.normalize(), wavelength)

    beam_centre = matrix.col(panel.get_beam_centre(beam.get_s0()))
    origin_shift = matrix.col((1, 0.5))
    new_beam_centre = beam_centre + origin_shift

    new_mosflm_beam_centre = tuple(reversed(new_beam_centre))

    from dxtbx.model.detector_helpers import set_mosflm_beam_centre
    set_mosflm_beam_centre(detector, beam, new_mosflm_beam_centre)

    assert (matrix.col(panel.get_beam_centre(beam.get_s0())) - matrix.col(
        tuple(reversed(new_mosflm_beam_centre)))).length() < 1e-6
Beispiel #4
0
def test_set_mosflm_beam_centre(detector):
    wavelength = 1.0
    panel = detector[0]
    detector_normal = matrix.col(panel.get_normal())
    _ = matrix.col(panel.get_origin())
    _ = matrix.col(panel.get_fast_axis())
    _ = matrix.col(panel.get_slow_axis())
    _ = panel.get_image_size_mm()

    s0 = (1.0 / wavelength) * detector_normal
    beam = Beam(-s0.normalize(), wavelength)

    beam_centre = matrix.col(panel.get_beam_centre(beam.get_s0()))
    origin_shift = matrix.col((1, 0.5))
    new_beam_centre = beam_centre + origin_shift

    new_mosflm_beam_centre = tuple(reversed(new_beam_centre))

    set_mosflm_beam_centre(detector, beam, new_mosflm_beam_centre)

    assert (
        matrix.col(panel.get_beam_centre(beam.get_s0()))
        - matrix.col(tuple(reversed(new_mosflm_beam_centre)))
    ).length() < 1e-6

    # test resolution methods
    beam = Beam(direction=(0, 0, 1), wavelength=1.0)
    d_min1 = detector.get_max_resolution(beam.get_s0())
    d_min2 = detector.get_max_inscribed_resolution(beam.get_s0())
    assert d_min1 < d_min2
Beispiel #5
0
 def set_beam_centre(self, beam_centre):
     from dxtbx.model.detector_helpers import set_mosflm_beam_centre
     try:
         set_mosflm_beam_centre(self.get_detector(), self.get_beam_obj(),
                                beam_centre)
         self._fp_beam_prov = 'user'
     except AssertionError as e:
         Debug.write('Error setting mosflm beam centre: %s' % e)
Beispiel #6
0
 def set_beam_centre(self, beam_centre):
   from dxtbx.model.detector_helpers import set_mosflm_beam_centre
   try:
     set_mosflm_beam_centre(self.get_detector(),
                            self.get_beam_obj(),
                            beam_centre)
     self._fp_beam_prov = 'user'
   except AssertionError, e:
     Debug.write('Error setting mosflm beam centre: %s' % e)
Beispiel #7
0
  def __call__(self, imageset):
    '''
    Replace the geometry

    '''
    from dxtbx.model.detector_helpers import set_mosflm_beam_centre
    set_mosflm_beam_centre(
      imageset.get_detector(),
      imageset.get_beam(),
      self.params.geometry.mosflm_beam_centre)
    return imageset
Beispiel #8
0
  def __call__(self, imageset):
    '''
    Replace the geometry

    '''
    from dxtbx.model.detector_helpers import set_mosflm_beam_centre
    set_mosflm_beam_centre(
      imageset.get_detector(),
      imageset.get_beam(),
      self.params.geometry.mosflm_beam_centre)
    return imageset
Beispiel #9
0
    def from_phil(params, reference=None, beam=None):
        """
        Convert phil parameters into detector model

        """
        from dxtbx.model.detector_helpers import set_detector_distance
        from dxtbx.model.detector_helpers import set_mosflm_beam_centre
        from dxtbx.model.detector_helpers import set_slow_fast_beam_centre_mm

        # Check the input. If no reference detector is provided then
        # Create the detector model from scratch from the parameters
        if reference is None:
            detector = DetectorFactory.generate_from_phil(params, beam)
        else:
            detector = DetectorFactory.overwrite_from_phil(
                params, reference, beam)

        # If the distance is set
        if params.detector.distance is not None:
            set_detector_distance(detector, params.detector.distance)

        # If the mosflm beam centre is set then update
        if params.detector.mosflm_beam_centre is not None:
            assert beam is not None
            set_mosflm_beam_centre(detector, beam,
                                   params.detector.mosflm_beam_centre)

        # If the slow fast beam centre is set then update
        if params.detector.slow_fast_beam_centre is not None:
            panel_id = 0
            if len(params.detector.slow_fast_beam_centre) > 2:
                panel_id = params.detector.slow_fast_beam_centre[2]
            if panel_id >= len(detector):
                from libtbx.utils import Sorry

                raise Sorry(
                    "Detector does not have panel index {0}".format(panel_id))
            px_size_f, px_size_s = detector[0].get_pixel_size()
            slow_fast_beam_centre_mm = (
                params.detector.slow_fast_beam_centre[0] * px_size_s,
                params.detector.slow_fast_beam_centre[1] * px_size_f,
            )
            assert beam is not None
            set_slow_fast_beam_centre_mm(detector,
                                         beam,
                                         slow_fast_beam_centre_mm,
                                         panel_id=panel_id)

        # Return the model
        return detector
 def update_settings(self, *args, **kwds):
   detector = self.imagesets[0].get_detector()
   beam = self.imagesets[0].get_beam()
   s0 = beam.get_s0()
   try:
     panel_id, beam_centre = detector.get_ray_intersection(beam.get_s0())
   except RuntimeError:
     pass
   else:
     if self.settings.beam_centre != beam_centre:
       from dxtbx.model.detector_helpers import set_mosflm_beam_centre
       set_mosflm_beam_centre(detector, beam, tuple(reversed(
         self.settings.beam_centre)))
       self.imagesets[0].set_detector(detector)
       self.imagesets[0].set_beam(beam)
   self.map_points_to_reciprocal_space()
   self.set_points()
   self.viewer.update_settings(*args, **kwds)
Beispiel #11
0
 def update_settings(self, *args, **kwds):
     detector = self.imagesets[0].get_detector()
     beam = self.imagesets[0].get_beam()
     s0 = beam.get_s0()
     try:
         panel_id, beam_centre = detector.get_ray_intersection(
             beam.get_s0())
     except RuntimeError:
         pass
     else:
         if self.settings.beam_centre != beam_centre:
             from dxtbx.model.detector_helpers import set_mosflm_beam_centre
             set_mosflm_beam_centre(
                 detector, beam, tuple(reversed(self.settings.beam_centre)))
             self.imagesets[0].set_detector(detector)
             self.imagesets[0].set_beam(beam)
     self.map_points_to_reciprocal_space()
     self.set_points()
     self.viewer.update_settings(*args, **kwds)
Beispiel #12
0
    def from_phil(params, reference=None, beam=None):
        '''
    Convert phil parameters into detector model

    '''
        from dxtbx.model.detector_helpers import set_detector_distance
        from dxtbx.model.detector_helpers import set_mosflm_beam_centre

        # Check the input. If no reference detector is provided then
        # Create the detector model from scratch from the parameters
        if reference is None:
            detector = DetectorFactory.generate_from_phil(params, beam)
        else:
            detector = DetectorFactory.overwrite_from_phil(
                params, reference, beam)

        # If the distance is set
        if params.detector.distance is not None:
            set_detector_distance(detector, params.detector.distance)

        # If the mosflm beam centre is set then update
        if params.detector.mosflm_beam_centre is not None:
            assert beam is not None
            set_mosflm_beam_centre(detector, beam,
                                   params.detector.mosflm_beam_centre)

        # If the slow fast beam centre is set then update
        if params.detector.slow_fast_beam_centre is not None:
            assert beam is not None
            beam_s, beam_f = params.detector.slow_fast_beam_centre[0:2]
            pnl = 0
            if len(params.detector.slow_fast_beam_centre) > 2:
                pnl = params.detector.slow_fast_beam_centre[2]
            try:
                p = detector[pnl]
            except RuntimeError:
                raise Sorry(
                    'Detector does not have panel index {0}'.format(pnl))
            beam.set_unit_s0(p.get_pixel_lab_coord((beam_f, beam_s)))

        # Return the model
        return detector
Beispiel #13
0
    def load_models(self, imagesets, reflections):
        self.imagesets = imagesets
        self.reflections_input = reflections
        if self.imagesets[0].get_goniometer() is not None:
            self.viewer.set_rotation_axis(
                self.imagesets[0].get_goniometer().get_rotation_axis())
        self.viewer.set_beam_vector(self.imagesets[0].get_beam().get_s0())

        detector = self.imagesets[0].get_detector()
        beam = self.imagesets[0].get_beam()
        if self.settings.beam_centre is None:
            try:
                panel_id, self.settings.beam_centre \
                  = detector.get_ray_intersection(beam.get_s0())
            except RuntimeError:
                pass
        else:
            from dxtbx.model.detector_helpers import set_mosflm_beam_centre
            set_mosflm_beam_centre(detector, beam,
                                   tuple(reversed(self.settings.beam_centre)))
        self.map_points_to_reciprocal_space()
        self.set_points()
  def load_models(self, imagesets, reflections):
    self.imagesets = imagesets
    self.reflections_input = reflections
    if self.imagesets[0].get_goniometer() is not None:
      self.viewer.set_rotation_axis(
        self.imagesets[0].get_goniometer().get_rotation_axis())
    self.viewer.set_beam_vector(self.imagesets[0].get_beam().get_s0())

    detector = self.imagesets[0].get_detector()
    beam = self.imagesets[0].get_beam()
    if self.settings.beam_centre is None:
      try:
        panel_id, self.settings.beam_centre \
          = detector.get_ray_intersection(beam.get_s0())
      except RuntimeError:
        pass
    else:
      from dxtbx.model.detector_helpers import set_mosflm_beam_centre
      set_mosflm_beam_centre(detector, beam, tuple(reversed(
        self.settings.beam_centre)))
    self.map_points_to_reciprocal_space()
    self.set_points()
Beispiel #15
0
    def __init__(
        self,
        name,
        wavelength,
        sample,
        directory=None,
        image=None,
        beam=None,
        reversephi=False,
        distance=None,
        gain=0.0,
        dmin=0.0,
        dmax=0.0,
        polarization=0.0,
        frames_to_process=None,
        user_lattice=None,
        user_cell=None,
        epoch=0,
        ice=False,
        excluded_regions=None,
    ):
        """Create a new sweep named name, belonging to XWavelength object
        wavelength, representing the images in directory starting with image,
        with beam centre optionally defined."""
        if excluded_regions is None:
            excluded_regions = []

        # FIXME bug 2221 if DIRECTORY starts with ~/ or ~graeme (say) need to
        # interpret this properly - e.g. map it to a full PATH.

        directory = expand_path(directory)

        self._name = name
        self._wavelength = wavelength
        self.sample = sample
        self._directory = directory
        self._image = image
        self._reversephi = reversephi
        self._epoch = epoch
        self._user_lattice = user_lattice
        self._user_cell = user_cell
        self._header = {}
        self._resolution_high = dmin
        self._resolution_low = dmax
        self._ice = ice
        self._excluded_regions = excluded_regions
        self._imageset = None

        # FIXME in here also need to be able to accumulate the total
        # dose from all experimental measurements (complex) and provide
        # a _epoch_to_dose dictionary or some such... may be fiddly as
        # this will need to parse across multiple templates. c/f Bug # 2798

        self._epoch_to_image = {}
        self._image_to_epoch = {}

        # to allow first, last image for processing to be
        # set... c/f integrater interface
        self._frames_to_process = frames_to_process

        # + derive template, list of images

        params = PhilIndex.get_python_object()
        if directory and image:
            self._template, self._directory = image2template_directory(
                os.path.join(directory, image))

            from xia2.Schema import load_imagesets

            imagesets = load_imagesets(
                self._template,
                self._directory,
                image_range=self._frames_to_process,
                reversephi=(params.xia2.settings.input.reverse_phi
                            or self._reversephi),
            )

            assert len(
                imagesets
            ) == 1, "one imageset expected, %d found" % len(imagesets)
            self._imageset = copy.deepcopy(imagesets[0])
            start, end = self._imageset.get_array_range()
            self._images = list(range(start + 1, end + 1))

            # FIXME in here check that (1) the list of images is continuous
            # and (2) that all of the images are readable. This should also
            # take into account frames_to_process if set.

            if self._frames_to_process is None:
                self._frames_to_process = min(self._images), max(self._images)

            start, end = self._frames_to_process

            error = False

            if params.general.check_image_files_readable:
                for j in range(start, end + 1):
                    if j not in self._images:
                        logger.debug("image %i missing for %s" %
                                     (j, self.get_imageset().get_template()))
                        error = True
                        continue
                    image_name = self.get_imageset().get_path(j - start)
                    if not os.access(image_name, os.R_OK):
                        logger.debug("image %s unreadable" % image_name)
                        error = True
                        continue

                if error:
                    raise RuntimeError("problem with sweep %s" % self._name)

            beam_ = self._imageset.get_beam()
            scan = self._imageset.get_scan()
            if wavelength is not None:

                # If the wavelength value is 0.0 then first set it to the header
                # value - note that this assumes that the header value is correct
                # (a reasonable assumption)
                if wavelength.get_wavelength() == 0.0:
                    wavelength.set_wavelength(beam_.get_wavelength())

                # FIXME 08/DEC/06 in here need to allow for the fact
                # that the wavelength in the image header could be wrong and
                # in fact it should be replaced with the input value -
                # through the user will need to be warned of this and
                # also everything using the FrameProcessor interface
                # will also have to respect this!

                if (math.fabs(beam_.get_wavelength() -
                              wavelength.get_wavelength()) > 0.0001):
                    logger.info(
                        "Header wavelength for sweep %s different"
                        " to assigned value (%4.2f vs. %4.2f)",
                        name,
                        beam_.get_wavelength(),
                        wavelength.get_wavelength(),
                    )

            # also in here look at the image headers to see if we can
            # construct a mapping between exposure epoch and image ...

            images = []

            if self._frames_to_process:
                start, end = self._frames_to_process
                for j in self._images:
                    if j >= start and j <= end:
                        images.append(j)
            else:
                images = self._images

            for j in images:
                epoch = scan.get_image_epoch(j)
                if epoch == 0.0:
                    epoch = float(
                        os.stat(self._imageset.get_path(j -
                                                        images[0])).st_mtime)
                self._epoch_to_image[epoch] = j
                self._image_to_epoch[j] = epoch

            epochs = self._epoch_to_image

            logger.debug("Exposure epoch for sweep %s: %d %d" %
                         (self._template, min(epochs), max(epochs)))

        self._input_imageset = copy.deepcopy(self._imageset)

        # + get the lattice - can this be a pointer, so that when
        #   this object updates lattice it is globally-for-this-crystal
        #   updated? The lattice included directly in here includes an
        #   exact unit cell for data reduction, the crystal lattice
        #   contains an approximate unit cell which should be
        #   from the unit cells from all sweeps contained in the
        #   XCrystal. FIXME should I be using a LatticeInfo object
        #   in here? See what the Indexer interface produces. ALT:
        #   just provide an Indexer implementation "hook".
        #   See Headnote 001 above. See also _get_indexer,
        #   _get_integrater below.

        self._indexer = None
        self._refiner = None
        self._integrater = None

        # I don't need this - it is equivalent to self.getWavelength(
        # ).getCrystal().getLattice()
        # self._crystal_lattice = None

        # this means that this module will have to present largely the
        # same interface as Indexer and Integrater so that the calls
        # can be appropriately forwarded.

        # finally configure the beam if set

        if beam is not None:
            from dxtbx.model.detector_helpers import set_mosflm_beam_centre

            try:
                set_mosflm_beam_centre(
                    self.get_imageset().get_detector(),
                    self.get_imageset().get_beam(),
                    beam,
                )
            except AssertionError as e:
                logger.debug("Error setting mosflm beam centre: %s" % e)

        self._beam_centre = beam
        self._distance = distance
        self._gain = gain
        self._polarization = polarization

        self._add_detector_identification_to_cif()
Beispiel #16
0
    def _index(self):
        '''Actually index the diffraction pattern. Note well that
    this is not going to compute the matrix...'''

        # acknowledge this program

        Citations.cite('labelit')
        Citations.cite('distl')

        #self.reset()

        _images = []
        for i in self._indxr_images:
            for j in i:
                if not j in _images:
                    _images.append(j)

        _images.sort()

        images_str = '%d' % _images[0]
        for i in _images[1:]:
            images_str += ', %d' % i

        cell_str = None
        if self._indxr_input_cell:
            cell_str = '%.2f %.2f %.2f %.2f %.2f %.2f' % \
                        self._indxr_input_cell

        if self._indxr_sweep_name:

            # then this is a proper autoindexing run - describe this
            # to the journal entry

            #if len(self._fp_directory) <= 50:
            #dirname = self._fp_directory
            #else:
            #dirname = '...%s' % self._fp_directory[-46:]
            dirname = os.path.dirname(self.get_imageset().get_template())

            Journal.block(
                'autoindexing', self._indxr_sweep_name, 'labelit', {
                    'images': images_str,
                    'target cell': cell_str,
                    'target lattice': self._indxr_input_lattice,
                    'template': self.get_imageset().get_template(),
                    'directory': dirname
                })

        if len(_images) > 4:
            raise RuntimeError('cannot use more than 4 images')

        from xia2.Wrappers.Labelit.LabelitIndex import LabelitIndex
        index = LabelitIndex()
        index.set_working_directory(self.get_working_directory())
        auto_logfiler(index)

        #task = 'Autoindex from images:'

        #for i in _images:
        #task += ' %s' % self.get_image_name(i)

        #self.set_task(task)

        Debug.write('Indexing from images:')
        for i in _images:
            index.add_image(self.get_image_name(i))
            Debug.write('%s' % self.get_image_name(i))

        xsweep = self.get_indexer_sweep()
        if xsweep is not None:
            if xsweep.get_distance() is not None:
                index.set_distance(xsweep.get_distance())
            #if self.get_wavelength_prov() == 'user':
            #index.set_wavelength(self.get_wavelength())
            if xsweep.get_beam_centre() is not None:
                index.set_beam_centre(xsweep.get_beam_centre())

        if self._refine_beam is False:
            index.set_refine_beam(False)
        else:
            index.set_refine_beam(True)
            index.set_beam_search_scope(self._beam_search_scope)

        if ((math.fabs(self.get_wavelength() - 1.54) < 0.01)
                or (math.fabs(self.get_wavelength() - 2.29) < 0.01)):
            index.set_Cu_KA_or_Cr_KA(True)

        #sweep = self.get_indexer_sweep_name()
        #FileHandler.record_log_file(
        #'%s INDEX' % (sweep), self.get_log_file())

        try:
            index.run()
        except RuntimeError as e:

            if self._refine_beam is False:
                raise e

            # can we improve the situation?

            if self._beam_search_scope < 4.0:
                self._beam_search_scope += 4.0

                # try repeating the indexing!

                self.set_indexer_done(False)
                return 'failed'

            # otherwise this is beyond redemption

            raise e

        self._solutions = index.get_solutions()

        # FIXME this needs to check the smilie status e.g.
        # ":)" or ";(" or "  ".

        # FIXME need to check the value of the RMSD and raise an
        # exception if the P1 solution has an RMSD > 1.0...

        # Change 27/FEB/08 to support user assigned spacegroups
        # (euugh!) have to "ignore" solutions with higher symmetry
        # otherwise the rest of xia will override us. Bummer.

        for i, solution in self._solutions.iteritems():
            if self._indxr_user_input_lattice:
                if (lattice_to_spacegroup(solution['lattice']) >
                        lattice_to_spacegroup(self._indxr_input_lattice)):
                    Debug.write('Ignoring solution: %s' % solution['lattice'])
                    del self._solutions[i]

        # check the RMSD from the triclinic unit cell
        if self._solutions[1]['rmsd'] > 1.0 and False:
            # don't know when this is useful - but I know when it is not!
            raise RuntimeError('high RMSD for triclinic solution')

        # configure the "right" solution
        self._solution = self.get_solution()

        # now store also all of the other solutions... keyed by the
        # lattice - however these should only be added if they
        # have a smiley in the appropriate record, perhaps?

        for solution in self._solutions.keys():
            lattice = self._solutions[solution]['lattice']
            if lattice in self._indxr_other_lattice_cell:
                if self._indxr_other_lattice_cell[lattice]['goodness'] < \
                   self._solutions[solution]['metric']:
                    continue

            self._indxr_other_lattice_cell[lattice] = {
                'goodness': self._solutions[solution]['metric'],
                'cell': self._solutions[solution]['cell']
            }

        self._indxr_lattice = self._solution['lattice']
        self._indxr_cell = tuple(self._solution['cell'])
        self._indxr_mosaic = self._solution['mosaic']

        lms = LabelitMosflmScript()
        lms.set_working_directory(self.get_working_directory())
        lms.set_solution(self._solution['number'])
        self._indxr_payload['mosflm_orientation_matrix'] = lms.calculate()

        # get the beam centre from the mosflm script - mosflm
        # may have inverted the beam centre and labelit will know
        # this!

        mosflm_beam_centre = lms.get_mosflm_beam()

        if mosflm_beam_centre:
            self._indxr_payload['mosflm_beam_centre'] = tuple(
                mosflm_beam_centre)

        import copy
        detector = copy.deepcopy(self.get_detector())
        beam = copy.deepcopy(self.get_beam())
        from dxtbx.model.detector_helpers import set_mosflm_beam_centre
        set_mosflm_beam_centre(detector, beam, mosflm_beam_centre)

        from xia2.Experts.SymmetryExpert import lattice_to_spacegroup_number
        from scitbx import matrix
        from cctbx import sgtbx, uctbx
        from dxtbx.model import CrystalFactory
        mosflm_matrix = matrix.sqr([
            float(i) for line in lms.calculate()
            for i in line.replace("-", " -").split()
        ][:9])

        space_group = sgtbx.space_group_info(
            lattice_to_spacegroup_number(self._solution['lattice'])).group()
        crystal_model = CrystalFactory.from_mosflm_matrix(
            mosflm_matrix,
            unit_cell=uctbx.unit_cell(tuple(self._solution['cell'])),
            space_group=space_group)

        from dxtbx.model import Experiment, ExperimentList
        experiment = Experiment(
            beam=beam,
            detector=detector,
            goniometer=self.get_goniometer(),
            scan=self.get_scan(),
            crystal=crystal_model,
        )

        experiment_list = ExperimentList([experiment])
        self.set_indexer_experiment_list(experiment_list)

        # also get an estimate of the resolution limit from the
        # labelit.stats_distl output... FIXME the name is wrong!

        lsd = LabelitStats_distl()
        lsd.set_working_directory(self.get_working_directory())
        lsd.stats_distl()

        resolution = 1.0e6
        for i in _images:
            stats = lsd.get_statistics(self.get_image_name(i))

            resol = 0.5 * (stats['resol_one'] + stats['resol_two'])

            if resol < resolution:
                resolution = resol

        self._indxr_resolution_estimate = resolution

        return 'ok'
    def _index(self):
        """Actually index the diffraction pattern. Note well that
        this is not going to compute the matrix..."""

        # acknowledge this program

        if not self._indxr_images:
            raise RuntimeError("No good spots found on any images")

        Citations.cite("labelit")
        Citations.cite("distl")

        _images = []
        for i in self._indxr_images:
            for j in i:
                if not j in _images:
                    _images.append(j)

        _images.sort()

        images_str = "%d" % _images[0]
        for i in _images[1:]:
            images_str += ", %d" % i

        cell_str = None
        if self._indxr_input_cell:
            cell_str = "%.2f %.2f %.2f %.2f %.2f %.2f" % self._indxr_input_cell

        if self._indxr_sweep_name:

            # then this is a proper autoindexing run - describe this
            # to the journal entry

            if len(self._fp_directory) <= 50:
                dirname = self._fp_directory
            else:
                dirname = "...%s" % self._fp_directory[-46:]

            Journal.block(
                "autoindexing",
                self._indxr_sweep_name,
                "labelit",
                {
                    "images": images_str,
                    "target cell": cell_str,
                    "target lattice": self._indxr_input_lattice,
                    "template": self._fp_template,
                    "directory": dirname,
                },
            )

        # auto_logfiler(self)

        from xia2.Wrappers.Labelit.LabelitIndex import LabelitIndex

        index = LabelitIndex()
        index.set_working_directory(self.get_working_directory())
        auto_logfiler(index)

        # task = 'Autoindex from images:'

        # for i in _images:
        # task += ' %s' % self.get_image_name(i)

        # self.set_task(task)

        # self.add_command_line('--index_only')

        Debug.write("Indexing from images:")
        for i in _images:
            index.add_image(self.get_image_name(i))
            Debug.write("%s" % self.get_image_name(i))

        if self._primitive_unit_cell:
            index.set_primitive_unit_cell(self._primitive_unit_cell)

        if self._indxr_input_cell:
            index.set_max_cell(1.25 * max(self._indxr_input_cell[:3]))

        xsweep = self.get_indexer_sweep()
        if xsweep is not None:
            if xsweep.get_distance() is not None:
                index.set_distance(xsweep.get_distance())
            # if self.get_wavelength_prov() == 'user':
            # index.set_wavelength(self.get_wavelength())
            if xsweep.get_beam_centre() is not None:
                index.set_beam_centre(xsweep.get_beam_centre())

        if self._refine_beam is False:
            index.set_refine_beam(False)
        else:
            index.set_refine_beam(True)
            index.set_beam_search_scope(self._beam_search_scope)

        if (math.fabs(self.get_wavelength() - 1.54) <
                0.01) or (math.fabs(self.get_wavelength() - 2.29) < 0.01):
            index.set_Cu_KA_or_Cr_KA(True)

        try:
            index.run()
        except RuntimeError as e:

            if self._refine_beam is False:
                raise e

            # can we improve the situation?

            if self._beam_search_scope < 4.0:
                self._beam_search_scope += 4.0

                # try repeating the indexing!

                self.set_indexer_done(False)
                return "failed"

            # otherwise this is beyond redemption

            raise e

        self._solutions = index.get_solutions()

        # FIXME this needs to check the smilie status e.g.
        # ":)" or ";(" or "  ".

        # FIXME need to check the value of the RMSD and raise an
        # exception if the P1 solution has an RMSD > 1.0...

        # Change 27/FEB/08 to support user assigned spacegroups
        # (euugh!) have to "ignore" solutions with higher symmetry
        # otherwise the rest of xia will override us. Bummer.

        for i, solution in self._solutions.iteritems():
            if self._indxr_user_input_lattice:
                if lattice_to_spacegroup(
                        solution["lattice"]) > lattice_to_spacegroup(
                            self._indxr_input_lattice):
                    Debug.write("Ignoring solution: %s" % solution["lattice"])
                    del self._solutions[i]

        # configure the "right" solution
        self._solution = self.get_solution()

        # now store also all of the other solutions... keyed by the
        # lattice - however these should only be added if they
        # have a smiley in the appropriate record, perhaps?

        for solution in self._solutions.keys():
            lattice = self._solutions[solution]["lattice"]
            if lattice in self._indxr_other_lattice_cell:
                if (self._indxr_other_lattice_cell[lattice]["goodness"] <
                        self._solutions[solution]["metric"]):
                    continue

            self._indxr_other_lattice_cell[lattice] = {
                "goodness": self._solutions[solution]["metric"],
                "cell": self._solutions[solution]["cell"],
            }

        self._indxr_lattice = self._solution["lattice"]
        self._indxr_cell = tuple(self._solution["cell"])
        self._indxr_mosaic = self._solution["mosaic"]

        lms = LabelitMosflmMatrix()
        lms.set_working_directory(self.get_working_directory())
        lms.set_solution(self._solution["number"])
        self._indxr_payload["mosflm_orientation_matrix"] = lms.calculate()

        # get the beam centre from the mosflm script - mosflm
        # may have inverted the beam centre and labelit will know
        # this!

        mosflm_beam_centre = lms.get_mosflm_beam()

        if mosflm_beam_centre:
            self._indxr_payload["mosflm_beam_centre"] = tuple(
                mosflm_beam_centre)

        detector = copy.deepcopy(self.get_detector())
        beam = copy.deepcopy(self.get_beam())
        from dxtbx.model.detector_helpers import set_mosflm_beam_centre

        set_mosflm_beam_centre(detector, beam, mosflm_beam_centre)

        from xia2.Experts.SymmetryExpert import lattice_to_spacegroup_number
        from scitbx import matrix
        from cctbx import sgtbx, uctbx
        from dxtbx.model import CrystalFactory

        mosflm_matrix = matrix.sqr([
            float(i) for line in lms.calculate()
            for i in line.replace("-", " -").split()
        ][:9])

        space_group = sgtbx.space_group_info(
            lattice_to_spacegroup_number(self._solution["lattice"])).group()
        crystal_model = CrystalFactory.from_mosflm_matrix(
            mosflm_matrix,
            unit_cell=uctbx.unit_cell(tuple(self._solution["cell"])),
            space_group=space_group,
        )

        from dxtbx.model import Experiment, ExperimentList

        experiment = Experiment(
            beam=beam,
            detector=detector,
            goniometer=self.get_goniometer(),
            scan=self.get_scan(),
            crystal=crystal_model,
        )

        experiment_list = ExperimentList([experiment])
        self.set_indexer_experiment_list(experiment_list)

        # also get an estimate of the resolution limit from the
        # labelit.stats_distl output... FIXME the name is wrong!

        lsd = LabelitStats_distl()
        lsd.set_working_directory(self.get_working_directory())
        lsd.stats_distl()

        resolution = 1.0e6
        for i in _images:
            stats = lsd.get_statistics(self.get_image_name(i))

            resol = 0.5 * (stats["resol_one"] + stats["resol_two"])

            if resol < resolution:
                resolution = resol

        self._indxr_resolution_estimate = resolution

        return "ok"
Beispiel #18
0
    def _mosflm_refine_cell(self, idxr, set_spacegroup=None):
        '''Perform the refinement of the unit cell. This will populate
    all of the information needed to perform the integration.'''

        # FIXME this will die after #1285

        #if not self.get_integrater_indexer():
        #Debug.write('Replacing indexer of %s with self at %d' % \
        #(str(self.get_integrater_indexer()), __line__))
        #self.set_integrater_indexer(self)

        #idxr = self.get_integrater_indexer()

        if not idxr.get_indexer_payload('mosflm_orientation_matrix'):
            raise RuntimeError('unexpected situation in indexing')

        lattice = idxr.get_indexer_lattice()
        mosaic = idxr.get_indexer_mosaic()
        cell = idxr.get_indexer_cell()
        beam_centre = idxr.get_indexer_beam_centre()

        # bug # 3174 - if mosaic is very small (here defined to be
        # 0.25 x osc_width) then set to this minimum value.

        phi_width = idxr.get_phi_width()
        if mosaic < 0.25 * phi_width:
            mosaic = 0.25 * phi_width

        if idxr.get_indexer_payload('mosflm_beam_centre'):
            beam_centre = idxr.get_indexer_payload('mosflm_beam_centre')

        distance = idxr.get_indexer_distance()
        matrix = idxr.get_indexer_payload('mosflm_orientation_matrix')

        integration_params = idxr.get_indexer_payload(
            'mosflm_integration_parameters')

        if integration_params is None:
            integration_params = {}

        if integration_params:
            if 'separation' in integration_params:
                self.set_refiner_parameter(
                    'mosflm', 'separation',
                    '%f %f' % tuple(integration_params['separation']))
            if 'raster' in integration_params:
                self.set_refiner_parameter(
                    'mosflm', 'raster',
                    '%d %d %d %d %d' % tuple(integration_params['raster']))

        idxr.set_indexer_payload('mosflm_integration_parameters', None)

        spacegroup_number = lattice_to_spacegroup(lattice)

        # copy these into myself for later reference, if indexer
        # is not myself - everything else is copied via the
        # cell refinement process...

        from cctbx import sgtbx
        from dxtbx.model import Crystal
        from dxtbx.model.detector_helpers import set_mosflm_beam_centre

        experiment = idxr.get_indexer_experiment_list()[0]
        set_mosflm_beam_centre(experiment.detector, experiment.beam,
                               beam_centre)
        space_group = sgtbx.space_group_info(number=spacegroup_number).group()
        a, b, c = experiment.crystal.get_real_space_vectors()
        experiment.crystal = Crystal(a, b, c, space_group=space_group)

        # FIXME surely these have been assigned further up?!

        if not self._mosflm_cell_ref_images:
            self._mosflm_cell_ref_images = self._refine_select_images(mosaic)

        f = open(
            os.path.join(self.get_working_directory(),
                         'xiaindex-%s.mat' % lattice), 'w')
        for m in matrix:
            f.write(m)
        f.close()

        # then start the cell refinement

        refiner = MosflmRefineCell()
        refiner.set_working_directory(self.get_working_directory())
        auto_logfiler(refiner)

        if self._mosflm_gain:
            refiner.set_gain(self._mosflm_gain)

        refiner.set_template(os.path.basename(idxr.get_template()))
        refiner.set_directory(idxr.get_directory())
        refiner.set_input_mat_file('xiaindex-%s.mat' % lattice)
        refiner.set_output_mat_file('xiarefine.mat')
        refiner.set_beam_centre(beam_centre)
        refiner.set_unit_cell(cell)
        refiner.set_distance(distance)
        if set_spacegroup:
            refiner.set_space_group_number(set_spacegroup)
        else:
            refiner.set_space_group_number(spacegroup_number)

        # FIXME 18/JUN/08 - it may help to have an overestimate
        # of the mosaic spread in here as it *may* refine down
        # better than up... - this is not a good idea as it may
        # also not refine at all! - 12972 # integration failed

        # Bug # 3103
        if self._mosflm_cell_ref_double_mosaic:
            mosaic *= 2.0
        refiner.set_mosaic(mosaic)

        # if set, use the resolution for cell refinement - see
        # bug # 2078...

        if self._mosflm_cell_ref_resolution:
            refiner.set_resolution(self._mosflm_cell_ref_resolution)

        refiner.set_fix_mosaic(self._mosflm_postref_fix_mosaic)

        # note well that the beam centre is coming from indexing so
        # should be already properly handled

        #if idxr.get_wavelength_prov() == 'user':
        #refiner.set_wavelength(idxr.get_wavelength())

        # belt + braces mode - only to be used when considering failover,
        # will run an additional step of autoindexing prior to cell
        # refinement, to be used only after proving that not going it
        # will result in cell refinement failure - will use the first
        # wedge... N.B. this is only useful if the indexer is Labelit
        # not Mosflm...

        refiner.set_add_autoindex(self._mosflm_cell_ref_add_autoindex)

        # get all of the stored parameter values
        parameters = self.get_refiner_parameters('mosflm')
        refiner.update_parameters(parameters)

        detector = idxr.get_detector()
        detector_width, detector_height = detector[0].get_image_size_mm()

        lim_x = 0.5 * detector_width
        lim_y = 0.5 * detector_height

        Debug.write('Scanner limits: %.1f %.1f' % (lim_x, lim_y))
        refiner.set_limits(lim_x, lim_y)
        refiner.set_images(self._mosflm_cell_ref_images)

        failover = PhilIndex.params.xia2.settings.failover

        if failover and not self._mosflm_cell_ref_add_autoindex:
            refiner.set_ignore_cell_refinement_failure(True)

        refiner.run()

        # then look to see if the cell refinement worked ok - if it
        # didn't then this may indicate that the lattice was wrongly
        # selected.

        cell_refinement_ok = refiner.cell_refinement_ok()

        if not cell_refinement_ok:
            Debug.write('Repeating cell refinement...')
            self.set_integrater_prepare_done(False)
            self._mosflm_cell_ref_add_autoindex = True
            return [0.0], [0.0]

        rms_values = refiner.get_rms_values()
        background_residual = refiner.get_background_residual()
        self._refinr_cell = refiner.get_refined_unit_cell()
        distance = refiner.get_refined_distance2()
        experiment = idxr.get_indexer_experiment_list()[0]
        from xia2.Wrappers.Mosflm.AutoindexHelpers import set_distance
        set_distance(experiment.detector, distance)

        self.set_refiner_parameter('mosflm', 'distortion yscale',
                                   refiner.get_refined_distortion_yscale())

        self.set_refiner_parameter('mosflm', 'raster', refiner.get_raster())

        #integration_params['distortion yscale'] \
        #= refiner.get_refined_distortion_yscale()
        #integration_params['raster'] = refiner.get_raster()

        separation = refiner.get_separation()
        if separation is not None:
            self.set_refiner_parameter('mosflm', 'separation',
                                       '%s %s' % refiner.get_separation())
            #integration_params['separation'] = refiner.get_separation()

        self.set_refiner_parameter('mosflm', 'beam',
                                   '%s %s' % refiner.get_refined_beam_centre())
        self.set_refiner_parameter('mosflm', 'distance',
                                   refiner.get_refined_distance())
        self.set_refiner_parameter('mosflm', 'distortion tilt',
                                   refiner.get_refined_distortion_tilt())
        self.set_refiner_parameter('mosflm', 'distortion twist',
                                   refiner.get_refined_distortion_twist())

        integration_params['beam'] = tuple(
            float(b) for b in refiner.get_refined_beam_centre())
        integration_params['distance'] = refiner.get_refined_distance()
        integration_params[
            'distortion tilt'] = refiner.get_refined_distortion_tilt()
        integration_params[
            'distortion twist'] = refiner.get_refined_distortion_twist()

        idxr._indxr_mosaic = refiner.get_refined_mosaic()

        idxr.set_indexer_payload(
            'mosflm_orientation_matrix',
            open(os.path.join(self.get_working_directory(), 'xiarefine.mat'),
                 'r').readlines())
        self.set_refiner_payload(
            'mosflm_orientation_matrix',
            idxr.get_indexer_payload('mosflm_orientation_matrix'))
        self.set_refiner_payload('mosaic', refiner.get_refined_mosaic())
        self.set_refiner_payload('beam', integration_params['beam'])
        self.set_refiner_payload('distance', integration_params['distance'])

        from xia2.Wrappers.Mosflm.AutoindexHelpers import crystal_model_from_mosflm_mat
        # make a dxtbx crystal_model object from the mosflm matrix
        experiment = idxr.get_indexer_experiment_list()[0]
        crystal_model = crystal_model_from_mosflm_mat(
            idxr._indxr_payload['mosflm_orientation_matrix'],
            unit_cell=refiner.get_refined_unit_cell(),
            space_group=experiment.crystal.get_space_group())
        experiment.crystal = crystal_model

        #self.set_refiner_payload(
        #'mosflm_integration_parameters', integration_params)

        self._refinr_refined_experiment_list = ExperimentList([experiment])

        return rms_values, background_residual
Beispiel #19
0
    def _index(self):
        '''Implement the indexer interface.'''

        Citations.cite('mosflm')

        indexer = MosflmIndex()
        indexer.set_working_directory(self.get_working_directory())
        auto_logfiler(indexer)

        from xia2.lib.bits import unique_elements
        _images = unique_elements(self._indxr_images)
        indexer.set_images(_images)
        images_str = ', '.join(map(str, _images))

        cell_str = None
        if self._indxr_input_cell:
            cell_str = '%.2f %.2f %.2f %.2f %.2f %.2f' % \
                        self._indxr_input_cell

        if self._indxr_sweep_name:

            #if len(self._fp_directory) <= 50:
            #dirname = self._fp_directory
            #else:
            #dirname = '...%s' % self._fp_directory[-46:]
            dirname = os.path.dirname(self.get_imageset().get_template())

            Journal.block(
                'autoindexing', self._indxr_sweep_name, 'mosflm', {
                    'images': images_str,
                    'target cell': self._indxr_input_cell,
                    'target lattice': self._indxr_input_lattice,
                    'template': self.get_imageset().get_template(),
                    'directory': dirname
                })

        #task = 'Autoindex from images:'

        #for i in _images:
        #task += ' %s' % self.get_image_name(i)

        #self.set_task(task)

        indexer.set_template(os.path.basename(self.get_template()))
        indexer.set_directory(self.get_directory())

        xsweep = self.get_indexer_sweep()
        if xsweep is not None:
            if xsweep.get_distance() is not None:
                indexer.set_distance(xsweep.get_distance())
            #if self.get_wavelength_prov() == 'user':
            #index.set_wavelength(self.get_wavelength())
            if xsweep.get_beam_centre() is not None:
                indexer.set_beam_centre(xsweep.get_beam_centre())

        if self._indxr_input_cell:
            indexer.set_unit_cell(self._indxr_input_cell)

        if self._indxr_input_lattice is not None:
            spacegroup_number = lattice_to_spacegroup(
                self._indxr_input_lattice)
            indexer.set_space_group_number(spacegroup_number)

        if not self._mosflm_autoindex_thresh:

            try:

                min_peaks = 200

                Debug.write('Aiming for at least %d spots...' % min_peaks)

                thresholds = []

                for i in _images:

                    p = Printpeaks()
                    p.set_working_directory(self.get_working_directory())
                    auto_logfiler(p)
                    p.set_image(self.get_image_name(i))
                    thresh = p.threshold(min_peaks)

                    Debug.write('Autoindex threshold for image %d: %d' % \
                                (i, thresh))

                    thresholds.append(thresh)

                thresh = min(thresholds)
                self._mosflm_autoindex_thresh = thresh

            except Exception as e:
                print str(e)  #XXX this should disappear!
                Debug.write('Error computing threshold: %s' % str(e))
                Debug.write('Using default of 20.0')
                thresh = 20.0

        else:
            thresh = self._mosflm_autoindex_thresh

        Debug.write('Using autoindex threshold: %d' % thresh)

        if self._mosflm_autoindex_sol:
            indexer.set_solution_number(self._mosflm_autoindex_sol)
        indexer.set_threshold(thresh)

        # now forget this to prevent weird things happening later on
        if self._mosflm_autoindex_sol:
            self._mosflm_autoindex_sol = 0

        indexer.run()

        indxr_cell = indexer.get_refined_unit_cell()
        self._indxr_lattice = indexer.get_lattice()
        space_group_number = indexer.get_indexed_space_group_number()
        detector_distance = indexer.get_refined_distance()
        beam_centre = indexer.get_refined_beam_centre()
        mosaic_spreads = indexer.get_mosaic_spreads()

        if min(list(indxr_cell)) < 10.0 and \
           indxr_cell[2] / indxr_cell[0] > 6:

            Debug.write('Unrealistic autoindexing solution: ' +
                        '%.2f %.2f %.2f %.2f %.2f %.2f' % indxr_cell)

            # tweak some parameters and try again...
            self._mosflm_autoindex_thresh *= 1.5
            self.set_indexer_done(False)

            return

        intgr_params = {}

        # look up other possible indexing solutions (not well - in
        # standard settings only!) This is moved earlier as it could
        # result in returning if Mosflm has selected the wrong
        # solution!

        try:
            self._indxr_other_lattice_cell = indexer.get_solutions()

            # Change 27/FEB/08 to support user assigned spacegroups
            if self._indxr_user_input_lattice:
                lattice_to_spacegroup_dict = {
                    'aP': 1,
                    'mP': 3,
                    'mC': 5,
                    'oP': 16,
                    'oC': 20,
                    'oF': 22,
                    'oI': 23,
                    'tP': 75,
                    'tI': 79,
                    'hP': 143,
                    'hR': 146,
                    'cP': 195,
                    'cF': 196,
                    'cI': 197
                }
                for k in self._indxr_other_lattice_cell.keys():
                    if lattice_to_spacegroup_dict[k] > \
                           lattice_to_spacegroup_dict[
                        self._indxr_input_lattice]:
                        del (self._indxr_other_lattice_cell[k])

            # check that the selected unit cell matches - and if
            # not raise a "horrible" exception

            if self._indxr_input_cell:
                assert indxr_cell is not None
                for j in range(6):
                    if math.fabs(self._indxr_input_cell[j] -
                                 indxr_cell[j]) > 2.0:
                        Chatter.write('Mosflm autoindexing did not select ' +
                                      'correct (target) unit cell')
                        raise RuntimeError(
                            'something horrible happened in indexing')

        except RuntimeError as e:
            # check if mosflm rejected a solution we have it
            if 'horribl' in str(e):
                # ok it did - time to break out the big guns...
                if not self._indxr_input_cell:
                    raise RuntimeError(
                        'error in solution selection when not preset')

                # XXX FIXME
                self._mosflm_autoindex_sol = _get_indexing_solution_number(
                    indexer.get_all_output(), self._indxr_input_cell,
                    self._indxr_input_lattice)

                # set the fact that we are not done...
                self.set_indexer_done(False)

                # and return - hopefully this will restart everything
                return
            else:
                raise e

        if len(mosaic_spreads) == 0:
            # then consider setting it do a default value...
            # equal to the oscillation width (a good guess)
            phi_width = self.get_phi_width()
            Chatter.write(
                'Mosaic estimation failed, so guessing at %4.2f' % \
                phi_width)
            # only consider this if we have thus far no idea on the
            # mosaic spread...
            mosaic_spreads.append(phi_width)

        intgr_params['raster'] = indexer.get_raster()

        intgr_params['separation'] = indexer.get_separation()

        self._indxr_resolution_estimate = indexer.get_resolution_estimate()

        # compute mosaic as mean(mosaic_spreads)

        self._indxr_mosaic = sum(mosaic_spreads) / len(mosaic_spreads)

        self._indxr_payload['mosflm_integration_parameters'] = intgr_params

        self._indxr_payload['mosflm_orientation_matrix'] = open(
            os.path.join(self.get_working_directory(), 'xiaindex.mat'),
            'r').readlines()

        import copy
        from dxtbx.model.detector_helpers import set_mosflm_beam_centre
        from xia2.Wrappers.Mosflm.AutoindexHelpers import set_distance
        from xia2.Wrappers.Mosflm.AutoindexHelpers import crystal_model_from_mosflm_mat
        from cctbx import sgtbx, uctbx

        # update the beam centre (i.e. shift the origin of the detector)
        detector = copy.deepcopy(self.get_detector())
        beam = copy.deepcopy(self.get_beam())
        set_mosflm_beam_centre(detector, beam, beam_centre)
        if detector_distance is not None:
            set_distance(detector, detector_distance)

        # make a dxtbx crystal_model object from the mosflm matrix
        space_group = sgtbx.space_group_info(number=space_group_number).group()
        crystal_model = crystal_model_from_mosflm_mat(
            self._indxr_payload['mosflm_orientation_matrix'],
            unit_cell=uctbx.unit_cell(tuple(indxr_cell)),
            space_group=space_group)

        # construct an experiment_list
        from dxtbx.model import Experiment, ExperimentList
        experiment = Experiment(beam=beam,
                                detector=detector,
                                goniometer=self.get_goniometer(),
                                scan=self.get_scan(),
                                crystal=crystal_model)

        experiment_list = ExperimentList([experiment])
        self.set_indexer_experiment_list(experiment_list)
Beispiel #20
0
  def __init__(self, name,
               wavelength,
               sample,
               directory = None,
               image = None,
               beam = None,
               reversephi = False,
               distance = None,
               gain = 0.0,
               dmin = 0.0,
               dmax = 0.0,
               polarization = 0.0,
               frames_to_process = None,
               user_lattice = None,
               user_cell = None,
               epoch = 0,
               ice = False,
               excluded_regions = None):
    '''Create a new sweep named name, belonging to XWavelength object
    wavelength, representing the images in directory starting with image,
    with beam centre optionally defined.'''
    if excluded_regions is None:
      excluded_regions = []

    # + check the wavelength is an XWavelength object
    #   raise an exception if not... or not...

    if not wavelength.__class__.__name__ == 'XWavelength':
      pass

    # FIXME bug 2221 if DIRECTORY starts with ~/ or ~graeme (say) need to
    # interpret this properly - e.g. map it to a full PATH.

    directory = expand_path(directory)

    self._name = name
    self._wavelength = wavelength
    self._sample = sample
    self._directory = directory
    self._image = image
    self._reversephi = reversephi
    self._epoch = epoch
    self._user_lattice = user_lattice
    self._user_cell = user_cell
    self._header = { }
    self._resolution_high = dmin
    self._resolution_low = dmax
    self._ice = ice
    self._excluded_regions = excluded_regions
    self._imageset = None

    # FIXME in here also need to be able to accumulate the total
    # dose from all experimental measurements (complex) and provide
    # a _epoch_to_dose dictionary or some such... may be fiddly as
    # this will need to parse across multiple templates. c/f Bug # 2798

    self._epoch_to_image = { }
    self._image_to_epoch = { }

    # to allow first, last image for processing to be
    # set... c/f integrater interface
    self._frames_to_process = frames_to_process

    # + derive template, list of images

    params = PhilIndex.get_python_object()
    if directory and image:
      self._template, self._directory = \
                      image2template_directory(os.path.join(directory,
                                                            image))

      from xia2.Schema import load_imagesets
      imagesets = load_imagesets(
        self._template, self._directory, image_range=self._frames_to_process,
        reversephi=(params.xia2.settings.input.reverse_phi or self._reversephi))

      assert len(imagesets) == 1, "one imageset expected, %d found" % \
          len(imagesets)
      self._imageset = copy.deepcopy(imagesets[0])
      start, end = self._imageset.get_array_range()
      self._images = list(range(start+1, end+1))

      # FIXME in here check that (1) the list of images is continuous
      # and (2) that all of the images are readable. This should also
      # take into account frames_to_process if set.

      if self._frames_to_process is None:
        self._frames_to_process = min(self._images), max(self._images)

      start, end = self._frames_to_process

      error = False

      if params.general.check_image_files_readable:
        for j in range(start, end + 1):
          image_name = self.get_imageset().get_path(j-start)
          if not j in self._images:
            Debug.write('image %s missing' %image_name)
            error = True
            continue
          if not os.access(image_name, os.R_OK):
            Debug.write('image %s unreadable' %image_name)
            error = True
            continue

        if error:
          raise RuntimeError, 'problem with sweep %s' % self._name

      # + read the image header information into here?
      #   or don't I need it? it would be useful for checking
      #   against wavelength.getWavelength() I guess to make
      #   sure that the plumbing is all sound.

      # check that they match by closer than 0.0001A, if wavelength
      # is not None

      beam_ = self._imageset.get_beam()
      scan = self._imageset.get_scan()
      if wavelength is not None:

        # FIXME 29/NOV/06 if the wavelength wavelength value
        # is 0.0 then first set it to the header value - note
        # that this assumes that the header value is correct
        # (a reasonable assumption)

        if wavelength.get_wavelength() == 0.0:
          wavelength.set_wavelength(beam_.get_wavelength())

        # FIXME 08/DEC/06 in here need to allow for the fact
        # that the wavelength in the image header could be wrong and
        # in fact it should be replaced with the input value -
        # through the user will need to be warned of this and
        # also everything using the FrameProcessor interface
        # will also have to respect this!

        if math.fabs(beam_.get_wavelength() -
                     wavelength.get_wavelength()) > 0.0001:
          # format = 'wavelength for sweep %s does not ' + \
          # 'match wavelength %s'
          # raise RuntimeError, format  % \
          # (name, wavelength.get_name())

          format = 'Header wavelength for sweep %s different' + \
                   ' to assigned value (%4.2f vs. %4.2f)'

          Chatter.write(format % (name, beam_.get_wavelength(),
                                  wavelength.get_wavelength()))


      # also in here look at the image headers to see if we can
      # construct a mapping between exposure epoch and image ...

      images = []

      if self._frames_to_process:
        start, end = self._frames_to_process
        for j in self._images:
          if j >= start and j <= end:
            images.append(j)
      else:
        images = self._images

      for j in images:
        epoch = scan.get_image_epoch(j)
        if epoch == 0.0:
          epoch = float(os.stat(self._imageset.get_path(j-images[0])).st_mtime)
        self._epoch_to_image[epoch] = j
        self._image_to_epoch[j] = epoch

      epochs = self._epoch_to_image.keys()

      Debug.write('Exposure epoch for sweep %s: %d %d' % \
                  (self._template, min(epochs), max(epochs)))

    self._input_imageset = copy.deepcopy(self._imageset)

    # + get the lattice - can this be a pointer, so that when
    #   this object updates lattice it is globally-for-this-crystal
    #   updated? The lattice included directly in here includes an
    #   exact unit cell for data reduction, the crystal lattice
    #   contains an approximate unit cell which should be
    #   from the unit cells from all sweeps contained in the
    #   XCrystal. FIXME should I be using a LatticeInfo object
    #   in here? See what the Indexer interface produces. ALT:
    #   just provide an Indexer implementation "hook".
    #   See Headnote 001 above. See also _get_indexer,
    #   _get_integrater below.

    self._indexer = None
    self._refiner = None
    self._integrater = None

    # I don't need this - it is equivalent to self.getWavelength(
    # ).getCrystal().getLattice()
    # self._crystal_lattice = None

    # this means that this module will have to present largely the
    # same interface as Indexer and Integrater so that the calls
    # can be appropriately forwarded.

    # finally configure the beam if set

    if beam is not None:
      from dxtbx.model.detector_helpers import set_mosflm_beam_centre
      try:
        set_mosflm_beam_centre(self.get_imageset().get_detector(),
                               self.get_imageset().get_beam(),
                               beam)
      except AssertionError, e:
        Debug.write('Error setting mosflm beam centre: %s' % e)