Example #1
0
    def detectorbase_start(self):
        from xfel.cftbx.detector.cspad_detector import CSPadDetector

        self.detectorbase = CSPadDetector(self._image_file)
        self.detectorbase.readHeader()
        self._metrology_params = self.detectorbase._metrology_params
        self._tiles = self.detectorbase._tiles

        # The lines above could eventually be replaced by the lines
        # below.
        """
  def detectorbase_start(self):
    from xfel.cftbx.detector.cspad_detector import CSPadDetector

    self.detectorbase = CSPadDetector(self._image_file)
    self.detectorbase.readHeader()
    self._metrology_params = self.detectorbase._metrology_params
    self._tiles = self.detectorbase._tiles

    # The lines above could eventually be replaced by the lines
    # below.
    """
class FormatPYmultitile(FormatPY):

  @staticmethod
  def understand(image_file):
    try:
      import cPickle as pickle
      stream = FormatPYmultitile.open_file(image_file, 'rb')
      data = pickle.load(stream)
    except IOError:
      return False

    wanted_header_items = ['TILES', 'METROLOGY']
    for header_item in wanted_header_items:
      if not header_item in data:
        return False

    unwanted_header_items = ['SIZE1', 'SIZE2']
    for header_item in unwanted_header_items:
      if header_item in data:
        return False

    return True


  def __init__(self, image_file):
    '''Initialise the image structure from the given file.'''

    assert(self.understand(image_file))

    FormatPY.__init__(self, image_file)


  def _start(self):
    # this Format class depends on stuff from detectorbase
    self.detectorbase_start()
    return

  def detectorbase_start(self):
    from xfel.cftbx.detector.cspad_detector import CSPadDetector

    self.detectorbase = CSPadDetector(self._image_file)
    self.detectorbase.readHeader()
    self._metrology_params = self.detectorbase._metrology_params
    self._tiles = self.detectorbase._tiles

    # The lines above could eventually be replaced by the lines
    # below.
    """
    from cPickle import load
    stream = FormatPYmultitile.open_file(self._image_file)
    d = load(stream)
    self._metrology_params = d['METROLOGY'].extract()
    self._tiles = d['TILES']
    stream.close()
    """


  def _goniometer(self):
    return self._goniometer_factory.single_axis()


  def _detector(self):
    '''The _detector() function returns a model for a CSPAD detector as
    used at LCLS's CXI and XPP endstations.  It converts the
    metrology information in the pure Python object extracted from
    the image pickle to DXTBX-style transformation vectors.  Only
    ASIC:s are considered, since DXTBX metrology is not concerned
    with hierarchies.

    Merged from xfel.cftbx.detector.cspad_detector.readHeader() and
    xfel.cftbx.detector.metrology.metrology_as_dxtbx_vectors().
    '''

    from dxtbx.model import SimplePxMmStrategy
    from dxtbx.model.detector import HierarchicalDetector
    from scitbx.matrix import col

    # XXX Introduces dependency on cctbx.xfel!  Should probably be
    # merged into the code here!
    from xfel.cftbx.detector.metrology import \
         _transform, get_projection_matrix

    # Apply the detector distance to the translation of the root
    # detector object.
    d = self._metrology_params.detector
    Tb_d = _transform(
      col(d.orientation).normalize(),
      col(d.translation) +
      col((0, 0, -self._metrology_params.distance * 1e-3)))[1]

    self._raw_data = []
    detector = HierarchicalDetector()

    for p in d.panel:
      Tb_p = Tb_d * _transform(
        col(p.orientation).normalize(),
        col(p.translation))[1]

      for s in p.sensor:
        Tb_s = Tb_p * _transform(
          col(s.orientation).normalize(),
          col(s.translation))[1]

        for a in s.asic:
          Tb_a = Tb_s * _transform(
            col(a.orientation).normalize(),
            col(a.translation))[1]

          Pb = get_projection_matrix(a.pixel_size, a.dimension)[1]

          # The DXTBX-style metrology description consists of three
          # vectors for each ASIC.  The origin vector locates the
          # (0, 0)-pixel in the laboratory frame in units of mm.
          # The second and third vectors give the directions to the
          # pixels immediately next to (0, 0) in the fast and slow
          # directions, respectively, in arbitrary units.
          origin = Tb_a * Pb * col((0, 0, 1))
          fast = Tb_a * Pb * col((0, a.dimension[0], 1)) - origin
          slow = Tb_a * Pb * col((a.dimension[1], 0, 1)) - origin

          # Convert vector units from meter to millimeter.  The
          # default, SimplePxMmStrategy applies here.  XXX Due to
          # dark subtraction, a valid pixel intensity may be
          # negative, and this is currently not reflected by
          # trusted_range.
          key = (d.serial, p.serial, s.serial, a.serial)

          panel = detector.add_panel()
          panel.set_type("PAD")
          panel.set_name('%d:%d:%d:%d' % key)
          panel.set_local_frame(
            [t * 1e3 for t in fast.elems[0:3]],
            [t * 1e3 for t in slow.elems[0:3]],
            [t * 1e3 for t in origin.elems[0:3]])

          panel.set_pixel_size([t * 1e3 for t in a.pixel_size])
          panel.set_image_size(a.dimension)
          panel.set_trusted_range((0, a.saturation))

          self._raw_data.append(self._tiles[key])

    return detector


  def get_raw_data(self):
    ''' Return a tuple of flex arrays, one for each asic '''

    return tuple(self._raw_data)


  def _beam(self):
    '''Return a simple model for the beam.'''

    return self._beam_factory.simple(self._metrology_params.wavelength)


  def _scan(self):
    '''Return the scan information for this image.'''

    from calendar import timegm
    from time import strptime

    # Convert textual ISO 8601 timestamp in UTC to
    # millisecond-precision Unix epoch.
    str_min = self._metrology_params.timestamp[:16] + 'UTC'
    str_sec = self._metrology_params.timestamp[17:]
    epoch = timegm(strptime(str_min, '%Y-%m-%dT%H:%M%Z')) + float(str_sec)

    return self._scan_factory.make_scan(
      image_range=(1, 1),
      exposure_times=[1e-15 * self._metrology_params.pulse_length],
      oscillation=(0, 0),
      epochs={1: epoch})
Example #4
0
class FormatPYmultitile(FormatPY):
    @staticmethod
    def understand(image_file):
        try:
            import six.moves.cPickle as pickle

            stream = FormatPYmultitile.open_file(image_file, "rb")
            data = pickle.load(stream)
        except IOError:
            return False

        wanted_header_items = ["TILES", "METROLOGY"]
        for header_item in wanted_header_items:
            if not header_item in data:
                return False

        unwanted_header_items = ["SIZE1", "SIZE2"]
        for header_item in unwanted_header_items:
            if header_item in data:
                return False

        return True

    def __init__(self, image_file, **kwargs):
        """Initialise the image structure from the given file."""

        from dxtbx import IncorrectFormatError

        if not self.understand(image_file):
            raise IncorrectFormatError(self, image_file)

        FormatPY.__init__(self, image_file, **kwargs)

    def _start(self):
        # this Format class depends on stuff from detectorbase
        self.detectorbase_start()
        return

    def detectorbase_start(self):
        from xfel.cftbx.detector.cspad_detector import CSPadDetector

        self.detectorbase = CSPadDetector(self._image_file)
        self.detectorbase.readHeader()
        self._metrology_params = self.detectorbase._metrology_params
        self._tiles = self.detectorbase._tiles

        # The lines above could eventually be replaced by the lines
        # below.
        """
    from cPickle import load
    stream = FormatPYmultitile.open_file(self._image_file)
    d = load(stream)
    self._metrology_params = d['METROLOGY'].extract()
    self._tiles = d['TILES']
    stream.close()
    """

    def _goniometer(self):
        return self._goniometer_factory.single_axis()

    def _detector(self):
        """The _detector() function returns a model for a CSPAD detector as
        used at LCLS's CXI and XPP endstations.  It converts the
        metrology information in the pure Python object extracted from
        the image pickle to DXTBX-style transformation vectors.  Only
        ASIC:s are considered, since DXTBX metrology is not concerned
        with hierarchies.

        Merged from xfel.cftbx.detector.cspad_detector.readHeader() and
        xfel.cftbx.detector.metrology.metrology_as_dxtbx_vectors().
        """

        from dxtbx.model import SimplePxMmStrategy
        from dxtbx.model import Detector
        from scitbx.matrix import col

        # XXX Introduces dependency on cctbx.xfel!  Should probably be
        # merged into the code here!
        from xfel.cftbx.detector.metrology import _transform, get_projection_matrix

        # Apply the detector distance to the translation of the root
        # detector object.
        d = self._metrology_params.detector
        Tb_d = _transform(
            col(d.orientation).normalize(),
            col(d.translation) + col((0, 0, -self._metrology_params.distance * 1e-3)),
        )[1]

        self._raw_data = []
        detector = Detector()

        for p in d.panel:
            Tb_p = (
                Tb_d * _transform(col(p.orientation).normalize(), col(p.translation))[1]
            )

            for s in p.sensor:
                Tb_s = (
                    Tb_p
                    * _transform(col(s.orientation).normalize(), col(s.translation))[1]
                )

                for a in s.asic:
                    Tb_a = (
                        Tb_s
                        * _transform(
                            col(a.orientation).normalize(), col(a.translation)
                        )[1]
                    )

                    Pb = get_projection_matrix(a.pixel_size, a.dimension)[1]

                    # The DXTBX-style metrology description consists of three
                    # vectors for each ASIC.  The origin vector locates the
                    # (0, 0)-pixel in the laboratory frame in units of mm.
                    # The second and third vectors give the directions to the
                    # pixels immediately next to (0, 0) in the fast and slow
                    # directions, respectively, in arbitrary units.
                    origin = Tb_a * Pb * col((0, 0, 1))
                    fast = Tb_a * Pb * col((0, a.dimension[0], 1)) - origin
                    slow = Tb_a * Pb * col((a.dimension[1], 0, 1)) - origin

                    # Convert vector units from meter to millimeter.  The
                    # default, SimplePxMmStrategy applies here.  XXX Due to
                    # dark subtraction, a valid pixel intensity may be
                    # negative, and this is currently not reflected by
                    # trusted_range.
                    key = (d.serial, p.serial, s.serial, a.serial)

                    panel = detector.add_panel()
                    panel.set_type("PAD")
                    panel.set_name("%d:%d:%d:%d" % key)
                    panel.set_local_frame(
                        [t * 1e3 for t in fast.elems[0:3]],
                        [t * 1e3 for t in slow.elems[0:3]],
                        [t * 1e3 for t in origin.elems[0:3]],
                    )

                    panel.set_pixel_size([t * 1e3 for t in a.pixel_size])
                    panel.set_image_size(a.dimension)
                    panel.set_trusted_range((0, a.saturation))

                    self._raw_data.append(self._tiles[key])

        return detector

    def get_raw_data(self):
        """ Return a tuple of flex arrays, one for each asic """

        return tuple(self._raw_data)

    def _beam(self):
        """Return a simple model for the beam."""

        return self._beam_factory.simple(self._metrology_params.wavelength)

    def _scan(self):
        """Return the scan information for this image."""

        from calendar import timegm
        from time import strptime

        # Convert textual ISO 8601 timestamp in UTC to
        # millisecond-precision Unix epoch.
        str_min = self._metrology_params.timestamp[:16] + "UTC"
        str_sec = self._metrology_params.timestamp[17:]
        epoch = timegm(strptime(str_min, "%Y-%m-%dT%H:%M%Z")) + float(str_sec)

        return self._scan_factory.make_scan(
            image_range=(1, 1),
            exposure_times=[1e-15 * self._metrology_params.pulse_length],
            oscillation=(0, 0),
            epochs={1: epoch},
        )
Example #5
0
 def detectorbase_start(self):
     self.detectorbase = CSPadDetector(self._image_file)
     self.detectorbase.readHeader()
     self._metrology_params = self.detectorbase._metrology_params
     self._tiles = self.detectorbase._tiles