Example #1
0
def tst_detector():
  from dxtbx.model import ParallaxCorrectedPxMmStrategy

  def create_detector(offset = 0):
    # Create the detector
    detector = Detector(Panel(
      "",                 # Type
      "Panel",            # Name
      (10, 0, 0),         # Fast axis
      (0, 10, 0),         # Slow axis
      (0 + offset, 0 + offset, 200 - offset),
                          # Origin
      (0.172, 0.172),     # Pixel size
      (512, 512),         # Image size
      (0, 1000),          # Trusted range
      0.1,                # Thickness
      "Si"))              # Material
    return detector

  detector = create_detector()

  # Perform some tests
  tst_set_mosflm_beam_centre(detector)
  tst_get_pixel_lab_coord(detector)
  tst_get_image_size_mm(detector)
  tst_is_value_in_trusted_range(detector)
  tst_is_coord_valid(detector)
  tst_pixel_to_millimeter_to_pixel(detector)
  tst_get_names(detector)
  tst_get_thickness(detector)
  tst_get_material(detector)

  # Attenuation length
  from cctbx.eltbx import attenuation_coefficient
  table = attenuation_coefficient.get_table("Si")
  mu = table.mu_at_angstrom(1) / 10
  t0 = 0.320

  # Create another detector with different origin
  detector_moved = create_detector(offset=100)
  tst_detectors_are_different(detector, detector_moved)

  detector_moved_copy = create_detector(offset=100)
  tst_detectors_are_same(detector_moved, detector_moved_copy)

  # Create the detector
  detector = Detector(Panel(
      "",                 # Type
      "",                 # Name
      (10, 0, 0),         # Fast axis
      (0, 10, 0),         # Slow axis
      (0, 0, 200),        # Origin
      (0.172, 0.172),     # Pixel size
      (512, 512),         # Image size
      (0, 1000),          # Trusted range
      0.0,                # Thickness
      "",                 # Material
      ParallaxCorrectedPxMmStrategy(mu, t0)))

  tst_parallax_correction(detector)
Example #2
0
    def _detector(self):
        """Return a working detector instance, with added mask regions."""

        detector = self._detector_factory.imgCIF_H(self._get_cbf_handle(), "PAD")

        for f0, f1, s0, s1 in determine_pilatus_mask(detector):
            detector[0].add_mask(f0 - 1, s0 - 1, f1, s1)

        m = re.search(
            r"^#\s*(\S+)\ssensor, thickness\s*([0-9.]+)\s*m\s*$",
            self._cif_header,
            re.MULTILINE,
        )
        if m:
            # header gives thickness in metres, we store mm
            thickness = float(m.group(2)) * 1000
            material = m.group(1)

            if material == "Silicon":
                material = "Si"

            for panel in detector:
                panel.set_thickness(thickness)
                panel.set_material(material)

            try:
                # a header only CBF file will not have a beam object
                beam = self._beam()

            except Exception:
                beam = None

            if beam:
                # attenuation coefficient depends on the beam wavelength
                wavelength = beam.get_wavelength()

                # this will fail for undefined composite materials
                table = attenuation_coefficient.get_table(material)
                # mu_at_angstrom returns cm^-1
                mu = table.mu_at_angstrom(wavelength) / 10.0

                for panel in detector:
                    panel.set_px_mm_strategy(
                        ParallaxCorrectedPxMmStrategy(mu, thickness)
                    )
                    panel.set_mu(mu)

        m = re.search(r"^#\s*Detector:\s+(.*?)\s*$", self._cif_header, re.MULTILINE)
        if m and m.group(1):
            panel.set_identifier(m.group(1).encode())

        size = detector[0].get_image_size()
        if size == (2463, 2527):
            self.vendortype = "Pilatus-6M"
        elif size == (1475, 1679):
            self.vendortype = "Pilatus-2M"
        elif size == (487, 619):
            self.vendortype = "Pilatus-300K"

        return detector
Example #3
0
def to_imageset(input_filename, extra_filename=None):
  '''Get an image set from the xds input filename plus an extra filename

  Params:
      input_filename The XDS.INP file
      extra_filename A (G)XPARM.XDS, INTGRATE.HKL or XDS_ASCII.HKL file

  Returns:
      The imageset

  '''
  from iotbx.xds import xds_inp
  from dxtbx.imageset import ImageSetFactory
  import dxtbx

  # Read the input filename
  handle = xds_inp.reader()
  handle.read_file(input_filename)

  # Get the template
  template = handle.name_template_of_data_frames[0].replace('?', '#')
  image_range = handle.data_range
  detector_name = handle.detector

  if extra_filename is not None:
    # we can get all the extra dxtbx models from extra_filename
    check_format = False
  else:
    # we need the image files present to get the dxtbx models
    check_format = True

  # Create the imageset
  imageset = ImageSetFactory.from_template(
    template, image_range=image_range, check_format=False)[0]

  # If an extra filename has been specified, try to load models
  if extra_filename:
    models = dxtbx.load(extra_filename)
    detector = models.get_detector()
    if detector_name.strip() == 'PILATUS':
      from dxtbx.model import ParallaxCorrectedPxMmStrategy
      from cctbx.eltbx import attenuation_coefficient
      table = attenuation_coefficient.get_table("Si")
      wavelength = models.get_beam().get_wavelength()
      mu = table.mu_at_angstrom(wavelength) / 10.0
      t0 = handle.sensor_thickness
      for panel in detector:
        panel.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, t0))
        panel.set_trusted_range(
          (handle.minimum_valid_pixel_value, handle.overload))
    imageset.set_beam(models.get_beam())
    imageset.set_detector(detector)
    imageset.set_goniometer(models.get_goniometer())
    # take the image range from XDS.INP
    scan = models.get_scan()
    scan.set_image_range(image_range)
    imageset.set_scan(scan)

  # Return the imageset
  return imageset
Example #4
0
    def _detector(self):
        """Partly dummy detector"""
        from scitbx import matrix

        # Get the detector geometry
        entry = self._h5_handle["entry"]
        instrument = entry["instrument"]
        detector = instrument["detector"]

        # Initialise detector frame - origin at 0,0,0
        fast = matrix.col((1.0, 0.0, 0.0))
        slow = matrix.col((0.0, 1.0, 0.0))
        orig = matrix.col((0.0, 0.0, 0.0))

        # Get the pixel and image size
        pixel_size = (
            1.0e-3 * detector["x_pixel_size"].value,
            1.0e-3 * detector["y_pixel_size"].value,
        )
        layout = detector["layout"].value[0].split("X")
        image_size = int(layout[0]), int(layout[1])
        trusted_range = (-1, detector["saturation_value"][0])
        thickness = float(detector["sensor_thickness"].value) / 1000.0
        material = str(detector["sensor_material"].value[0])

        # Make the detector
        detector = self._detector_factory.make_detector(
            "PAD",
            fast,
            slow,
            orig,
            pixel_size,
            image_size,
            trusted_range,
            name="Panel",
            thickness=thickness,
            material=material,
        )

        # At the moment, beam is a dummy object because wavelength is not set in
        # the header. Therefore, the px<-->mm strategy will generally be
        # incorrect. Set it anyway, to override later.
        beam = self._beam()
        wavelength = beam.get_wavelength()

        from cctbx.eltbx import attenuation_coefficient
        from dxtbx.model import ParallaxCorrectedPxMmStrategy

        # this will fail for undefined composite materials
        table = attenuation_coefficient.get_table(material)

        # mu_at_angstrom returns cm^-1, but need mu in mm^-1
        mu = table.mu_at_angstrom(wavelength) / 10.0

        for panel in detector:
            panel.set_mu(mu)
            panel.set_px_mm_strategy(
                ParallaxCorrectedPxMmStrategy(mu, thickness))

        return detector
Example #5
0
    def _detector(self):
        d = FormatCBFMultiTileHierarchyStill._detector(self)

        try:
            # a header only CBF file will not have a beam object
            beam = self._beam()
        except Exception as e:
            if "CBF_NOTFOUND" not in str(e):
                raise e
            return d

        # take into consideration here the thickness of the sensor also the
        # wavelength of the radiation (which we have in the same file...)
        wavelength = beam.get_wavelength()
        thickness = 0.5  # mm, see Hart et al. 2012
        from cctbx.eltbx import attenuation_coefficient

        table = attenuation_coefficient.get_table("Si")
        # mu_at_angstrom returns cm^-1
        mu = table.mu_at_angstrom(wavelength) / 10.0  # mu: mm^-1
        t0 = thickness

        for panel in d:
            panel.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, t0))
        return d
def tst_for_z(z):
    from cctbx.eltbx import attenuation_coefficient

    eps = 1e-7

    # Get the table
    table = attenuation_coefficient.get_table(z)

    # Get list of energies and coefficients
    energy = table.energy()[1:-1]
    mu_rho = table.mu_rho()[1:-1]
    mu_en_rho = table.mu_en_rho()[1:-1]

    # Check values at measured energies match
    for i in range(len(energy)):
        e = energy[i] + 1e-16  # move beyond edges
        mr = mu_rho[i]
        mer = mu_en_rho[i]

        if i < len(energy) - 1:
            if abs(e - energy[i + 1]) < eps:
                continue

        mr2 = table.mu_rho_at_ev(e * 1000000.0)
        mer2 = table.mu_en_rho_at_ev(e * 1000000.0)
        #   print "%3d, %3d, %15f MeV -- %15f %15f %15f %15f -- %15.9f %15.9f" % (z, i, e, mr, mr2, mer, mer2, abs(mr - mr2), abs(mer - mer2))
        assert (abs(mr - mr2) <= eps)
        assert (abs(mer - mer2) <= eps)

    print 'OK'
Example #7
0
        def get_values(invert_y):

            from dxtbx.model.beam import beam_factory
            beam = beam_factory.simple(wavelength=1)

            if invert_y:
                y_direction = "-y"
            else:
                y_direction = "+y"

            from dxtbx.model.detector import detector_factory
            detector = detector_factory.simple(
                sensor=detector_factory.sensor("PAD"),
                distance=100,
                beam_centre=[50, 50],
                fast_direction="+x",
                slow_direction=y_direction,
                pixel_size=[0.1, 0.1],
                image_size=[1000, 1000])

            from dxtbx.model import ParallaxCorrectedPxMmStrategy
            from cctbx.eltbx import attenuation_coefficient
            wavelength = beam.get_wavelength()
            thickness = 0.5
            table = attenuation_coefficient.get_table("Si")
            mu = table.mu_at_angstrom(wavelength) / 10.0
            t0 = thickness

            for panel in detector:
                panel.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, t0))
            v1 = detector[0].pixel_to_millimeter((0, 0))
            v2 = detector[0].pixel_to_millimeter((1000, 1000))

            return v1, v2
Example #8
0
class Test(object):
    def __init__(self):
        import os
        import libtbx.load_env
        try:
            dials_regression = libtbx.env.dist_path('dials_regression')
        except KeyError, e:
            print 'FAIL: dials_regression not configured'
            exit(0)

        filename = os.path.join(dials_regression, 'image_examples', 'XDS',
                                'XPARM.XDS')

        import dxtbx
        models = dxtbx.load(filename)
        self.detector = models.get_detector()
        self.beam = models.get_beam()
        assert (len(self.detector) == 1)
        self.t0 = 0.320
        from cctbx.eltbx import attenuation_coefficient
        table = attenuation_coefficient.get_table("Si")
        self.mu = table.mu_at_angstrom(self.beam.get_wavelength()) / 10.0
        self.distance = self.detector[0].get_distance()
        self.origin = self.detector[0].get_ray_intersection(
            self.detector[0].get_normal())[1]
        self.pixel_size = self.detector[0].get_pixel_size()
Example #9
0
def test_parallax_correction():
    # Attenuation length
    table = attenuation_coefficient.get_table("Si")
    mu = table.mu_at_angstrom(1) / 10.0
    t0 = 0.320

    # Create the detector
    detector = Detector(
        Panel(
            "",  # Type
            "",  # Name
            (10, 0, 0),  # Fast axis
            (0, 10, 0),  # Slow axis
            (0, 0, 200),  # Origin
            (0.172, 0.172),  # Pixel size
            (512, 512),  # Image size
            (0, 1000),  # Trusted range
            0.0,  # Thickness
            "",  # Material
            ParallaxCorrectedPxMmStrategy(mu, t0),
        )
    )
    for i in range(10000):
        mm = (random.uniform(-1000, 1000), random.uniform(-1000, 1000))
        px = detector[0].millimeter_to_pixel(mm)
        mm2 = detector[0].pixel_to_millimeter(px)
        assert abs(matrix.col(mm) - matrix.col(mm2)) < 1e-3
Example #10
0
    def test(self, dials_regression):
        filename = os.path.join(dials_regression, "image_examples", "XDS",
                                "XPARM.XDS")

        import dxtbx

        models = dxtbx.load(filename)
        self.detector = models.get_detector()
        self.beam = models.get_beam()
        assert len(self.detector) == 1
        self.t0 = 0.320
        from cctbx.eltbx import attenuation_coefficient

        table = attenuation_coefficient.get_table("Si")
        self.mu = table.mu_at_angstrom(self.beam.get_wavelength()) / 10.0
        self.distance = self.detector[0].get_distance()
        self.origin = self.detector[0].get_ray_intersection(
            self.detector[0].get_normal())[1]
        self.pixel_size = self.detector[0].get_pixel_size()

        from random import uniform

        # Generate some random coordinates and do the correction
        random_coord = lambda: (uniform(-1000, 1000), uniform(-1000, 1000))
        for i in range(10000):
            xy = random_coord()
            self.tst_single(xy)

        from scitbx.array_family import flex

        xy = flex.vec2_double([random_coord() for i in range(100)])
        self.tst_array(xy)

        self.tst_inverted_axis()
def tst_for_z(z):
  from cctbx.eltbx import attenuation_coefficient

  eps = 1e-7

  # Get the table
  table = attenuation_coefficient.get_table(z)

  # Get list of energies and coefficients
  energy = table.energy()[1:-1]
  mu_rho = table.mu_rho()[1:-1]
  mu_en_rho = table.mu_en_rho()[1:-1]

  # Check values at measured energies match
  for i in range(len(energy)):
    e = energy[i] + 1e-16 # move beyond edges
    mr = mu_rho[i]
    mer = mu_en_rho[i]

    if i < len(energy) - 1:
      if abs(e - energy[i+1]) < eps:
        continue

    mr2 = table.mu_rho_at_ev(e * 1000000.0)
    mer2 = table.mu_en_rho_at_ev(e * 1000000.0)
#   print "%3d, %3d, %15f MeV -- %15f %15f %15f %15f -- %15.9f %15.9f" % (z, i, e, mr, mr2, mer, mer2, abs(mr - mr2), abs(mer - mer2))
    assert(abs(mr - mr2) <= eps)
    assert(abs(mer - mer2) <= eps)

  print 'OK'
Example #12
0
    def _detector(self):
        """ Create an Eiger detector profile (taken from FormatCBFMiniEiger) """
        configuration = self.header["configuration"]
        info = self.header["info"]

        distance = configuration["detector_distance"]
        wavelength = configuration["wavelength"]
        beam_x = configuration["beam_center_x"]
        beam_y = configuration["beam_center_y"]

        pixel_x = configuration["x_pixel_size"]
        pixel_y = configuration["y_pixel_size"]

        material = configuration["sensor_material"]
        thickness = configuration["sensor_thickness"] * 1000

        nx = configuration["x_pixels_in_detector"]
        ny = configuration["y_pixels_in_detector"]

        if "count_rate_correction_count_cutoff" in configuration:
            overload = configuration["count_rate_correction_count_cutoff"]
        else:
            # hard-code if missing from Eiger stream header
            overload = 4001400
        underload = -1

        try:
            identifier = configuration["description"]
        except KeyError:
            identifier = "Unknown Eiger"

        table = attenuation_coefficient.get_table(material)
        mu = table.mu_at_angstrom(wavelength) / 10.0
        t0 = thickness

        detector = self._detector_factory.simple(
            sensor="PAD",
            distance=distance * 1000.0,
            beam_centre=(beam_x * pixel_x * 1000.0, beam_y * pixel_y * 1000.0),
            fast_direction="+x",
            slow_direction="-y",
            pixel_size=(1000 * pixel_x, 1000 * pixel_y),
            image_size=(nx, ny),
            trusted_range=(underload, overload),
            mask=[],
            px_mm=ParallaxCorrectedPxMmStrategy(mu, t0),
            mu=mu,
        )

        for f0, f1, s0, s1 in determine_eiger_mask(detector):
            detector[0].add_mask(f0 - 1, s0 - 1, f1, s1)

        for panel in detector:
            panel.set_thickness(thickness)
            panel.set_material(material)
            panel.set_identifier(identifier)
            panel.set_mu(mu)

        return detector
Example #13
0
    def _detector(self):
        '''Return a model for a simple detector, presuming no one has
    one of these on a two-theta stage. Assert that the beam centre is
    provided in the Mosflm coordinate frame.'''

        distance = float(
            self._cif_header_dictionary['Detector_distance'].split()[0])

        beam_xy = self._cif_header_dictionary['Beam_xy'].replace(
            '(', '').replace(')', '').replace(',', '').split()[:2]

        wavelength = float(
            self._cif_header_dictionary['Wavelength'].split()[0])

        beam_x, beam_y = map(float, beam_xy)

        pixel_xy = self._cif_header_dictionary['Pixel_size'].replace(
            'm', '').replace('x', '').split()

        pixel_x, pixel_y = map(float, pixel_xy)

        if 'Silicon' in self._cif_header_dictionary:
            thickness = float(
                self._cif_header_dictionary['Silicon'].split()[2]) * 1000.0
            material = 'Si'
        elif 'CdTe' in self._cif_header_dictionary:
            thickness = float(
                self._cif_header_dictionary['CdTe'].split()[2]) * 1000.0
            material = 'CdTe'
        else:
            thickness = 0.450
            material = 'Si'

        nx = int(
            self._cif_header_dictionary['X-Binary-Size-Fastest-Dimension'])
        ny = int(self._cif_header_dictionary['X-Binary-Size-Second-Dimension'])

        overload = dxtbx_overload_scale * int(
            self._cif_header_dictionary['Count_cutoff'].split()[0])
        underload = -1

        # take into consideration here the thickness of the sensor also the
        # wavelength of the radiation (which we have in the same file...)
        from cctbx.eltbx import attenuation_coefficient
        table = attenuation_coefficient.get_table(material)
        mu = table.mu_at_angstrom(wavelength) / 10.0
        t0 = thickness

        detector = self._detector_factory.simple(
            'PAD', distance * 1000.0,
            (beam_x * pixel_x * 1000.0, beam_y * pixel_y * 1000.0), '+x', '-y',
            (1000 * pixel_x, 1000 * pixel_y), (nx, ny), (underload, overload),
            [], ParallaxCorrectedPxMmStrategy(mu, t0))

        detector[0].set_thickness(thickness)
        detector[0].set_material(material)
        detector[0].set_mu(mu)

        return detector
Example #14
0
    def _detector(self):
        """Return a model for a simple detector, presuming no one has
        one of these on a two-theta stage. Assert that the beam centre is
        provided in the Mosflm coordinate frame."""

        distance = float(
            self._cif_header_dictionary["Detector_distance"].split()[0])

        beam_xy = (self._cif_header_dictionary["Beam_xy"].replace(
            "(", "").replace(")", "").replace(",", "").split()[:2])

        wavelength = float(
            self._cif_header_dictionary["Wavelength"].split()[0])

        beam_x, beam_y = map(float, beam_xy)

        pixel_xy = (self._cif_header_dictionary["Pixel_size"].replace(
            "m", "").replace("x", "").split())

        pixel_x, pixel_y = map(float, pixel_xy)

        thickness = float(
            self._cif_header_dictionary["Silicon"].split()[2]) * 1000.0

        nx = int(
            self._cif_header_dictionary["X-Binary-Size-Fastest-Dimension"])
        ny = int(self._cif_header_dictionary["X-Binary-Size-Second-Dimension"])

        overload = int(self._cif_header_dictionary["Count_cutoff"].split()[0])
        underload = -1

        # take into consideration here the thickness of the sensor also the
        # wavelength of the radiation (which we have in the same file...)
        from cctbx.eltbx import attenuation_coefficient

        table = attenuation_coefficient.get_table("Si")
        mu = table.mu_at_angstrom(wavelength) / 10.0
        t0 = thickness

        # FIXME would also be very nice to be able to take into account the
        # misalignment of the individual modules given the calibration information...

        detector = self._detector_factory.simple(
            "PAD",
            distance * 1000.0,
            (beam_x * pixel_x * 1000.0, beam_y * pixel_y * 1000.0),
            "+x",
            "-y",
            (1000 * pixel_x, 1000 * pixel_y),
            (nx, ny),
            (underload, overload),
            [],
            ParallaxCorrectedPxMmStrategy(mu, t0),
        )
        """
    for f0, f1, s0, s1 in determine_pilatus_mask(detector):
      detector[0].add_mask(f0-1, s0-1, f1, s1)
    """
        return detector
Example #15
0
    def _detector(self, index=None):
        from dxtbx.model.detector import Detector
        from scitbx import matrix
        import math

        wavelength = self.get_beam(index).get_wavelength()

        from dxtbx.model import ParallaxCorrectedPxMmStrategy
        from cctbx.eltbx import attenuation_coefficient

        table = attenuation_coefficient.get_table("Si")
        mu = table.mu_at_angstrom(wavelength) / 10.0
        px_mm = ParallaxCorrectedPxMmStrategy(mu, self.thickness)

        if self.RECONST_MODE:
            return self._detector_factory.simple(
                sensor="PAD",
                distance=self.distance,
                beam_centre=(
                    self.RECONST_SIZE / 2 * self.PIXEL_SIZE,
                    self.RECONST_SIZE / 2 * self.PIXEL_SIZE,
                ),
                fast_direction="-x",
                slow_direction="-y",
                pixel_size=(self.PIXEL_SIZE, self.PIXEL_SIZE),
                image_size=(self.RECONST_SIZE, self.RECONST_SIZE),
                trusted_range=(-1, 65535),
                mask=[],
            )  # TODO: add gaps

        detector = Detector()
        root = detector.hierarchy()
        root.set_frame((-1, 0, 0), (0, 1, 0), (0, 0, -self.distance))

        for i in range(8):
            angle = math.pi * self.panel_rotations[i] / 180.0
            fast = matrix.col((math.cos(angle), math.sin(angle), 0))
            slow = matrix.col((-math.sin(angle), math.cos(angle), 0))
            normal = fast.cross(slow)

            origin = (matrix.col((
                -self.panel_origins[i][0],
                self.panel_origins[i][1],
                self.panel_origins[i][2],
            )) / 1000.0)
            p = root.add_panel()
            p.set_type("SENSOR_PAD")
            p.set_name("Panel%d" % i)
            p.set_image_size((512, 1024))
            p.set_trusted_range((-1, 65535))
            p.set_pixel_size((self.PIXEL_SIZE, self.PIXEL_SIZE))
            p.set_thickness(self.thickness)
            p.set_local_frame(fast.elems, slow.elems, origin.elems)
            p.set_px_mm_strategy(px_mm)
            p.set_gain(10)

        return detector
  def _detector(self):
    '''Return a model for a simple detector, presuming no one has
    one of these on a two-theta stage. Assert that the beam centre is
    provided in the Mosflm coordinate frame.'''

    distance = float(
        self._cif_header_dictionary['Detector_distance'].split()[0])

    beam_xy = self._cif_header_dictionary['Beam_xy'].replace(
        '(', '').replace(')', '').replace(',', '').split()[:2]

    wavelength = float(
        self._cif_header_dictionary['Wavelength'].split()[0])

    beam_x, beam_y = map(float, beam_xy)

    pixel_xy = self._cif_header_dictionary['Pixel_size'].replace(
        'm', '').replace('x', '').split()

    pixel_x, pixel_y = map(float, pixel_xy)

    thickness = float(
      self._cif_header_dictionary['Silicon'].split()[2]) * 1000.0

    nx = int(
        self._cif_header_dictionary['X-Binary-Size-Fastest-Dimension'])
    ny = int(
        self._cif_header_dictionary['X-Binary-Size-Second-Dimension'])

    overload = dxtbx_overload_scale * int(
        self._cif_header_dictionary['Count_cutoff'].split()[0])
    underload = -1

    # take into consideration here the thickness of the sensor also the
    # wavelength of the radiation (which we have in the same file...)
    from cctbx.eltbx import attenuation_coefficient
    table = attenuation_coefficient.get_table("Si")
    mu = table.mu_at_angstrom(wavelength) / 10.0
    t0 = thickness

    detector = self._detector_factory.simple(
        'PAD', distance * 1000.0, (beam_x * pixel_x * 1000.0,
                                   beam_y * pixel_y * 1000.0), '+x', '-y',
        (1000 * pixel_x, 1000 * pixel_y),
        (nx, ny), (underload, overload), [],
        ParallaxCorrectedPxMmStrategy(mu, t0))

    for f0, s0, f1, s1 in determine_pilatus_mask(detector):
      detector[0].add_mask(f0, s0, f1, s1)

    detector[0].set_thickness(thickness)
    detector[0].set_material('Si')
    detector[0].set_mu(mu)

    return detector
    def _detector(self):
        '''Return a working detector instance, with added mask regions.'''

        detector = self._detector_factory.imgCIF_H(self._get_cbf_handle(),
                                                   'PAD')

        for f0, s0, f1, s1 in determine_pilatus_mask(detector):
            detector[0].add_mask(f0, s0, f1, s1)

        import re
        m = re.search('^#\s*(\S+)\ssensor, thickness\s*([0-9.]+)\s*m\s*$', \
                      self._cif_header, re.MULTILINE)
        if m:
            # header gives thickness in metres, we store mm
            thickness = float(m.group(2)) * 1000
            material = m.group(1)

            if material == 'Silicon':
                material = 'Si'

            for panel in detector:
                panel.set_thickness(thickness)
                panel.set_material(material)

            try:
                # a header only CBF file will not have a beam object
                beam = self._beam()

            except Exception:
                beam = None

            if beam:
                # attenuation coefficient depends on the beam wavelength
                wavelength = beam.get_wavelength()

                from cctbx.eltbx import attenuation_coefficient
                from dxtbx.model import ParallaxCorrectedPxMmStrategy
                # this will fail for undefined composite materials
                table = attenuation_coefficient.get_table(material)
                # mu_at_angstrom returns cm^-1
                mu = table.mu_at_angstrom(wavelength) / 10.0

                for panel in detector:
                    panel.set_px_mm_strategy(
                        ParallaxCorrectedPxMmStrategy(mu, thickness))
                    panel.set_mu(mu)

        m = re.search('^#\s*Detector:\s+(.*?)\s*$', \
                      self._cif_header, re.MULTILINE)
        if m and m.group(1):
            panel.set_identifier(m.group(1))

        return detector
  def _detector(self):
    '''Return a working detector instance, with added mask regions.'''

    detector = self._detector_factory.imgCIF_H(self._get_cbf_handle(),
                                               'PAD')

    for f0, s0, f1, s1 in determine_pilatus_mask(detector):
      detector[0].add_mask(f0, s0, f1, s1)

    import re
    m = re.search('^#\s*(\S+)\ssensor, thickness\s*([0-9.]+)\s*m\s*$', \
                  self._cif_header, re.MULTILINE)
    if m:
      # header gives thickness in metres, we store mm
      thickness = float(m.group(2)) * 1000
      material = m.group(1)

      if material == 'Silicon':
        material = 'Si'

      for panel in detector:
        panel.set_thickness(thickness)
        panel.set_material(material)

      try:
        # a header only CBF file will not have a beam object
        beam = self._beam()

      except Exception:
        beam = None

      if beam:
        # attenuation coefficient depends on the beam wavelength
        wavelength = beam.get_wavelength()

        from cctbx.eltbx import attenuation_coefficient
        from dxtbx.model import ParallaxCorrectedPxMmStrategy
        # this will fail for undefined composite materials
        table = attenuation_coefficient.get_table(material)
        # mu_at_angstrom returns cm^-1
        mu = table.mu_at_angstrom(wavelength) / 10.0

        for panel in detector:
          panel.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, thickness))
          panel.set_mu(mu)

    m = re.search('^#\s*Detector:\s+(.*?)\s*$', \
                  self._cif_header, re.MULTILINE)
    if m and m.group(1):
      panel.set_identifier(m.group(1))

    return detector
def model(dials_regression):
    filename = os.path.join(dials_regression, "image_examples", "XDS", "XPARM.XDS")

    models = dxtbx.load(filename)
    detector = models.get_detector()
    assert len(detector) == 1
    detector = detector[0]
    t0 = 0.320

    table = attenuation_coefficient.get_table("Si")
    mu = table.mu_at_angstrom(models.get_beam().get_wavelength()) / 10.0
    pixel_size = detector.get_pixel_size()

    return {"mu": mu, "t0": t0, "detector": detector, "pixel_size": pixel_size}
  def _detector(self):
    '''Partly dummy detector'''
    from scitbx import matrix

    # Get the detector geometry
    entry = self._h5_handle['entry']
    instrument = entry['instrument']
    detector = instrument['detector']

    # Initialise detector frame - origin at 0,0,0
    fast = matrix.col((1.0, 0.0, 0.0))
    slow = matrix.col((0.0, 1.0, 0.0))
    orig = matrix.col((0.0, 0.0, 0.0))

    # Get the pixel and image size
    pixel_size = 1.e-3 * detector['x_pixel_size'].value, \
                 1.e-3 * detector['y_pixel_size'].value
    layout = detector['layout'].value[0].split('X')
    image_size = int(layout[0]), int(layout[1])
    trusted_range = (-1, detector['saturation_value'][0])
    thickness = float(detector['sensor_thickness'].value) / 1000.
    material = str(detector['sensor_material'].value[0])

    # Make the detector
    detector = self._detector_factory.make_detector(
      "PAD", fast, slow, orig,
      pixel_size, image_size, trusted_range,
      name="Panel", thickness=thickness, material=material,)

    # At the moment, beam is a dummy object because wavelength is not set in
    # the header. Therefore, the px<-->mm strategy will generally be
    # incorrect. Set it anyway, to override later.
    beam = self._beam()
    wavelength = beam.get_wavelength()

    from cctbx.eltbx import attenuation_coefficient
    from dxtbx.model import ParallaxCorrectedPxMmStrategy

    # this will fail for undefined composite materials
    table = attenuation_coefficient.get_table(material)

    # mu_at_angstrom returns cm^-1, but need mu in mm^-1
    mu = table.mu_at_angstrom(wavelength) / 10.0

    for panel in detector:
      panel.set_mu(mu)
      panel.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, thickness))

    return detector
Example #21
0
  def _detector(self):
    distance = float(
        self._cif_header_dictionary['Detector_distance'].split()[0])

    beam_xy = self._cif_header_dictionary['Beam_xy'].replace(
        '(', '').replace(')', '').replace(',', '').split()[:2]

    wavelength = float(
        self._cif_header_dictionary['Wavelength'].split()[0])

    beam_x, beam_y = map(float, beam_xy)

    pixel_xy = self._cif_header_dictionary['Pixel_size'].replace(
        'm', '').replace('x', '').split()

    pixel_x, pixel_y = map(float, pixel_xy)

    thickness = float(
      self._cif_header_dictionary['Silicon'].split()[-2]) * 1000.0

    nx = int(
        self._cif_header_dictionary['X-Binary-Size-Fastest-Dimension'])
    ny = int(
        self._cif_header_dictionary['X-Binary-Size-Second-Dimension'])

    overload = int(
        self._cif_header_dictionary['Count_cutoff'].split()[0])
    underload = -1

    from cctbx.eltbx import attenuation_coefficient
    table = attenuation_coefficient.get_table("Si")
    mu = table.mu_at_angstrom(wavelength) / 10.0
    t0 = thickness

    detector = self._detector_factory.simple(
        'PAD', distance * 1000.0, (beam_x * pixel_x * 1000.0,
                                   beam_y * pixel_y * 1000.0), '+x', '-y',
        (1000 * pixel_x, 1000 * pixel_y),
        (nx, ny), (underload, overload), [],
        ParallaxCorrectedPxMmStrategy(mu, t0))

    for f0, s0, f1, s1 in [(0, 513, 1030, 550)]:
      detector[0].add_mask(f0, s0, f1, s1)

    return detector
  def _detector(self):
    distance = float(
        self._cif_header_dictionary['Detector_distance'].split()[0])

    beam_xy = self._cif_header_dictionary['Beam_xy'].replace(
        '(', '').replace(')', '').replace(',', '').split()[:2]

    wavelength = float(
        self._cif_header_dictionary['Wavelength'].split()[0])

    beam_x, beam_y = map(float, beam_xy)

    pixel_xy = self._cif_header_dictionary['Pixel_size'].replace(
        'm', '').replace('x', '').split()

    pixel_x, pixel_y = map(float, pixel_xy)

    thickness = float(
      self._cif_header_dictionary['Silicon'].split()[-2]) * 1000.0

    nx = int(
        self._cif_header_dictionary['X-Binary-Size-Fastest-Dimension'])
    ny = int(
        self._cif_header_dictionary['X-Binary-Size-Second-Dimension'])

    overload = int(
        self._cif_header_dictionary['Count_cutoff'].split()[0])
    underload = -1

    from cctbx.eltbx import attenuation_coefficient
    table = attenuation_coefficient.get_table("Si")
    mu = table.mu_at_angstrom(wavelength) / 10.0
    t0 = thickness

    detector = self._detector_factory.simple(
        'PAD', distance * 1000.0, (beam_x * pixel_x * 1000.0,
                                   beam_y * pixel_y * 1000.0), '+x', '-y',
        (1000 * pixel_x, 1000 * pixel_y),
        (nx, ny), (underload, overload), [],
        ParallaxCorrectedPxMmStrategy(mu, t0))

    for f0, s0, f1, s1 in [(0, 513, 1030, 550)]:
      detector[0].add_mask(f0, s0, f1, s1)

    return detector
Example #23
0
class FormatCBFCspad(FormatCBFMultiTileHierarchy, FormatStill):
    '''An image reading class CSPAD CBF files'''
    @staticmethod
    def understand(image_file):
        '''Check to see if this looks like an CSPD CBF format image, i.e. we can
    make sense of it.'''

        cbf_handle = pycbf.cbf_handle_struct()
        cbf_handle.read_widefile(image_file, pycbf.MSG_DIGEST)

        cbf_handle.find_category("diffrn_detector")
        if cbf_handle.count_rows() > 1:
            return False  # support 1 detector per file for now

        cbf_handle.find_column("type")

        return cbf_handle.get_value() == "CS PAD"

    def _detector(self):
        d = FormatCBFMultiTileHierarchy._detector(self)

        try:
            # a header only CBF file will not have a beam object
            beam = self._beam()
        except Exception, e:
            if "CBF_NOTFOUND" not in str(e): raise e
            return d

        # take into consideration here the thickness of the sensor also the
        # wavelength of the radiation (which we have in the same file...)
        wavelength = beam.get_wavelength()
        thickness = 0.5
        from cctbx.eltbx import attenuation_coefficient
        table = attenuation_coefficient.get_table("Si")
        # mu_at_angstrom returns cm^-1
        mu = table.mu_at_angstrom(wavelength) / 10.0
        t0 = thickness

        for panel in d:
            panel.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, t0))
        return d
  def _detector(self):
    '''Return a working detector instance, with added mask regions.'''

    cif_header = FormatCBFFullPilatus.get_cbf_header(self._image_file)

    self._cif_header_dictionary = { }

    for record in cif_header.split('\n'):
      if not '#' in record[:1]:
        continue

      if len(record[1:].split()) <= 2 and record.count(':') == 2:
        self._cif_header_dictionary['timestamp'] = record[1:].strip()
        continue

      tokens = record.replace('=', '').replace(':', '').split()[1:]

      self._cif_header_dictionary[tokens[0]] = ' '.join(tokens[1:])

    for record in self._mime_header.split('\n'):
      if not record.strip():
        continue
      token, value = record.split(':')
      self._cif_header_dictionary[token.strip()] = value.strip()


    distance = float(
        self._cif_header_dictionary['Detector_distance'].split()[0])

    beam_xy = self._cif_header_dictionary['Beam_xy'].replace(
        '(', '').replace(')', '').replace(',', '').split()[:2]

    wavelength = float(
        self._cif_header_dictionary['Wavelength'].split()[0])

    beam_x, beam_y = map(float, beam_xy)

    pixel_xy = self._cif_header_dictionary['Pixel_size'].replace(
        'm', '').replace('x', '').split()

    pixel_x, pixel_y = map(float, pixel_xy)

    nx = int(
        self._cif_header_dictionary['X-Binary-Size-Fastest-Dimension'])
    ny = int(
        self._cif_header_dictionary['X-Binary-Size-Second-Dimension'])

    overload = int(
        self._cif_header_dictionary['Count_cutoff'].split()[0])
    underload = -1

    two_theta = float(self._cif_header_dictionary['Detector_2theta'].split()[0])

    # hard code "correct" values for these
    distance = 0.11338
    beam_x = 222.0
    beam_y = 383.0

    detector = self._detector_factory.two_theta(
        'PAD', distance * 1000.0, (beam_x * pixel_x * 1000.0,
                                   beam_y * pixel_y * 1000.0), '+x', '-y',
                                   '+x', two_theta,
        (1000 * pixel_x, 1000 * pixel_y),
        (nx, ny), (underload, overload), [], None)

    import re
    m = re.search('^#\s*(\S+)\ssensor, thickness\s*([0-9.]+)\s*m\s*$', \
                  self._cif_header, re.MULTILINE)

    if m:
      # header gives thickness in metres, we store mm
      thickness = float(m.group(2)) * 1000
      material = m.group(1)

      if material == 'Silicon':
        material = 'Si'

      for panel in detector:
        panel.set_thickness(thickness)
        panel.set_material(material)

      try:
        # a header only CBF file will not have a beam object
        beam = self._beam()

      except Exception:
        pass

      if beam:
        # attenuation coefficient depends on the beam wavelength
        wavelength = beam.get_wavelength()

        from cctbx.eltbx import attenuation_coefficient
        from dxtbx.model import ParallaxCorrectedPxMmStrategy
        # this will fail for undefined composite materials
        table = attenuation_coefficient.get_table(material)
        # mu_at_angstrom returns cm^-1, but need mu in mm^-1
        mu = table.mu_at_angstrom(wavelength) / 10.0

        for panel in detector:
          panel.set_mu(mu)
          panel.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, thickness))

    return detector
Example #25
0
    def _detector(self):

        # module positions from detector blueprints - modelling at the moment as
        # 24 modules, each consisting of 5 sensors (the latter is ignored)

        from dxtbx.model import Detector
        from scitbx import matrix
        import math

        x = matrix.col((-1, 0, 0))
        y = matrix.col((0, 1, 0))
        z = matrix.col((0, 0, 1))

        beam_xy = self._cif_header_dictionary['Beam_xy']
        beam_xy = beam_xy.replace('(', '').replace(')',
                                                   '').replace(',',
                                                               '').split()[:2]
        obs_beam_x, obs_beam_y = [float(f) for f in beam_xy]

        ideal_beam_x = 1075
        ideal_beam_y = 2594

        beam_shift_x = 0.172 * (ideal_beam_x - obs_beam_x)
        beam_shift_y = 0.172 * (ideal_beam_y - obs_beam_y)

        distance = float(self._cif_header_dictionary['Detector_distance'].
                         split()[0]) * 1000.0

        wavelength = float(
            self._cif_header_dictionary['Wavelength'].split()[0])

        thickness = float(
            self._cif_header_dictionary['Silicon'].split()[2]) * 1000.0

        off_x = 184.9

        detector = Detector()
        root = detector.hierarchy()
        root.set_frame(x.elems, y.elems, (-distance * z + (beam_shift_x * x) +
                                          (beam_shift_y * y)).elems)

        from cctbx.eltbx import attenuation_coefficient
        table = attenuation_coefficient.get_table("Si")
        mu = table.mu_at_angstrom(wavelength) / 10.0
        t0 = thickness
        px_mm = ParallaxCorrectedPxMmStrategy(mu, t0)

        self.coords = {}

        for j in range(24):
            shift_y = 195 + 17
            ymin, ymax = j * shift_y, j * shift_y + 195

            angle = math.pi * (-12.2 + 0.5 * 7.903 + j *
                               (7.903 + 0.441)) / 180.0
            fast = matrix.col((1, 0, 0))
            slow = matrix.col((0, math.sin(angle), math.cos(angle)))
            normal = fast.cross(slow)

            row_origin = 250.0 * normal - off_x * fast - 16.8 * slow

            if not self._multi_panel:
                xmin, xmax = 0, 2463

                # OK two calls to add_panel here for detector like things => two
                # copies of the panel then? https://github.com/dials/dials/issues/189
                # ... this is also not the source of the leak

                # OBS! you need to set the panel to a root before set local frame...
                p = root.add_panel()
                p.set_type('SENSOR_PAD')
                p.set_name('row-%02d' % j)
                p.set_raw_image_offset((xmin, ymin))
                p.set_image_size((2463, 195))
                p.set_trusted_range((-1, 1000000))
                p.set_pixel_size((0.172, 0.172))
                p.set_local_frame(fast.elems, slow.elems, row_origin.elems)
                p.set_thickness(thickness)
                p.set_material('Si')
                p.set_mu(mu)
                p.set_px_mm_strategy(px_mm)
                p.set_raw_image_offset((xmin, ymin))
                self.coords[p.get_name()] = (xmin, ymin, xmax, ymax)

            else:
                shift_x = 487 + 7

                for i in range(5):
                    xmin, xmax = i * shift_x, i * shift_x + 487
                    origin = row_origin + i * (487 + 7) * 0.172 * fast

                    # OBS! you need to set the panel to a root before set local frame...
                    p = root.add_panel()
                    p.set_type('SENSOR_PAD')
                    p.set_name('row-%02d-col-%02d' % (j, i))
                    p.set_raw_image_offset((xmin, ymin))
                    p.set_image_size((487, 195))
                    p.set_trusted_range((-1, 1000000))
                    p.set_pixel_size((0.172, 0.172))
                    p.set_local_frame(fast.elems, slow.elems, origin.elems)
                    p.set_thickness(thickness)
                    p.set_material('Si')
                    p.set_mu(mu)
                    p.set_px_mm_strategy(px_mm)
                    p.set_raw_image_offset((xmin, ymin))
                    self.coords[p.get_name()] = (xmin, ymin, xmax, ymax)

        return detector
Example #26
0
  def override_detector(self, detector, params, beam, beam_params):
    '''
    Override the detector parameters

    '''

    # need to gather material from multiple phil parameters to set
    frame_hash = { }
    for panel_params in params.panel:
      panel_id = panel_params.id
      panel = detector[panel_params.id]

      if not panel_id in frame_hash:
        frame_hash[panel_id] = {'fast_axis':None,
                                'slow_axis':None,
                                'origin':None}

      if panel_params.fast_axis is not None:
        frame_hash[panel_id]['fast_axis'] = panel_params.fast_axis
      if panel_params.slow_axis is not None:
        frame_hash[panel_id]['slow_axis'] = panel_params.slow_axis
      if panel_params.origin is not None:
        frame_hash[panel_id]['origin'] = panel_params.origin

      if panel_params.name is not None:
        panel.set_name(panel_params.name)
      if panel_params.type is not None:
        panel.set_type(panel_params.type)
      if panel_params.pixel_size is not None:
        panel.set_pixel_size(panel_params.pixel_size)
      if panel_params.image_size is not None:
        panel.set_image_size(panel_params.image_size)
      if panel_params.trusted_range is not None:
        panel.set_trusted_range(panel_params.trusted_range)
      if panel_params.thickness is not None:
        panel.set_thickness(panel_params.thickness)
      if panel_params.material is not None:
        panel.set_material(panel_params.material)

      # Update the parallax correction
      if (panel_params.material is not None or
          panel_params.thickness is not None or
          beam_params.wavelength is not None):
        from dxtbx.model import ParallaxCorrectedPxMmStrategy
        from cctbx.eltbx import attenuation_coefficient
        table = attenuation_coefficient.get_table(panel.get_material())
        mu = table.mu_at_angstrom(beam.get_wavelength()) / 10.0
        t0 = panel.get_thickness()
        px_mm = ParallaxCorrectedPxMmStrategy(mu, t0)
        panel.set_px_mm_strategy(px_mm)
        panel.set_mu(mu)



    for panel_id in frame_hash:
      fast_axis = frame_hash[panel_id]['fast_axis']
      slow_axis = frame_hash[panel_id]['slow_axis']
      origin = frame_hash[panel_id]['origin']
      if [fast_axis, slow_axis, origin].count(None) == 0:
        panel = detector[panel_id]
        panel.set_frame(fast_axis, slow_axis, origin)
      elif [fast_axis, slow_axis, origin].count(None) != 3:
        raise Sorry("fast_axis, slow_axis and origin must be set together")
  def _detector(self):

    # module positions from detector blueprints - modelling at the moment as
    # 24 modules, each consisting of 5 sensors (the latter is ignored)

    from dxtbx.model.detector import HierarchicalDetector
    from scitbx import matrix
    import math

    x = matrix.col((1, 0, 0))
    y = matrix.col((0, 1, 0))
    z = matrix.col((0, 0, 1))

    obs_beam_y = 2587
    ideal_beam_y = 2594
    beam_shift_y = 0.172 * (2594 - 2587)

    distance = float(
        self._cif_header_dictionary['Detector_distance'].split()[0]) * 1000.0

    wavelength = float(
        self._cif_header_dictionary['Wavelength'].split()[0])

    thickness = float(
      self._cif_header_dictionary['Silicon'].split()[2]) * 1000.0

    detector = HierarchicalDetector()
    root = detector.hierarchy()
    root.set_frame(
      (1, 0, 0),
      (0, 1, 0),
      (0, 0, - (250 + distance)))

    from cctbx.eltbx import attenuation_coefficient
    table = attenuation_coefficient.get_table("Si")
    mu = table.mu_at_angstrom(wavelength) / 10.0
    t0 = thickness
    px_mm = ParallaxCorrectedPxMmStrategy(mu, t0)

    for j in range(24):

      angle = math.pi * (-12.2 + 0.5 * 7.903 + j * (7.903 + 0.441)) / 180.0
      fast = matrix.col((-1, 0, 0))
      slow = matrix.col((0, math.sin(angle), - math.cos(angle)))
      normal = fast.cross(slow)
      # for longer wavelength data sets move 192.3 below to 184.9
      if wavelength < 1.128:
        off_x = 191.9
      else:
        off_x = 184.9

      if group_rows:
        origin = 250.0 * normal - off_x * fast - 16.8 * slow + 250 * z + \
            beam_shift_y * y
        p = detector.add_panel()

        # OBS! you need to set the panel to a root before set local frame...
        root.add_panel(p)
        p.set_name('row-%02d' % j)
        p.set_image_size((2463, 195))
        p.set_trusted_range((-1, 1000000))
        p.set_pixel_size((0.172, 0.172))
        p.set_local_frame(
          fast.elems,
          slow.elems,
          origin.elems)
        p.set_px_mm_strategy(px_mm)

      else:
        row_origin = 250.0 * normal - off_x * fast - 16.8 * slow + 250 * z + \
            beam_shift_y * y

        for i in range(5):
          p = detector.add_panel()
          origin = row_origin + i * (487+7) * 0.172 * fast

          # OBS! you need to set the panel to a root before set local frame...
          root.add_panel(p)
          p.set_name('row-%02d' % j)
          p.set_image_size((487, 195))
          p.set_trusted_range((-1, 1000000))
          p.set_pixel_size((0.172, 0.172))
          p.set_local_frame(
            fast.elems,
            slow.elems,
            origin.elems)
          p.set_px_mm_strategy(px_mm)

    return detector
Example #28
0
    def _detector(self):
        """Return a model for a simple detector, presuming no one has
        one of these on a two-theta stage. Assert that the beam centre is
        provided in the Mosflm coordinate frame."""

        if not self._multi_panel:
            detector = FormatCBFMini._detector(self)
            for f0, f1, s0, s1 in determine_pilatus_mask(detector):
                detector[0].add_mask(f0 - 1, s0 - 1, f1, s1)
            return detector

        # got to here means 60-panel version
        d = Detector()

        distance = float(
            self._cif_header_dictionary["Detector_distance"].split()[0])

        beam_xy = (self._cif_header_dictionary["Beam_xy"].replace(
            "(", "").replace(")", "").replace(",", "").split()[:2])

        beam_x, beam_y = map(float, beam_xy)

        wavelength = float(
            self._cif_header_dictionary["Wavelength"].split()[0])

        pixel_xy = (self._cif_header_dictionary["Pixel_size"].replace(
            "m", "").replace("x", "").split())

        pixel_x, pixel_y = map(float, pixel_xy)

        thickness = float(
            self._cif_header_dictionary["Silicon"].split()[2]) * 1000.0

        nx = int(
            self._cif_header_dictionary["X-Binary-Size-Fastest-Dimension"])
        ny = int(self._cif_header_dictionary["X-Binary-Size-Second-Dimension"])

        overload = int(self._cif_header_dictionary["Count_cutoff"].split()[0])
        underload = -1

        # take into consideration here the thickness of the sensor also the
        # wavelength of the radiation (which we have in the same file...)
        table = attenuation_coefficient.get_table("Si")
        mu = table.mu_at_angstrom(wavelength) / 10.0
        t0 = thickness

        # FIXME would also be very nice to be able to take into account the
        # misalignment of the individual modules given the calibration...

        # single detector or multi-module detector

        pixel_x *= 1000.0
        pixel_y *= 1000.0
        distance *= 1000.0

        beam_centre = matrix.col((beam_x * pixel_x, beam_y * pixel_y, 0))

        fast = matrix.col((1.0, 0.0, 0.0))
        slow = matrix.col((0.0, -1.0, 0.0))
        s0 = matrix.col((0, 0, -1))
        origin = (distance * s0) - (fast * beam_centre[0]) - (slow *
                                                              beam_centre[1])

        root = d.hierarchy()
        root.set_local_frame(fast.elems, slow.elems, origin.elems)

        det = _DetectorDatabase["Pilatus"]

        # Edge dead areas not included, only gaps between modules matter
        n_fast, remainder = divmod(nx, det.module_size_fast)
        assert (n_fast - 1) * det.gap_fast == remainder

        n_slow, remainder = divmod(ny, det.module_size_slow)
        assert (n_slow - 1) * det.gap_slow == remainder

        mx = det.module_size_fast
        my = det.module_size_slow
        dx = det.gap_fast
        dy = det.gap_slow

        xmins = [(mx + dx) * i for i in range(n_fast)]
        xmaxes = [mx + (mx + dx) * i for i in range(n_fast)]
        ymins = [(my + dy) * i for i in range(n_slow)]
        ymaxes = [my + (my + dy) * i for i in range(n_slow)]

        self.coords = {}

        fast = matrix.col((1.0, 0.0, 0.0))
        slow = matrix.col((0.0, 1.0, 0.0))
        panel_idx = 0
        for ymin, ymax in zip(ymins, ymaxes):
            for xmin, xmax in zip(xmins, xmaxes):
                xmin_mm = xmin * pixel_x
                ymin_mm = ymin * pixel_y

                origin_panel = fast * xmin_mm + slow * ymin_mm

                panel_name = "Panel%d" % panel_idx
                panel_idx += 1

                p = d.add_panel()
                p.set_type("SENSOR_PAD")
                p.set_name(panel_name)
                p.set_raw_image_offset((xmin, ymin))
                p.set_image_size((xmax - xmin, ymax - ymin))
                p.set_trusted_range((underload, overload))
                p.set_pixel_size((pixel_x, pixel_y))
                p.set_thickness(thickness)
                p.set_material("Si")
                p.set_mu(mu)
                p.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, t0))
                p.set_local_frame(fast.elems, slow.elems, origin_panel.elems)
                p.set_raw_image_offset((xmin, ymin))
                self.coords[panel_name] = (xmin, ymin, xmax, ymax)

        return d
Example #29
0
    def _detector(self):
        """Return a model for the detector, allowing for two-theta offsets
        and the detector position. This will be rather more complex..."""

        detector_name = self._header_dictionary["DETECTOR_NAMES"].split()[0].strip()

        detector_axes = self.get_detector_axes(detector_name)
        fast = matrix.col(tuple(detector_axes[:3]))
        slow = matrix.col(tuple(detector_axes[3:]))
        distortion = self.get_distortion(detector_name)

        # multiply through by the distortion to get the true detector fast, slow

        detector_fast, detector_slow = (
            distortion[0] * fast + distortion[1] * slow,
            distortion[2] * fast + distortion[3] * slow,
        )

        beam_pixels = self.get_beam_pixels(detector_name)
        pixel_size = self.get_pixel_size(detector_name)
        image_size = self.get_image_size(detector_name)

        detector_origin = -(
            beam_pixels[0] * pixel_size[0] * detector_fast
            + beam_pixels[1] * pixel_size[1] * detector_slow
        )

        gonio_axes = self.get_gonio_axes(detector_name)
        gonio_values = self.get_gonio_values(detector_name)
        gonio_units = self._header_dictionary["%sGONIO_UNITS" % detector_name].split()
        gonio_num_axes = int(
            self._header_dictionary["%sGONIO_NUM_VALUES" % detector_name]
        )

        rotations = []
        translations = []

        for j, unit in enumerate(gonio_units):
            axis = matrix.col(gonio_axes[3 * j : 3 * (j + 1)])
            if unit == "deg":
                rotations.append(
                    axis.axis_and_angle_as_r3_rotation_matrix(gonio_values[j], deg=True)
                )
                translations.append(matrix.col((0.0, 0.0, 0.0)))
            elif unit == "mm":
                rotations.append(
                    matrix.sqr((1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0))
                )
                translations.append(gonio_values[j] * axis)
            else:
                raise RuntimeError("unknown axis unit %s" % unit)

        rotations.reverse()
        translations.reverse()

        for j in range(gonio_num_axes):
            detector_fast = rotations[j] * detector_fast
            detector_slow = rotations[j] * detector_slow
            detector_origin = rotations[j] * detector_origin
            detector_origin = translations[j] + detector_origin

        overload = int(float(self._header_dictionary["SATURATED_VALUE"]))
        underload = -1

        # Unfortunately thickness and material are not stored in the header. Set
        # to sensible defaults.
        t0 = 0.450
        material = "Si"

        table = attenuation_coefficient.get_table(material)
        wavelength = float(self._header_dictionary["SCAN_WAVELENGTH"])
        mu = table.mu_at_angstrom(wavelength) / 10.0

        detector = self._detector_factory.complex(
            "PAD",
            detector_origin.elems,
            detector_fast.elems,
            detector_slow.elems,
            pixel_size,
            image_size,
            (underload, overload),
            px_mm=ParallaxCorrectedPxMmStrategy(mu, t0),
            mu=mu,
        )

        for panel in detector:
            panel.set_thickness(t0)
            panel.set_material(material)

        return detector
  def _detector(self):
    '''Detector model, allowing for small offsets in the positions of 60
    detector modules'''

    # Module positional offsets in x, y, in pixels - for the moment ignoring the
    # rotational offsets as these are not well defined. To be honest these
    # positional offsets are also not well defined as I do not know how they
    # should be applied...

    x = {
      (0, 0):  -0.477546,   (0, 1):   0.130578,   (0, 2):   0.045041,
      (0, 3):  -0.439872,   (0, 4):  -0.382077,   (1, 0):   0.087405,
      (1, 1):   0.249597,   (1, 2):   0.184265,   (1, 3):   0.158342,
      (1, 4):   0.025225,   (2, 0):  -0.179892,   (2, 1):  -0.010974,
      (2, 2):  -0.139207,   (2, 3):   0.282851,   (2, 4):  -0.442219,
      (3, 0):  -0.185027,   (3, 1):   0.218601,   (3, 2):   0.092585,
      (3, 3):    0.35862,   (3, 4):   -0.29161,   (4, 0):   0.145368,
      (4, 1):   0.609289,   (4, 2):   0.396265,   (4, 3):    0.41625,
      (4, 4):    0.07152,   (5, 0):   0.247142,   (5, 1):   0.046563,
      (5, 2):   0.248714,   (5, 3):  -0.044628,   (5, 4):  -0.391509,
      (6, 0):   0.516643,   (6, 1):   0.358453,   (6, 2):   0.069219,
      (6, 3):   0.095861,   (6, 4):  -0.167403,   (7, 0):  -0.381352,
      (7, 1):   -0.35338,   (7, 2):   0.348656,   (7, 3):   0.024543,
      (7, 4):   0.328706,   (8, 0):   0.150886,   (8, 1):   0.244987,
      (8, 2):  -0.102911,   (8, 3):    0.16633,   (8, 4):   0.386622,
      (9, 0):   0.037924,   (9, 1):   0.314392,   (9, 2):   0.238818,
      (9, 3):   0.815028,   (9, 4):  -0.048818,  (10, 0):  -0.670524,
      (10, 1):  -0.304119,  (10, 2):   0.252284,  (10, 3):   -0.05485,
      (10, 4):  -0.355264,  (11, 0):  -0.404947,  (11, 1):  -0.020622,
      (11, 2):   0.648473,  (11, 3):  -0.277175,  (11, 4):  -0.711951
    }

    y = {
      (0, 0):  -0.494797,   (0, 1):  -0.212976,   (0, 2):   0.085351,
      (0, 3):    0.35494,   (0, 4):   0.571189,   (1, 0):  -0.421708,
      (1, 1):   0.061914,   (1, 2):   0.238996,   (1, 3):   0.146692,
      (1, 4):   0.407145,   (2, 0):  -0.313212,   (2, 1):  -0.225025,
      (2, 2):   0.031613,   (2, 3):  -0.047839,   (2, 4):    0.42716,
      (3, 0):  -0.361193,   (3, 1):   0.057663,   (3, 2):   0.022357,
      (3, 3):   0.062717,   (3, 4):   0.150611,   (4, 0):   0.035511,
      (4, 1):  -0.271567,   (4, 2):   0.007761,   (4, 3):  -0.124021,
      (4, 4):   0.093017,   (5, 0):  -0.238897,   (5, 1):  -0.179724,
      (5, 2):  -0.113608,   (5, 3):   0.017841,   (5, 4):  -0.012933,
      (6, 0):  -0.166337,   (6, 1):  -0.272922,   (6, 2):  -0.194665,
      (6, 3):  -0.058535,   (6, 4):  -0.405404,   (7, 0):  -0.318824,
      (7, 1):  -0.311276,   (7, 2):  -0.205223,   (7, 3):  -0.292664,
      (7, 4):  -0.474762,   (8, 0):  -0.039504,   (8, 1):  -0.239887,
      (8, 2):  -0.343485,   (8, 3):  -0.459429,   (8, 4):  -0.426901,
      (9, 0):  -0.187805,   (9, 1):   0.282727,   (9, 2):  -0.601164,
      (9, 3):  -0.467605,   (9, 4):  -0.589271,  (10, 0):   0.028311,
      (10, 1):  -0.391571,  (10, 2):  -0.463112,  (10, 3):  -0.358092,
      (10, 4):  -0.285396,  (11, 0):    0.01863,  (11, 1):  -0.380099,
      (11, 2):  -0.234953,  (11, 3):  -0.593992,  (11, 4):  -0.801247
    }

    distance = float(
        self._cif_header_dictionary['Detector_distance'].split()[0])

    beam_xy = self._cif_header_dictionary['Beam_xy'].replace(
        '(', '').replace(')', '').replace(',', '').split()[:2]

    beam_x, beam_y = map(float, beam_xy)

    wavelength = float(
        self._cif_header_dictionary['Wavelength'].split()[0])

    pixel_xy = self._cif_header_dictionary['Pixel_size'].replace(
        'm', '').replace('x', '').split()

    pixel_x, pixel_y = map(float, pixel_xy)

    thickness = float(
      self._cif_header_dictionary['Silicon'].split()[2]) * 1000.0

    nx = int(
        self._cif_header_dictionary['X-Binary-Size-Fastest-Dimension'])
    ny = int(
        self._cif_header_dictionary['X-Binary-Size-Second-Dimension'])

    overload = int(
        self._cif_header_dictionary['Count_cutoff'].split()[0])
    underload = -1

    # take into consideration here the thickness of the sensor also the
    # wavelength of the radiation (which we have in the same file...)
    from cctbx.eltbx import attenuation_coefficient
    table = attenuation_coefficient.get_table("Si")
    mu = table.mu_at_angstrom(wavelength) / 10.0
    t0 = thickness

    # FIXME would also be very nice to be able to take into account the
    # misalignment of the individual modules given the calibration information...

    detector = self._detector_factory.simple(
        'PAD', distance * 1000.0, (beam_x * pixel_x * 1000.0,
                                   beam_y * pixel_y * 1000.0), '+x', '-y',
        (1000 * pixel_x, 1000 * pixel_y),
        (nx, ny), (underload, overload), [],
        ParallaxCorrectedPxMmStrategy(mu, t0))

    for f0, s0, f1, s1 in determine_pilatus_mask(detector):
      detector[0].add_mask(f0, s0, f1, s1)

    return detector
Example #31
0
def test_detector():
    from dxtbx.model import ParallaxCorrectedPxMmStrategy

    def create_detector(offset=0):
        # Create the detector
        detector = Detector(
            Panel(
                "",  # Type
                "Panel",  # Name
                (10, 0, 0),  # Fast axis
                (0, 10, 0),  # Slow axis
                (0 + offset, 0 + offset, 200 - offset),
                # Origin
                (0.172, 0.172),  # Pixel size
                (512, 512),  # Image size
                (0, 1000),  # Trusted range
                0.1,  # Thickness
                "Si",  # Material
                identifier="123"))  # Identifier
        return detector

    detector = create_detector()

    # Perform some tests
    tst_get_identifier(detector)
    tst_get_gain(detector)
    tst_set_mosflm_beam_centre(detector)
    tst_get_pixel_lab_coord(detector)
    tst_get_image_size_mm(detector)
    tst_is_value_in_trusted_range(detector)
    tst_is_coord_valid(detector)
    tst_pixel_to_millimeter_to_pixel(detector)
    tst_get_names(detector)
    tst_get_thickness(detector)
    tst_get_material(detector)
    tst_resolution(detector)
    tst_panel_mask()

    # Attenuation length
    from cctbx.eltbx import attenuation_coefficient
    table = attenuation_coefficient.get_table("Si")
    mu = table.mu_at_angstrom(1) / 10.0
    t0 = 0.320

    # Create another detector with different origin
    detector_moved = create_detector(offset=100)
    tst_detectors_are_different(detector, detector_moved)

    detector_moved_copy = create_detector(offset=100)
    tst_detectors_are_same(detector_moved, detector_moved_copy)

    # Create the detector
    detector = Detector(
        Panel(
            "",  # Type
            "",  # Name
            (10, 0, 0),  # Fast axis
            (0, 10, 0),  # Slow axis
            (0, 0, 200),  # Origin
            (0.172, 0.172),  # Pixel size
            (512, 512),  # Image size
            (0, 1000),  # Trusted range
            0.0,  # Thickness
            "",  # Material
            ParallaxCorrectedPxMmStrategy(mu, t0)))

    tst_parallax_correction(detector)
    def _detector(self):
        '''Detector model, allowing for small offsets in the positions of 60
    detector modules'''

        # Module positional offsets in x, y, in pixels - for the moment ignoring the
        # rotational offsets as these are not well defined. To be honest these
        # positional offsets are also not well defined as I do not know how they
        # should be applied...

        x = {
            (0, 0): -0.477546,
            (0, 1): 0.130578,
            (0, 2): 0.045041,
            (0, 3): -0.439872,
            (0, 4): -0.382077,
            (1, 0): 0.087405,
            (1, 1): 0.249597,
            (1, 2): 0.184265,
            (1, 3): 0.158342,
            (1, 4): 0.025225,
            (2, 0): -0.179892,
            (2, 1): -0.010974,
            (2, 2): -0.139207,
            (2, 3): 0.282851,
            (2, 4): -0.442219,
            (3, 0): -0.185027,
            (3, 1): 0.218601,
            (3, 2): 0.092585,
            (3, 3): 0.35862,
            (3, 4): -0.29161,
            (4, 0): 0.145368,
            (4, 1): 0.609289,
            (4, 2): 0.396265,
            (4, 3): 0.41625,
            (4, 4): 0.07152,
            (5, 0): 0.247142,
            (5, 1): 0.046563,
            (5, 2): 0.248714,
            (5, 3): -0.044628,
            (5, 4): -0.391509,
            (6, 0): 0.516643,
            (6, 1): 0.358453,
            (6, 2): 0.069219,
            (6, 3): 0.095861,
            (6, 4): -0.167403,
            (7, 0): -0.381352,
            (7, 1): -0.35338,
            (7, 2): 0.348656,
            (7, 3): 0.024543,
            (7, 4): 0.328706,
            (8, 0): 0.150886,
            (8, 1): 0.244987,
            (8, 2): -0.102911,
            (8, 3): 0.16633,
            (8, 4): 0.386622,
            (9, 0): 0.037924,
            (9, 1): 0.314392,
            (9, 2): 0.238818,
            (9, 3): 0.815028,
            (9, 4): -0.048818,
            (10, 0): -0.670524,
            (10, 1): -0.304119,
            (10, 2): 0.252284,
            (10, 3): -0.05485,
            (10, 4): -0.355264,
            (11, 0): -0.404947,
            (11, 1): -0.020622,
            (11, 2): 0.648473,
            (11, 3): -0.277175,
            (11, 4): -0.711951
        }

        y = {
            (0, 0): -0.494797,
            (0, 1): -0.212976,
            (0, 2): 0.085351,
            (0, 3): 0.35494,
            (0, 4): 0.571189,
            (1, 0): -0.421708,
            (1, 1): 0.061914,
            (1, 2): 0.238996,
            (1, 3): 0.146692,
            (1, 4): 0.407145,
            (2, 0): -0.313212,
            (2, 1): -0.225025,
            (2, 2): 0.031613,
            (2, 3): -0.047839,
            (2, 4): 0.42716,
            (3, 0): -0.361193,
            (3, 1): 0.057663,
            (3, 2): 0.022357,
            (3, 3): 0.062717,
            (3, 4): 0.150611,
            (4, 0): 0.035511,
            (4, 1): -0.271567,
            (4, 2): 0.007761,
            (4, 3): -0.124021,
            (4, 4): 0.093017,
            (5, 0): -0.238897,
            (5, 1): -0.179724,
            (5, 2): -0.113608,
            (5, 3): 0.017841,
            (5, 4): -0.012933,
            (6, 0): -0.166337,
            (6, 1): -0.272922,
            (6, 2): -0.194665,
            (6, 3): -0.058535,
            (6, 4): -0.405404,
            (7, 0): -0.318824,
            (7, 1): -0.311276,
            (7, 2): -0.205223,
            (7, 3): -0.292664,
            (7, 4): -0.474762,
            (8, 0): -0.039504,
            (8, 1): -0.239887,
            (8, 2): -0.343485,
            (8, 3): -0.459429,
            (8, 4): -0.426901,
            (9, 0): -0.187805,
            (9, 1): 0.282727,
            (9, 2): -0.601164,
            (9, 3): -0.467605,
            (9, 4): -0.589271,
            (10, 0): 0.028311,
            (10, 1): -0.391571,
            (10, 2): -0.463112,
            (10, 3): -0.358092,
            (10, 4): -0.285396,
            (11, 0): 0.01863,
            (11, 1): -0.380099,
            (11, 2): -0.234953,
            (11, 3): -0.593992,
            (11, 4): -0.801247
        }

        distance = float(
            self._cif_header_dictionary['Detector_distance'].split()[0])

        beam_xy = self._cif_header_dictionary['Beam_xy'].replace(
            '(', '').replace(')', '').replace(',', '').split()[:2]

        beam_x, beam_y = map(float, beam_xy)

        wavelength = float(
            self._cif_header_dictionary['Wavelength'].split()[0])

        pixel_xy = self._cif_header_dictionary['Pixel_size'].replace(
            'm', '').replace('x', '').split()

        pixel_x, pixel_y = map(float, pixel_xy)

        thickness = float(
            self._cif_header_dictionary['Silicon'].split()[2]) * 1000.0

        nx = int(
            self._cif_header_dictionary['X-Binary-Size-Fastest-Dimension'])
        ny = int(self._cif_header_dictionary['X-Binary-Size-Second-Dimension'])

        overload = int(self._cif_header_dictionary['Count_cutoff'].split()[0])
        underload = -1

        # take into consideration here the thickness of the sensor also the
        # wavelength of the radiation (which we have in the same file...)
        from cctbx.eltbx import attenuation_coefficient
        table = attenuation_coefficient.get_table("Si")
        mu = table.mu_at_angstrom(wavelength) / 10.0
        t0 = thickness

        # FIXME would also be very nice to be able to take into account the
        # misalignment of the individual modules given the calibration information...

        detector = self._detector_factory.simple(
            'PAD', distance * 1000.0,
            (beam_x * pixel_x * 1000.0, beam_y * pixel_y * 1000.0), '+x', '-y',
            (1000 * pixel_x, 1000 * pixel_y), (nx, ny), (underload, overload),
            [], ParallaxCorrectedPxMmStrategy(mu, t0))

        for f0, f1, s0, s1 in determine_pilatus_mask(detector):
            detector[0].add_mask(f0 - 1, s0 - 1, f1, s1)

        return detector
    def _detector(self):
        '''Detector model, allowing for small offsets in the positions of 60
    detector modules'''

        # Module positional offsets in x, y, in pixels - for the moment ignoring the
        # rotational offsets as these are not well defined. To be honest these
        # positional offsets are also not well defined as I do not know how they
        # should be applied...

        x = {
            (0, 0): -0.477546,
            (0, 1): 0.130578,
            (0, 2): 0.045041,
            (0, 3): -0.439872,
            (0, 4): -0.382077,
            (1, 0): 0.087405,
            (1, 1): 0.249597,
            (1, 2): 0.184265,
            (1, 3): 0.158342,
            (1, 4): 0.025225,
            (2, 0): -0.179892,
            (2, 1): -0.010974,
            (2, 2): -0.139207,
            (2, 3): 0.282851,
            (2, 4): -0.442219,
            (3, 0): -0.185027,
            (3, 1): 0.218601,
            (3, 2): 0.092585,
            (3, 3): 0.35862,
            (3, 4): -0.29161,
            (4, 0): 0.145368,
            (4, 1): 0.609289,
            (4, 2): 0.396265,
            (4, 3): 0.41625,
            (4, 4): 0.07152,
            (5, 0): 0.247142,
            (5, 1): 0.046563,
            (5, 2): 0.248714,
            (5, 3): -0.044628,
            (5, 4): -0.391509,
            (6, 0): 0.516643,
            (6, 1): 0.358453,
            (6, 2): 0.069219,
            (6, 3): 0.095861,
            (6, 4): -0.167403,
            (7, 0): -0.381352,
            (7, 1): -0.35338,
            (7, 2): 0.348656,
            (7, 3): 0.024543,
            (7, 4): 0.328706,
            (8, 0): 0.150886,
            (8, 1): 0.244987,
            (8, 2): -0.102911,
            (8, 3): 0.16633,
            (8, 4): 0.386622,
            (9, 0): 0.037924,
            (9, 1): 0.314392,
            (9, 2): 0.238818,
            (9, 3): 0.815028,
            (9, 4): -0.048818,
            (10, 0): -0.670524,
            (10, 1): -0.304119,
            (10, 2): 0.252284,
            (10, 3): -0.05485,
            (10, 4): -0.355264,
            (11, 0): -0.404947,
            (11, 1): -0.020622,
            (11, 2): 0.648473,
            (11, 3): -0.277175,
            (11, 4): -0.711951
        }

        y = {
            (0, 0): -0.494797,
            (0, 1): -0.212976,
            (0, 2): 0.085351,
            (0, 3): 0.35494,
            (0, 4): 0.571189,
            (1, 0): -0.421708,
            (1, 1): 0.061914,
            (1, 2): 0.238996,
            (1, 3): 0.146692,
            (1, 4): 0.407145,
            (2, 0): -0.313212,
            (2, 1): -0.225025,
            (2, 2): 0.031613,
            (2, 3): -0.047839,
            (2, 4): 0.42716,
            (3, 0): -0.361193,
            (3, 1): 0.057663,
            (3, 2): 0.022357,
            (3, 3): 0.062717,
            (3, 4): 0.150611,
            (4, 0): 0.035511,
            (4, 1): -0.271567,
            (4, 2): 0.007761,
            (4, 3): -0.124021,
            (4, 4): 0.093017,
            (5, 0): -0.238897,
            (5, 1): -0.179724,
            (5, 2): -0.113608,
            (5, 3): 0.017841,
            (5, 4): -0.012933,
            (6, 0): -0.166337,
            (6, 1): -0.272922,
            (6, 2): -0.194665,
            (6, 3): -0.058535,
            (6, 4): -0.405404,
            (7, 0): -0.318824,
            (7, 1): -0.311276,
            (7, 2): -0.205223,
            (7, 3): -0.292664,
            (7, 4): -0.474762,
            (8, 0): -0.039504,
            (8, 1): -0.239887,
            (8, 2): -0.343485,
            (8, 3): -0.459429,
            (8, 4): -0.426901,
            (9, 0): -0.187805,
            (9, 1): 0.282727,
            (9, 2): -0.601164,
            (9, 3): -0.467605,
            (9, 4): -0.589271,
            (10, 0): 0.028311,
            (10, 1): -0.391571,
            (10, 2): -0.463112,
            (10, 3): -0.358092,
            (10, 4): -0.285396,
            (11, 0): 0.01863,
            (11, 1): -0.380099,
            (11, 2): -0.234953,
            (11, 3): -0.593992,
            (11, 4): -0.801247
        }

        distance = float(
            self._cif_header_dictionary['Detector_distance'].split()[0])

        beam_xy = self._cif_header_dictionary['Beam_xy'].replace(
            '(', '').replace(')', '').replace(',', '').split()[:2]

        beam_x, beam_y = map(float, beam_xy)

        wavelength = float(
            self._cif_header_dictionary['Wavelength'].split()[0])

        pixel_xy = self._cif_header_dictionary['Pixel_size'].replace(
            'm', '').replace('x', '').split()

        pixel_x, pixel_y = map(float, pixel_xy)

        thickness = float(
            self._cif_header_dictionary['Silicon'].split()[2]) * 1000.0

        nx = int(
            self._cif_header_dictionary['X-Binary-Size-Fastest-Dimension'])
        ny = int(self._cif_header_dictionary['X-Binary-Size-Second-Dimension'])

        overload = int(self._cif_header_dictionary['Count_cutoff'].split()[0])
        underload = -1

        # take into consideration here the thickness of the sensor also the
        # wavelength of the radiation (which we have in the same file...)

        from cctbx.eltbx import attenuation_coefficient
        table = attenuation_coefficient.get_table("Si")
        mu = table.mu_at_angstrom(wavelength) / 10.0
        t0 = thickness

        # FIXME would also be very nice to be able to take into account the
        # misalignment of the individual modules given the calibration...

        # single detector or multi-module detector

        pixel_x *= 1000.0
        pixel_y *= 1000.0
        distance *= 1000.0

        if not self._multi_panel:
            detector = self._detector_factory.simple(
                'PAD', distance, (beam_x * pixel_x, beam_y * pixel_y), '+x',
                '-y', (pixel_x, pixel_y), (nx, ny), (underload, overload), [],
                ParallaxCorrectedPxMmStrategy(mu, t0))

            for f0, f1, s0, s1 in determine_pilatus_mask(detector):
                detector[0].add_mask(f0 - 1, s0 - 1, f1, s1)

            detector[0].set_thickness(thickness)
            detector[0].set_material('Si')
            detector[0].set_mu(mu)

            return detector

        # got to here means 60-panel version

        from dxtbx.model import Detector
        from scitbx import matrix

        d = Detector()

        beam_centre = matrix.col((beam_x * pixel_x, beam_y * pixel_y, 0))

        fast = matrix.col((1.0, 0.0, 0.0))
        slow = matrix.col((0.0, -1.0, 0.0))
        s0 = matrix.col((0, 0, -1))
        origin = (distance * s0) - (fast * beam_centre[0]) - \
          (slow * beam_centre[1])

        root = d.hierarchy()
        root.set_local_frame(fast.elems, slow.elems, origin.elems)

        xmins = [0, 494, 988, 1482, 1976]
        xmaxes = [487, 981, 1475, 1969, 2463]
        ymins = [
            0, 212, 424, 636, 848, 1060, 1272, 1484, 1696, 1908, 2120, 2332
        ]
        ymaxes = [
            195, 407, 619, 831, 1043, 1255, 1467, 1679, 1891, 2103, 2315, 2527
        ]

        self.coords = {}

        fast = matrix.col((1.0, 0.0, 0.0))
        slow = matrix.col((0.0, 1.0, 0.0))
        panel_idx = 0
        for ymin, ymax in zip(ymins, ymaxes):
            for xmin, xmax in zip(xmins, xmaxes):
                xmin_mm = xmin * pixel_x
                ymin_mm = ymin * pixel_y

                origin_panel = fast * xmin_mm + slow * ymin_mm

                panel_name = "Panel%d" % panel_idx
                panel_idx += 1

                p = root.add_panel()
                p.set_type("SENSOR_PAD")
                p.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, t0))
                p.set_name(panel_name)
                p.set_image_size((xmax - xmin, ymax - ymin))
                p.set_trusted_range((underload, overload))
                p.set_pixel_size((pixel_x, pixel_y))
                p.set_thickness(thickness)
                p.set_material('Si')
                p.set_mu(mu)
                p.set_local_frame(fast.elems, slow.elems, origin_panel.elems)
                p.set_raw_image_offset((xmin, ymin))
                self.coords[panel_name] = (xmin, ymin, xmax, ymax)

        return d
  def _detector(self):

    # module positions from detector blueprints - modelling at the moment as
    # 24 modules, each consisting of 5 sensors (the latter is ignored)

    from dxtbx.model import Detector
    from scitbx import matrix
    import math

    x = matrix.col((-1, 0, 0))
    y = matrix.col((0, 1, 0))
    z = matrix.col((0, 0, 1))

    obs_beam_y = 2587
    ideal_beam_y = 2594
    beam_shift_y = 0.172 * (2594 - 2587)

    distance = float(
        self._cif_header_dictionary['Detector_distance'].split()[0]) * 1000.0

    wavelength = float(
        self._cif_header_dictionary['Wavelength'].split()[0])

    thickness = float(
      self._cif_header_dictionary['Silicon'].split()[2]) * 1000.0

    # for longer wavelength data sets move 192.3 below to 184.9
    if wavelength < 1.128:
      off_x = 191.9
    else:
      off_x = 184.9

    z += beam_shift_y * y

    detector = Detector()
    root = detector.hierarchy()
    root.set_frame(
      x.elems,
      y.elems,
      (-distance * z).elems)

    from cctbx.eltbx import attenuation_coefficient
    table = attenuation_coefficient.get_table("Si")
    mu = table.mu_at_angstrom(wavelength) / 10.0
    t0 = thickness
    px_mm = ParallaxCorrectedPxMmStrategy(mu, t0)

    self.coords = {}

    for j in range(24):
      shift_y = 195 + 17
      ymin, ymax = j * shift_y, j * shift_y + 195

      angle = math.pi * (-12.2 + 0.5 * 7.903 + j * (7.903 + 0.441)) / 180.0
      fast = matrix.col((1, 0, 0))
      slow = matrix.col((0, math.sin(angle), math.cos(angle)))
      normal = fast.cross(slow)

      row_origin = 250.0 * normal - off_x * fast - 16.8 * slow

      if not self._multi_panel:
        xmin, xmax = 0, 2463

        # OK two calls to add_panel here for detector like things => two
        # copies of the panel then? https://github.com/dials/dials/issues/189
        # ... this is also not the source of the leak

        # OBS! you need to set the panel to a root before set local frame...
        p = root.add_panel()
        p.set_type('SENSOR_PAD')
        p.set_name('row-%02d' % j)
        p.set_raw_image_offset((xmin, ymin))
        p.set_image_size((2463, 195))
        p.set_trusted_range((-1, 1000000))
        p.set_pixel_size((0.172, 0.172))
        p.set_local_frame(
          fast.elems,
          slow.elems,
          row_origin.elems)
        p.set_thickness(thickness)
        p.set_material('Si')
        p.set_mu(mu)
        p.set_px_mm_strategy(px_mm)
        p.set_raw_image_offset((xmin,ymin))
        self.coords[p.get_name()] = (xmin,ymin,xmax,ymax)

      else:
        shift_x = 487 + 7

        for i in range(5):
          xmin, xmax = i * shift_x, i * shift_x + 487
          origin = row_origin + i * (487+7) * 0.172 * fast

          # OBS! you need to set the panel to a root before set local frame...
          p = root.add_panel()
          p.set_type('SENSOR_PAD')
          p.set_name('row-%02d-col-%02d' % (j, i))
          p.set_raw_image_offset((xmin, ymin))
          p.set_image_size((487, 195))
          p.set_trusted_range((-1, 1000000))
          p.set_pixel_size((0.172, 0.172))
          p.set_local_frame(
            fast.elems,
            slow.elems,
            origin.elems)
          p.set_thickness(thickness)
          p.set_material('Si')
          p.set_mu(mu)
          p.set_px_mm_strategy(px_mm)
          p.set_raw_image_offset((xmin,ymin))
          self.coords[p.get_name()] = (xmin,ymin,xmax,ymax)

    return detector
Example #35
0
    def _detector(self, index=None):
        from PSCalib.SegGeometryStore import sgs

        from xfel.cftbx.detector.cspad_cbf_tbx import basis_from_geo

        run = self.get_run_from_index(index)
        if run.run() in self._cached_detector:
            return self._cached_detector[run.run()]

        if index is None:
            index = 0
        self._env = self._ds.env()
        assert len(self.params.detector_address) == 1
        self._det = psana.Detector(self.params.detector_address[0], self._env)
        geom = self._det.pyda.geoaccess(self._get_event(index).run())
        pixel_size = (self._det.pixel_size(self._get_event(index)) / 1000.0
                      )  # convert to mm
        d = Detector()
        pg0 = d.hierarchy()
        # first deal with D0
        det_num = 0
        root = geom.get_top_geo()
        root_basis = basis_from_geo(root)
        while len(root.get_list_of_children()) == 1:
            sub = root.get_list_of_children()[0]
            sub_basis = basis_from_geo(sub)
            root = sub
            root_basis = root_basis * sub_basis
        t = root_basis.translation
        root_basis.translation = col((t[0], t[1], -t[2]))

        origin = col((root_basis * col((0, 0, 0, 1)))[0:3])
        fast = col((root_basis * col((1, 0, 0, 1)))[0:3]) - origin
        slow = col((root_basis * col((0, 1, 0, 1)))[0:3]) - origin
        pg0.set_local_frame(fast.elems, slow.elems, origin.elems)
        pg0.set_name("D%d" % (det_num))

        # Now deal with modules
        for module_num in range(len(root.get_list_of_children())):
            module = root.get_list_of_children()[module_num]
            module_basis = basis_from_geo(module)
            origin = col((module_basis * col((0, 0, 0, 1)))[0:3])
            fast = col((module_basis * col((1, 0, 0, 1)))[0:3]) - origin
            slow = col((module_basis * col((0, 1, 0, 1)))[0:3]) - origin
            pg1 = pg0.add_group()
            pg1.set_local_frame(fast.elems, slow.elems, origin.elems)
            pg1.set_name("D%dM%d" % (det_num, module_num))

            # Read the known layout of the Jungfrau 2x4 module
            sg = sgs.Create(segname=module.oname)
            xx, yy = sg.get_seg_xy_maps_um()
            xx = xx / 1000
            yy = yy / 1000

            # Now deal with ASICs
            for asic_num in range(8):
                val = "ARRAY_D0M%dA%d" % (module_num, asic_num)
                dim_slow = xx.shape[0]
                dim_fast = xx.shape[1]
                sensor_id = asic_num // 4  # There are 2X4 asics per module
                asic_in_sensor_id = asic_num % 4  # this number will be 0,1,2 or 3
                id_slow = sensor_id * (dim_slow // 2)
                id_fast = asic_in_sensor_id * (dim_fast // 4)
                origin = col((xx[id_slow][id_fast], yy[id_slow][id_fast], 0))
                fp = col(
                    (xx[id_slow][id_fast + 1], yy[id_slow][id_fast + 1], 0))
                sp = col(
                    (xx[id_slow + 1][id_fast], yy[id_slow + 1][id_fast], 0))
                fast = (fp - origin).normalize()
                slow = (sp - origin).normalize()
                p = pg1.add_panel()
                p.set_local_frame(fast.elems, slow.elems, origin.elems)
                p.set_pixel_size((pixel_size, pixel_size))
                p.set_trusted_range((-10, 2e6))
                p.set_name(val)

                thickness, material = 0.32, "Si"
                p.set_thickness(thickness)  # mm
                p.set_material(material)
                # Compute the attenuation coefficient.
                # This will fail for undefined composite materials
                # mu_at_angstrom returns cm^-1, but need mu in mm^-1
                table = attenuation_coefficient.get_table(material)
                wavelength = self.get_beam(index).get_wavelength()
                mu = table.mu_at_angstrom(wavelength) / 10.0
                p.set_mu(mu)
                p.set_px_mm_strategy(
                    ParallaxCorrectedPxMmStrategy(mu, thickness))

                if (self.params.jungfrau.use_big_pixels
                        and os.environ.get("DONT_USE_BIG_PIXELS_JUNGFRAU") is
                        None):
                    p.set_image_size((1030, 514))
                    break
                else:
                    p.set_image_size((dim_fast // 4, dim_slow // 2))

        if (self.params.jungfrau.use_big_pixels
                and os.environ.get("DONT_USE_BIG_PIXELS_JUNGFRAU") is None):
            assert len(d) == 8
        self._cached_detector[run.run()] = d
        return d
Example #36
0
    output {
        experiments = None
            .type = path
            .help = "The output experiment list file name. If None, don't output an " \
                    "experiment list file."
        reflections = corrected.refl
            .type = path
            .help = "The output reflection table file."
        log = dials.anvil_correction.log
            .type = path
    }
    """)

# Get the tabulated NIST mass attenuation coefficient data for carbon.
carbon_attenuation_data = attenuation_coefficient.get_table("C")


def goniometer_rotation(experiment: Experiment,
                        reflections: flex.reflection_table) -> Rotation:
    """
    Calculate the goniometer rotation operator for each reflection.

    Following the DXTBX model of a goniometer, whereby a scan is only possible
    around one physical axis at a time, the rotation operation (conventionally
    denoted R, here denoted R' to avoid confusion with the notation of
    dxtbx/model/goniometer.h) can be calculated as R' = S · R · F.
    Here:
        * S is the 'setting rotation', the operator denoting the position of all parent
        axes of the scan axis, which hence defines the orientation of the scan axis;
        * R is the the operator denoting the scan rotation as if it were performed with
    def _detector(self):
        '''Return a working detector instance, with added mask regions.'''

        cif_header = FormatCBFFullPilatus.get_cbf_header(self._image_file)

        self._cif_header_dictionary = {}

        for record in cif_header.split('\n'):
            if not '#' in record[:1]:
                continue

            if len(record[1:].split()) <= 2 and record.count(':') == 2:
                self._cif_header_dictionary['timestamp'] = record[1:].strip()
                continue

            tokens = record.replace('=', '').replace(':', '').split()[1:]

            self._cif_header_dictionary[tokens[0]] = ' '.join(tokens[1:])

        for record in self._mime_header.split('\n'):
            if not record.strip():
                continue
            token, value = record.split(':')
            self._cif_header_dictionary[token.strip()] = value.strip()

        distance = float(
            self._cif_header_dictionary['Detector_distance'].split()[0])

        beam_xy = self._cif_header_dictionary['Beam_xy'].replace(
            '(', '').replace(')', '').replace(',', '').split()[:2]

        wavelength = float(
            self._cif_header_dictionary['Wavelength'].split()[0])

        beam_x, beam_y = map(float, beam_xy)

        pixel_xy = self._cif_header_dictionary['Pixel_size'].replace(
            'm', '').replace('x', '').split()

        pixel_x, pixel_y = map(float, pixel_xy)

        nx = int(
            self._cif_header_dictionary['X-Binary-Size-Fastest-Dimension'])
        ny = int(self._cif_header_dictionary['X-Binary-Size-Second-Dimension'])

        overload = int(self._cif_header_dictionary['Count_cutoff'].split()[0])
        underload = -1

        two_theta = float(
            self._cif_header_dictionary['Detector_2theta'].split()[0])

        # hard code "correct" values for these
        distance = 0.11338
        beam_x = 222.0
        beam_y = 383.0

        detector = self._detector_factory.two_theta(
            'PAD', distance * 1000.0,
            (beam_x * pixel_x * 1000.0, beam_y * pixel_y * 1000.0), '+x', '-y',
            '+x', two_theta, (1000 * pixel_x, 1000 * pixel_y), (nx, ny),
            (underload, overload), [], None)

        import re
        m = re.search('^#\s*(\S+)\ssensor, thickness\s*([0-9.]+)\s*m\s*$', \
                      self._cif_header, re.MULTILINE)

        if m:
            # header gives thickness in metres, we store mm
            thickness = float(m.group(2)) * 1000
            material = m.group(1)

            if material == 'Silicon':
                material = 'Si'

            for panel in detector:
                panel.set_thickness(thickness)
                panel.set_material(material)

            try:
                # a header only CBF file will not have a beam object
                beam = self._beam()

            except Exception:
                pass

            if beam:
                # attenuation coefficient depends on the beam wavelength
                wavelength = beam.get_wavelength()

                from cctbx.eltbx import attenuation_coefficient
                from dxtbx.model import ParallaxCorrectedPxMmStrategy
                # this will fail for undefined composite materials
                table = attenuation_coefficient.get_table(material)
                # mu_at_angstrom returns cm^-1, but need mu in mm^-1
                mu = table.mu_at_angstrom(wavelength) / 10.0

                for panel in detector:
                    panel.set_mu(mu)
                    panel.set_px_mm_strategy(
                        ParallaxCorrectedPxMmStrategy(mu, thickness))

        return detector
Example #38
0
    def _detector(self, index=None):
        import psana
        from xfel.cftbx.detector.cspad_cbf_tbx import read_slac_metrology
        from dxtbx.model import Detector
        from scitbx.matrix import col
        from dxtbx.model import ParallaxCorrectedPxMmStrategy
        if index is None: index = 0
        self._env = self._ds.env()
        self._det = psana.Detector(self._src, self._env)
        geom = self._det.pyda.geoaccess(self.events_list[index])
        cob = read_slac_metrology(geometry=geom, include_asic_offset=True)
        d = Detector()
        pg0 = d.hierarchy()
        # first deal with D0
        det_num = 0
        origin = col((cob[(0, )] * col((0, 0, 0, 1)))[0:3])
        fast = col((cob[(0, )] * col((1, 0, 0, 1)))[0:3]) - origin
        slow = col((cob[(0, )] * col((0, 1, 0, 1)))[0:3]) - origin
        origin += col((0., 0., -100.))
        pg0.set_local_frame(fast.elems, slow.elems, origin.elems)
        pg0.set_name('D%d' % (det_num))
        for quad_num in xrange(4):
            # Now deal with Qx
            pg1 = pg0.add_group()
            origin = col((cob[(0, quad_num)] * col((0, 0, 0, 1)))[0:3])
            fast = col((cob[(0, quad_num)] * col((1, 0, 0, 1)))[0:3]) - origin
            slow = col((cob[(0, quad_num)] * col((0, 1, 0, 1)))[0:3]) - origin
            pg1.set_local_frame(fast.elems, slow.elems, origin.elems)
            pg1.set_name('D%dQ%d' % (det_num, quad_num))
            for sensor_num in xrange(8):
                # Now deal with Sy
                pg2 = pg1.add_group()
                origin = col((cob[(0, quad_num, sensor_num)] * col(
                    (0, 0, 0, 1)))[0:3])
                fast = col((cob[(0, quad_num, sensor_num)] * col(
                    (1, 0, 0, 1)))[0:3]) - origin
                slow = col((cob[(0, quad_num, sensor_num)] * col(
                    (0, 1, 0, 1)))[0:3]) - origin
                pg2.set_local_frame(fast.elems, slow.elems, origin.elems)
                pg2.set_name('D%dQ%dS%d' % (det_num, quad_num, sensor_num))
                # Now deal with Az
                for asic_num in xrange(2):
                    val = 'ARRAY_D0Q%dS%dA%d' % (quad_num, sensor_num,
                                                 asic_num)
                    p = pg2.add_panel()
                    origin = col(
                        (cob[(0, quad_num, sensor_num, asic_num)] * col(
                            (0, 0, 0, 1)))[0:3])
                    fast = col((cob[(0, quad_num, sensor_num, asic_num)] * col(
                        (1, 0, 0, 1)))[0:3]) - origin
                    slow = col((cob[(0, quad_num, sensor_num, asic_num)] * col(
                        (0, 1, 0, 1)))[0:3]) - origin
                    p.set_local_frame(fast.elems, slow.elems, origin.elems)
                    p.set_pixel_size(
                        (cspad_cbf_tbx.pixel_size, cspad_cbf_tbx.pixel_size))
                    p.set_image_size(cspad_cbf_tbx.asic_dimension)
                    p.set_trusted_range((cspad_tbx.cspad_min_trusted_value,
                                         cspad_tbx.cspad_saturated_value))
                    p.set_name(val)

        try:
            beam = self._beam(index)
        except Exception:
            print 'No beam object initialized. Returning CSPAD detector without parallax corrections'
            return d

        # take into consideration here the thickness of the sensor also the
        # wavelength of the radiation (which we have in the same file...)
        wavelength = beam.get_wavelength()
        thickness = 0.5  # mm, see Hart et al. 2012
        from cctbx.eltbx import attenuation_coefficient
        table = attenuation_coefficient.get_table("Si")
        # mu_at_angstrom returns cm^-1
        mu = table.mu_at_angstrom(wavelength) / 10.0  # mu: mm^-1
        t0 = thickness
        for panel in d:
            panel.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, t0))
        return d
Example #39
0
    def _detector(self, index=None):
        if index is None:
            index = 0

        run = self.get_run_from_index(index)
        det = self._get_psana_detector(run)
        geom = det.pyda.geoaccess(run.run())
        cob = read_slac_metrology(geometry=geom, include_asic_offset=True)
        distance = env_distance(
            self.params.detector_address[0], run.env(), self.params.cspad.detz_offset
        )
        d = Detector()
        pg0 = d.hierarchy()
        # first deal with D0
        det_num = 0
        origin = col((cob[(0,)] * col((0, 0, 0, 1)))[0:3])
        fast = col((cob[(0,)] * col((1, 0, 0, 1)))[0:3]) - origin
        slow = col((cob[(0,)] * col((0, 1, 0, 1)))[0:3]) - origin
        origin += col((0.0, 0.0, -distance))
        pg0.set_local_frame(fast.elems, slow.elems, origin.elems)
        pg0.set_name("D%d" % (det_num))
        for quad_num in range(4):
            # Now deal with Qx
            pg1 = pg0.add_group()
            origin = col((cob[(0, quad_num)] * col((0, 0, 0, 1)))[0:3])
            fast = col((cob[(0, quad_num)] * col((1, 0, 0, 1)))[0:3]) - origin
            slow = col((cob[(0, quad_num)] * col((0, 1, 0, 1)))[0:3]) - origin
            pg1.set_local_frame(fast.elems, slow.elems, origin.elems)
            pg1.set_name("D%dQ%d" % (det_num, quad_num))
            for sensor_num in range(8):
                # Now deal with Sy
                pg2 = pg1.add_group()
                origin = col((cob[(0, quad_num, sensor_num)] * col((0, 0, 0, 1)))[0:3])
                fast = (
                    col((cob[(0, quad_num, sensor_num)] * col((1, 0, 0, 1)))[0:3])
                    - origin
                )
                slow = (
                    col((cob[(0, quad_num, sensor_num)] * col((0, 1, 0, 1)))[0:3])
                    - origin
                )
                pg2.set_local_frame(fast.elems, slow.elems, origin.elems)
                pg2.set_name("D%dQ%dS%d" % (det_num, quad_num, sensor_num))
                # Now deal with Az
                for asic_num in range(2):
                    val = "ARRAY_D0Q%dS%dA%d" % (quad_num, sensor_num, asic_num)
                    p = pg2.add_panel()
                    origin = col(
                        (cob[(0, quad_num, sensor_num, asic_num)] * col((0, 0, 0, 1)))[
                            0:3
                        ]
                    )
                    fast = (
                        col(
                            (
                                cob[(0, quad_num, sensor_num, asic_num)]
                                * col((1, 0, 0, 1))
                            )[0:3]
                        )
                        - origin
                    )
                    slow = (
                        col(
                            (
                                cob[(0, quad_num, sensor_num, asic_num)]
                                * col((0, 1, 0, 1))
                            )[0:3]
                        )
                        - origin
                    )
                    p.set_local_frame(fast.elems, slow.elems, origin.elems)
                    p.set_pixel_size(
                        (cspad_cbf_tbx.pixel_size, cspad_cbf_tbx.pixel_size)
                    )
                    p.set_image_size(cspad_cbf_tbx.asic_dimension)
                    p.set_trusted_range(
                        (
                            cspad_tbx.cspad_min_trusted_value,
                            cspad_tbx.cspad_saturated_value,
                        )
                    )
                    p.set_name(val)

        try:
            beam = self._beam(index)
        except Exception:
            print(
                "No beam object initialized. Returning CSPAD detector without parallax corrections"
            )
            return d

        # take into consideration here the thickness of the sensor also the
        # wavelength of the radiation (which we have in the same file...)
        wavelength = beam.get_wavelength()
        thickness = 0.5  # mm, see Hart et al. 2012

        table = attenuation_coefficient.get_table("Si")
        # mu_at_angstrom returns cm^-1
        mu = table.mu_at_angstrom(wavelength) / 10.0  # mu: mm^-1
        t0 = thickness
        for panel in d:
            panel.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, t0))
        return d
def run_sim(seed=1,
            wavelength=0.9,
            distance=500,
            random_orientation=False,
            phi=0,
            osc=0):
    SIM = nanoBragg(detpixels_slowfast=(2527, 2463),
                    pixel_size_mm=0.172,
                    Ncells_abc=(15, 15, 15),
                    verbose=0)
    # get same noise each time this test is run
    SIM.seed = seed
    # user may select random orientation
    if random_orientation:
        SIM.randomize_orientation()
    else:
        # fixed orientation, for doing rotation data sets
        SIM.missets_deg = (10, 20, 30)
    SIM.distance_mm = distance
    SIM.wavelength_A = wavelength
    # option to render a phi swell
    SIM.phi_deg = phi
    SIM.osc_deg = osc
    if osc >= 0:
        # need quite a few steps/deg for decent Rmeas
        SIM.phistep_deg = 0.001
    SIM.oversample = 1
    SIM.polarization = 1
    # this will become F000, marking the beam center
    SIM.F000 = 100
    print "mosaic_seed=", SIM.mosaic_seed
    print "seed=", SIM.seed
    print "calib_seed=", SIM.calib_seed
    print "missets_deg =", SIM.missets_deg
    # re-set the detector to be in
    SIM.beamcenter_convention = convention.DIALS
    SIM.beam_center_mm = (211, 214)
    sfall = fcalc_from_pdb(resolution=1.6,
                           algorithm="direct",
                           wavelength=SIM.wavelength_A)
    # use crystal structure to initialize Fhkl array
    SIM.Fhkl = sfall
    # fastest option, least realistic
    SIM.xtal_shape = shapetype.Tophat
    # only really useful for long runs
    SIM.progress_meter = False
    # prints out value of one pixel only.  will not render full image!
    #SIM.printout_pixel_fastslow=(500,500)
    #SIM.printout=True
    # flux is always in photons/s
    SIM.flux = 1e12
    # assumes round beam
    SIM.beamsize_mm = 0.1
    SIM.exposure_s = 0.1
    # Pilatus detector is thick
    SIM.detector_thick_mm = 0.450
    # get attenuation depth in mm
    from cctbx.eltbx import attenuation_coefficient
    table = attenuation_coefficient.get_table("Si")
    SIM.detector_attenuation_length_mm = 10.0 / (table.mu_at_angstrom(
        SIM.wavelength_A))
    print "detector_attenuation_length =", SIM.detector_attenuation_length_mm
    #SIM.detector_thick_mm=0
    SIM.detector_thicksteps = 3
    #
    # will simulate module mis-alignment by adjusting beam center of each module
    beam_center0 = SIM.beam_center_mm
    # simulated crystal is only 3375 unit cells (42 nm wide)
    # amplify spot signal to simulate physical crystal of 100 um
    # this is equivalent to adding up 28e9 mosaic domains in exactly the same orientation, but a lot faster
    aggregate_xtal_volume_mm3 = 0.1 * 0.1 * 0.1
    mosaic_domain_volume_mm3 = SIM.xtal_size_mm[0] * SIM.xtal_size_mm[
        1] * SIM.xtal_size_mm[2]
    SIM.spot_scale = aggregate_xtal_volume_mm3 / mosaic_domain_volume_mm3
    #
    # option for detector rotations to be about beam center or sample position
    #SIM.detector_pivot=pivot.Sample
    SIM.detector_pivot = pivot.Beam
    print "pivoting detector about", SIM.detector_pivot
    # make the module roi list
    # and also make up per-module mis-alignments shifts and rotations
    import random
    # make sure shifts are the same from image to image
    random.seed(12345)
    module_size = (487, 195)
    gap_size = (7, 17)
    modules = []
    for mx in range(0, 5):
        for my in range(0, 12):
            # define region of interest for this module
            fmin = mx * (module_size[0] + gap_size[0])
            fmax = fmin + module_size[0]
            smin = my * (module_size[1] + gap_size[1])
            smax = smin + module_size[1]
            # assume misalignments are uniform
            # up to ~0.5 pixel and 0.0 deg in each direction
            dx = 0.07 * (random.random() - 0.5) * 2
            dy = 0.07 * (random.random() - 0.5) * 2
            rotx = 0.0 * (random.random() - 0.5) * 2
            roty = 0.0 * (random.random() - 0.5) * 2
            rotz = 0.0 * (random.random() - 0.5) * 2
            modules.append(
                (((fmin, fmax), (smin, smax)), (dx, dy), (rotx, roty, rotz)))
    #
    # defeat module-by-module rendering by uncommenting next 3 lines
    #dim=SIM.detpixels_fastslow
    #modules = [(( ((0,dim[0]),(0,dim[1])) ),(0,0),(0,0,0))]
    #print modules
    i = -1
    for roi, (dx, dy), drot in modules:
        i = i + 1
        print "rendering module:", i, "roi=", roi
        SIM.region_of_interest = roi
        # shift the beam center
        x = beam_center0[0] + dx
        y = beam_center0[1] + dy
        SIM.beam_center_mm = (x, y)
        # also tilt the module by up to 0.05 deg in all directions
        SIM.detector_rotation_deg = drot
        print "beam center: ", SIM.beam_center_mm, "rotations:", drot
        # now actually burn up some CPU
        SIM.add_nanoBragg_spots()
        # add water contribution
        SIM.Fbg_vs_stol = Fbg_water
        SIM.amorphous_sample_thick_mm = 0.1
        SIM.amorphous_density_gcm3 = 1
        SIM.amorphous_molecular_weight_Da = 18
        SIM.add_background()
        # add air contribution
        SIM.Fbg_vs_stol = Fbg_air
        SIM.amorphous_sample_thick_mm = 35  # between beamstop and collimator
        SIM.amorphous_density_gcm3 = 1.2e-3
        SIM.amorphous_sample_molecular_weight_Da = 28  # nitrogen = N2
        SIM.add_background()
        # add nanocrystalline cubic ice contribution (unscaled)
        SIM.Fbg_vs_stol = Fbg_nanoice
        SIM.amorphous_sample_thick_mm = 0.05  # between beamstop and collimator
        SIM.amorphous_density_gcm3 = 0.95
        SIM.amorphous_sample_molecular_weight_Da = 18  # H2O
        SIM.add_background()
    #
    # set this to 0 or -1 to trigger automatic radius.  could be very slow with bright images
    SIM.detector_psf_kernel_radius_pixels = 5
    # turn off the point spread function for Pilatus
    SIM.detector_psf_fwhm_mm = 0.0
    SIM.detector_psf_type = shapetype.Gauss
    SIM.adc_offset_adu = 0
    SIM.readout_noise_adu = 0
    dim = SIM.detpixels_fastslow
    SIM.region_of_interest = ((0, dim[0]), (0, dim[1]))
    SIM.add_noise()
    return SIM
Example #41
0
  def __init__(self, obj, beam):
    from dxtbx.model import Detector, Panel
    from cctbx.eltbx import attenuation_coefficient
    from dxtbx.model import ParallaxCorrectedPxMmStrategy
    from scitbx import matrix

    # Get the handles
    nx_file = obj.handle.file
    nx_detector = obj.handle
    nx_module = obj.modules[0].handle

    # Get the detector name and type
    detector_type = str(nx_detector['type'][()])
    detector_name = str(nx_detector.name)

    # Get the trusted range of pixel values
    trusted_range = (-1, float(nx_detector['saturation_value'][()]))

    # Get the detector thickness
    thickness = nx_detector['sensor_thickness']
    thickness_value = float(thickness[()])
    thickness_units = thickness.attrs['units']
    thickness_value = float(convert_units(
      thickness_value,
      thickness_units,
      "mm"))

    # Get the detector material
    material = str(nx_detector['sensor_material'][()])

    # Get the fast pixel size and vector
    fast_pixel_direction = nx_module['fast_pixel_direction']
    fast_pixel_direction_value = float(fast_pixel_direction[()])
    fast_pixel_direction_units = fast_pixel_direction.attrs['units']
    fast_pixel_direction_vector = fast_pixel_direction.attrs['vector']
    fast_pixel_direction_value = convert_units(
      fast_pixel_direction_value,
      fast_pixel_direction_units,
      "mm")
    fast_axis = matrix.col(fast_pixel_direction_vector).normalize()

    # Get the slow pixel size and vector
    slow_pixel_direction = nx_module['slow_pixel_direction']
    slow_pixel_direction_value = float(slow_pixel_direction[()])
    slow_pixel_direction_units = slow_pixel_direction.attrs['units']
    slow_pixel_direction_vector = slow_pixel_direction.attrs['vector']
    slow_pixel_direction_value = convert_units(
      slow_pixel_direction_value,
      slow_pixel_direction_units,
      "mm")
    slow_axis = matrix.col(slow_pixel_direction_vector).normalize()

    # Get the origin vector
    module_offset = nx_module['module_offset']
    origin = construct_vector(
      nx_file,
      module_offset.name)

    # Ensure that fast and slow axis are orthogonal
    normal = fast_axis.cross(slow_axis)
    slow_axis = -fast_axis.cross(normal)

    # Compute the attenuation coefficient.
    # This will fail for undefined composite materials
    # mu_at_angstrom returns cm^-1, but need mu in mm^-1
    if material == 'Si':
      pass
    elif material == 'Silicon':
      material = 'Si'
    elif material == 'Sillicon':
      material = 'Si'
    elif material == 'CdTe':
      pass
    elif material == 'GaAs':
      pass
    else:
      raise RuntimeError('Unknown material: %s' % material)
    table = attenuation_coefficient.get_table(material)
    wavelength = beam.get_wavelength()
    mu = table.mu_at_angstrom(wavelength) / 10.0

    # Construct the detector model
    pixel_size = (fast_pixel_direction_value, slow_pixel_direction_value)
    image_size = tuple(map(int, nx_module['data_size']))

    self.model = Detector()
    self.model.add_panel(
      Panel(
        detector_type,
        detector_name,
        tuple(fast_axis),
        tuple(slow_axis),
        tuple(origin),
        pixel_size,
        image_size,
        trusted_range,
        thickness_value,
        material,
        mu))

    # Set the parallax correction
    for panel in self.model:
      panel.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, thickness_value))
      panel.set_type('SENSOR_PAD')
Example #42
0
  def XDS_INP(self, out=None,
              space_group_number=None,
              real_space_a=None, real_space_b=None, real_space_c=None,
              job_card="XYCORR INIT COLSPOT IDXREF DEFPIX INTEGRATE CORRECT"):
    if out is None:
      out = sys.stdout

    assert [real_space_a, real_space_b, real_space_c].count(None) in (0,3)

    sensor = self.get_detector()[0].get_type()
    fast, slow = self.detector_size
    f, s = self.pixel_size
    df = int(1000 * f)
    ds = int(1000 * s)

    # FIXME probably need to rotate by pi about the X axis

    detector = xds_detector_name(
        detector_helpers_types.get(sensor, fast, slow, df, ds))
    trusted = self.get_detector()[0].get_trusted_range()

    print >> out, 'DETECTOR=%s MINIMUM_VALID_PIXEL_VALUE=%d OVERLOAD=%d' % \
          (detector, trusted[0] + 1, trusted[1])

    if detector == 'PILATUS':
      print >> out, 'SENSOR_THICKNESS= %.3f' % \
        self.get_detector()[0].get_thickness()
      if self.get_detector()[0].get_material():
        from cctbx.eltbx import attenuation_coefficient
        material = self.get_detector()[0].get_material()
        table = attenuation_coefficient.get_table(material)
        mu = table.mu_at_angstrom(self.wavelength) / 10.0
        print >> out, '!SENSOR_MATERIAL / THICKNESS %s %.3f' % \
          (material, self.get_detector()[0].get_thickness())
        print >> out, '!SILICON= %f' % mu

    print >> out, 'DIRECTION_OF_DETECTOR_X-AXIS= %.3f %.3f %.3f' % \
          self.detector_x_axis

    print >> out, 'DIRECTION_OF_DETECTOR_Y-AXIS= %.3f %.3f %.3f' % \
          self.detector_y_axis

    print >> out, 'NX=%d NY=%d QX=%.4f QY=%.4f' % (fast, slow, f, s)

    print >> out, 'DETECTOR_DISTANCE= %.3f' % self.detector_distance
    print >> out, 'ORGX= %.1f ORGY= %.1f' % self.detector_origin
    print >> out, 'ROTATION_AXIS= %.3f %.3f %.3f' % \
          self.rotation_axis
    print >> out, 'STARTING_ANGLE= %.3f' % \
          self.starting_angle
    print >> out, 'OSCILLATION_RANGE= %.3f' % \
          self.oscillation_range
    print >> out, 'X-RAY_WAVELENGTH= %.5f' % \
          self.wavelength
    print >> out, 'INCIDENT_BEAM_DIRECTION= %.3f %.3f %.3f' % \
          self.beam_vector

    # FIXME LATER
    if hasattr(self.get_beam(), "get_polarization_fraction"):
      print >> out, 'FRACTION_OF_POLARIZATION= %.3f' % \
          self.get_beam().get_polarization_fraction()
      print >> out, 'POLARIZATION_PLANE_NORMAL= %.3f %.3f %.3f' % \
          self.get_beam().get_polarization_normal()
    print >> out, 'NAME_TEMPLATE_OF_DATA_FRAMES= %s' % \
        self.get_template().replace('#', '?')
    print >> out, 'TRUSTED_REGION= 0.0 1.41'
    for f0, s0, f1, s1 in self.get_detector()[0].get_mask():
      print >> out, 'UNTRUSTED_RECTANGLE= %d %d %d %d' % \
            (f0 - 1, f1 + 1, s0 - 1, s1 + 1)

    start_end = self.get_scan().get_image_range()

    if start_end[0] == 0:
      start_end = (1, start_end[1])

    print >> out, 'DATA_RANGE= %d %d' % start_end
    print >> out, 'JOB=%s' %job_card
    if space_group_number is not None:
      print >> out, 'SPACE_GROUP_NUMBER= %i' %space_group_number
    if [real_space_a, real_space_b, real_space_c].count(None) == 0:
      R = self.imagecif_to_xds_transformation_matrix
      unit_cell_a_axis = R * matrix.col(real_space_a)
      unit_cell_b_axis = R * matrix.col(real_space_b)
      unit_cell_c_axis = R * matrix.col(real_space_c)
      print >> out, "UNIT_CELL_A-AXIS= %.6f %.6f %.6f" %unit_cell_a_axis.elems
      print >> out, "UNIT_CELL_B-AXIS= %.6f %.6f %.6f" %unit_cell_b_axis.elems
      print >> out, "UNIT_CELL_C-AXIS= %.6f %.6f %.6f" %unit_cell_c_axis.elems
    def _detector(self):
        distance = float(
            self._cif_header_dictionary['Detector_distance'].split()[0])

        beam_xy = self._cif_header_dictionary['Beam_xy'].replace(
            '(', '').replace(')', '').replace(',', '').split()[:2]

        wavelength = float(
            self._cif_header_dictionary['Wavelength'].split()[0])

        beam_x, beam_y = map(float, beam_xy)

        pixel_xy = self._cif_header_dictionary['Pixel_size'].replace(
            'm', '').replace('x', '').split()

        pixel_x, pixel_y = map(float, pixel_xy)

        # extract sensor thickness, assume < 10mm; default to 450 microns unfound
        try:
            thickness = float(
                self._cif_header_dictionary['Silicon'].split()[-2]) * 1000.0
            material = 'Si'
            if thickness > 10:
                thickness = thickness / 1000.0
        except KeyError:
            thickness = 0.450
            material = 'Si'

        nx = int(
            self._cif_header_dictionary['X-Binary-Size-Fastest-Dimension'])
        ny = int(self._cif_header_dictionary['X-Binary-Size-Second-Dimension'])

        if 'Count_cutoff' in self._cif_header_dictionary:
            overload = int(
                self._cif_header_dictionary['Count_cutoff'].split()[0])
        else:
            # missing from data transformed with GPhL converter - dials#376
            overload = 100000000
        underload = -1

        try:
            identifier = self._cif_header_dictionary['Detector']
        except KeyError:
            identifier = 'Unknown Eiger'

        from cctbx.eltbx import attenuation_coefficient
        table = attenuation_coefficient.get_table("Si")
        mu = table.mu_at_angstrom(wavelength) / 10.0
        t0 = thickness

        detector = self._detector_factory.simple(
            'PAD', distance * 1000.0,
            (beam_x * pixel_x * 1000.0, beam_y * pixel_y * 1000.0), '+x', '-y',
            (1000 * pixel_x, 1000 * pixel_y), (nx, ny), (underload, overload),
            [], ParallaxCorrectedPxMmStrategy(mu, t0))

        for f0, f1, s0, s1 in determine_eiger_mask(detector):
            detector[0].add_mask(f0 - 1, s0 - 1, f1, s1)

        for panel in detector:
            panel.set_thickness(thickness)
            panel.set_material(material)
            panel.set_identifier(identifier)
            panel.set_mu(mu)

        return detector
    def _detector(self):
        """Detector model, allowing for small offsets in the positions of 60
    detector modules"""

        # Module positional offsets in x, y, in pixels - for the moment ignoring the
        # rotational offsets as these are not well defined. To be honest these
        # positional offsets are also not well defined as I do not know how they
        # should be applied...

        x = {
            (0, 0): -0.477546,
            (0, 1): 0.130578,
            (0, 2): 0.045041,
            (0, 3): -0.439872,
            (0, 4): -0.382077,
            (1, 0): 0.087405,
            (1, 1): 0.249597,
            (1, 2): 0.184265,
            (1, 3): 0.158342,
            (1, 4): 0.025225,
            (2, 0): -0.179892,
            (2, 1): -0.010974,
            (2, 2): -0.139207,
            (2, 3): 0.282851,
            (2, 4): -0.442219,
            (3, 0): -0.185027,
            (3, 1): 0.218601,
            (3, 2): 0.092585,
            (3, 3): 0.35862,
            (3, 4): -0.29161,
            (4, 0): 0.145368,
            (4, 1): 0.609289,
            (4, 2): 0.396265,
            (4, 3): 0.41625,
            (4, 4): 0.07152,
            (5, 0): 0.247142,
            (5, 1): 0.046563,
            (5, 2): 0.248714,
            (5, 3): -0.044628,
            (5, 4): -0.391509,
            (6, 0): 0.516643,
            (6, 1): 0.358453,
            (6, 2): 0.069219,
            (6, 3): 0.095861,
            (6, 4): -0.167403,
            (7, 0): -0.381352,
            (7, 1): -0.35338,
            (7, 2): 0.348656,
            (7, 3): 0.024543,
            (7, 4): 0.328706,
            (8, 0): 0.150886,
            (8, 1): 0.244987,
            (8, 2): -0.102911,
            (8, 3): 0.16633,
            (8, 4): 0.386622,
            (9, 0): 0.037924,
            (9, 1): 0.314392,
            (9, 2): 0.238818,
            (9, 3): 0.815028,
            (9, 4): -0.048818,
            (10, 0): -0.670524,
            (10, 1): -0.304119,
            (10, 2): 0.252284,
            (10, 3): -0.05485,
            (10, 4): -0.355264,
            (11, 0): -0.404947,
            (11, 1): -0.020622,
            (11, 2): 0.648473,
            (11, 3): -0.277175,
            (11, 4): -0.711951,
        }

        y = {
            (0, 0): -0.494797,
            (0, 1): -0.212976,
            (0, 2): 0.085351,
            (0, 3): 0.35494,
            (0, 4): 0.571189,
            (1, 0): -0.421708,
            (1, 1): 0.061914,
            (1, 2): 0.238996,
            (1, 3): 0.146692,
            (1, 4): 0.407145,
            (2, 0): -0.313212,
            (2, 1): -0.225025,
            (2, 2): 0.031613,
            (2, 3): -0.047839,
            (2, 4): 0.42716,
            (3, 0): -0.361193,
            (3, 1): 0.057663,
            (3, 2): 0.022357,
            (3, 3): 0.062717,
            (3, 4): 0.150611,
            (4, 0): 0.035511,
            (4, 1): -0.271567,
            (4, 2): 0.007761,
            (4, 3): -0.124021,
            (4, 4): 0.093017,
            (5, 0): -0.238897,
            (5, 1): -0.179724,
            (5, 2): -0.113608,
            (5, 3): 0.017841,
            (5, 4): -0.012933,
            (6, 0): -0.166337,
            (6, 1): -0.272922,
            (6, 2): -0.194665,
            (6, 3): -0.058535,
            (6, 4): -0.405404,
            (7, 0): -0.318824,
            (7, 1): -0.311276,
            (7, 2): -0.205223,
            (7, 3): -0.292664,
            (7, 4): -0.474762,
            (8, 0): -0.039504,
            (8, 1): -0.239887,
            (8, 2): -0.343485,
            (8, 3): -0.459429,
            (8, 4): -0.426901,
            (9, 0): -0.187805,
            (9, 1): 0.282727,
            (9, 2): -0.601164,
            (9, 3): -0.467605,
            (9, 4): -0.589271,
            (10, 0): 0.028311,
            (10, 1): -0.391571,
            (10, 2): -0.463112,
            (10, 3): -0.358092,
            (10, 4): -0.285396,
            (11, 0): 0.01863,
            (11, 1): -0.380099,
            (11, 2): -0.234953,
            (11, 3): -0.593992,
            (11, 4): -0.801247,
        }

        distance = float(self._cif_header_dictionary["Detector_distance"].split()[0])

        beam_xy = self._cif_header_dictionary["Beam_xy"].replace("(", "").replace(")", "").replace(",", "").split()[:2]

        beam_x, beam_y = map(float, beam_xy)

        wavelength = float(self._cif_header_dictionary["Wavelength"].split()[0])

        pixel_xy = self._cif_header_dictionary["Pixel_size"].replace("m", "").replace("x", "").split()

        pixel_x, pixel_y = map(float, pixel_xy)

        thickness = float(self._cif_header_dictionary["Silicon"].split()[2]) * 1000.0

        nx = int(self._cif_header_dictionary["X-Binary-Size-Fastest-Dimension"])
        ny = int(self._cif_header_dictionary["X-Binary-Size-Second-Dimension"])

        overload = int(self._cif_header_dictionary["Count_cutoff"].split()[0])
        underload = -1

        # take into consideration here the thickness of the sensor also the
        # wavelength of the radiation (which we have in the same file...)

        from cctbx.eltbx import attenuation_coefficient

        table = attenuation_coefficient.get_table("Si")
        mu = table.mu_at_angstrom(wavelength) / 10.0
        t0 = thickness

        # FIXME would also be very nice to be able to take into account the
        # misalignment of the individual modules given the calibration...

        # single detector or multi-module detector

        pixel_x *= 1000.0
        pixel_y *= 1000.0
        distance *= 1000.0

        if single_panel:
            detector = self._detector_factory.simple(
                "PAD",
                distance,
                (beam_x * pixel_x, beam_y * pixel_y),
                "+x",
                "-y",
                (pixel_x, pixel_y),
                (nx, ny),
                (underload, overload),
                [],
                ParallaxCorrectedPxMmStrategy(mu, t0),
            )

            for f0, s0, f1, s1 in determine_pilatus_mask(detector):
                detector[0].add_mask(f0, s0, f1, s1)

            detector[0].set_thickness(thickness)
            detector[0].set_material("Si")
            detector[0].set_mu(table.mu_at_angstrom(wavelength))

            return detector

        # got to here means 60-panel version

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

        d = HierarchicalDetector()

        beam_centre = matrix.col((beam_x * pixel_x, beam_y * pixel_y, 0))

        fast = matrix.col((1.0, 0.0, 0.0))
        slow = matrix.col((0.0, -1.0, 0.0))
        s0 = matrix.col((0, 0, -1))
        origin = (distance * s0) - (fast * beam_centre[0]) - (slow * beam_centre[1])

        root = d.hierarchy()
        root.set_local_frame(fast.elems, slow.elems, origin.elems)

        xmins = [0, 494, 988, 1482, 1976]
        xmaxes = [487, 981, 1475, 1969, 2463]
        ymins = [0, 212, 424, 636, 848, 1060, 1272, 1484, 1696, 1908, 2120, 2332]
        ymaxes = [195, 407, 619, 831, 1043, 1255, 1467, 1679, 1891, 2103, 2315, 2527]

        self.coords = {}

        fast = matrix.col((1.0, 0.0, 0.0))
        slow = matrix.col((0.0, 1.0, 0.0))
        panel_idx = 0
        for ymin, ymax in zip(ymins, ymaxes):
            for xmin, xmax in zip(xmins, xmaxes):
                xmin_mm = xmin * pixel_x
                ymin_mm = ymin * pixel_y

                origin_panel = fast * xmin_mm + slow * ymin_mm

                panel_name = "Panel%d" % panel_idx
                panel_idx += 1

                p = d.add_panel()
                p.set_name(panel_name)
                p.set_image_size((xmax - xmin, ymax - ymin))
                p.set_trusted_range((underload, overload))
                p.set_pixel_size((pixel_x, pixel_y))
                p.set_thickness(thickness)
                p.set_material("Si")
                p.set_local_frame(fast.elems, slow.elems, origin_panel.elems)
                self.coords[panel_name] = (xmin, ymin, xmax, ymax)

                root.add_panel(p)

        return d
Example #45
0
    def _detector(self):
        distance = float(self._cif_header_dictionary["Detector_distance"].split()[0])

        beam_xy = (
            self._cif_header_dictionary["Beam_xy"]
            .replace("(", "")
            .replace(")", "")
            .replace(",", "")
            .split()[:2]
        )

        wavelength = float(self._cif_header_dictionary["Wavelength"].split()[0])

        beam_x, beam_y = map(float, beam_xy)

        pixel_xy = (
            self._cif_header_dictionary["Pixel_size"]
            .replace("m", "")
            .replace("x", "")
            .split()
        )

        pixel_x, pixel_y = map(float, pixel_xy)

        if "Silicon" in self._cif_header_dictionary:
            thickness = (
                float(self._cif_header_dictionary["Silicon"].split()[2]) * 1000.0
            )
            material = "Si"
        elif "CdTe" in self._cif_header_dictionary:
            thickness = float(self._cif_header_dictionary["CdTe"].split()[2]) * 1000.0
            material = "CdTe"
        else:
            thickness = 0.450
            material = "Si"

        nx = int(self._cif_header_dictionary["X-Binary-Size-Fastest-Dimension"])
        ny = int(self._cif_header_dictionary["X-Binary-Size-Second-Dimension"])

        if "Count_cutoff" in self._cif_header_dictionary:
            overload = int(self._cif_header_dictionary["Count_cutoff"].split()[0])
        else:
            # missing from data transformed with GPhL converter - dials#376
            overload = 100000000
        underload = -1

        try:
            identifier = self._cif_header_dictionary["Detector"]
        except KeyError:
            identifier = "Unknown Eiger"

        from cctbx.eltbx import attenuation_coefficient

        table = attenuation_coefficient.get_table(material)
        mu = table.mu_at_angstrom(wavelength) / 10.0
        t0 = thickness

        detector = self._detector_factory.simple(
            "PAD",
            distance * 1000.0,
            (beam_x * pixel_x * 1000.0, beam_y * pixel_y * 1000.0),
            "+x",
            "-y",
            (1000 * pixel_x, 1000 * pixel_y),
            (nx, ny),
            (underload, overload),
            [],
            px_mm=ParallaxCorrectedPxMmStrategy(mu, t0),
            mu=mu,
        )

        for f0, f1, s0, s1 in determine_eiger_mask(detector):
            detector[0].add_mask(f0 - 1, s0 - 1, f1, s1)

        for panel in detector:
            panel.set_thickness(thickness)
            panel.set_material(material)
            panel.set_identifier(identifier)
            panel.set_mu(mu)

        return detector
    def _detector(self):
        """Return a working detector instance, with added mask regions."""

        cif_header = FormatCBFFullPilatus.get_cbf_header(self._image_file)

        self._cif_header_dictionary = {}

        for record in cif_header.split("\n"):
            if not "#" in record[:1]:
                continue

            if len(record[1:].split()) <= 2 and record.count(":") == 2:
                self._cif_header_dictionary["timestamp"] = record[1:].strip()
                continue

            tokens = record.replace("=", "").replace(":", "").split()[1:]

            self._cif_header_dictionary[tokens[0]] = " ".join(tokens[1:])

        for record in self._mime_header.split("\n"):
            if not record.strip():
                continue
            token, value = record.split(":")
            self._cif_header_dictionary[token.strip()] = value.strip()

        distance = float(self._cif_header_dictionary["Detector_distance"].split()[0])

        beam_xy = self._cif_header_dictionary["Beam_xy"].replace("(", "").replace(")", "").replace(",", "").split()[:2]

        wavelength = float(self._cif_header_dictionary["Wavelength"].split()[0])

        beam_x, beam_y = map(float, beam_xy)

        pixel_xy = self._cif_header_dictionary["Pixel_size"].replace("m", "").replace("x", "").split()

        pixel_x, pixel_y = map(float, pixel_xy)

        nx = int(self._cif_header_dictionary["X-Binary-Size-Fastest-Dimension"])
        ny = int(self._cif_header_dictionary["X-Binary-Size-Second-Dimension"])

        overload = int(self._cif_header_dictionary["Count_cutoff"].split()[0])
        underload = -1

        two_theta = float(self._cif_header_dictionary["Detector_2theta"].split()[0])

        # hard code "correct" values for these
        distance = 0.11338
        beam_x = 222.0
        beam_y = 383.0

        detector = self._detector_factory.two_theta(
            "PAD",
            distance * 1000.0,
            (beam_x * pixel_x * 1000.0, beam_y * pixel_y * 1000.0),
            "+x",
            "-y",
            "+x",
            two_theta,
            (1000 * pixel_x, 1000 * pixel_y),
            (nx, ny),
            (underload, overload),
            [],
            None,
        )

        import re

        m = re.search("^#\s*(\S+)\ssensor, thickness\s*([0-9.]+)\s*m\s*$", self._cif_header, re.MULTILINE)

        if m:
            # header gives thickness in metres, we store mm
            thickness = float(m.group(2)) * 1000
            material = m.group(1)

            if material == "Silicon":
                material = "Si"

            for panel in detector:
                panel.set_thickness(thickness)
                panel.set_material(material)

            try:
                # a header only CBF file will not have a beam object
                beam = self._beam()

            except Exception:
                pass

            if beam:
                # attenuation coefficient depends on the beam wavelength
                wavelength = beam.get_wavelength()

                from cctbx.eltbx import attenuation_coefficient
                from dxtbx.model import ParallaxCorrectedPxMmStrategy

                # this will fail for undefined composite materials (ie all except CdTe)
                table = attenuation_coefficient.get_table(material)
                # mu_at_angstrom returns cm^-1, but need mu in mm^-1
                mu = table.mu_at_angstrom(wavelength) / 10.0

                for panel in detector:
                    panel.set_mu(table.mu_at_angstrom(wavelength))
                    panel.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, thickness))

        return detector