Beispiel #1
0
    def _detector(self):
        '''Return a working detector instance.'''
        if self._panel_origin is not None:
            from dxtbx.model import Detector
            detector = Detector()
            root = detector.hierarchy()
            root.set_frame(self._fast_axis, self._slow_axis,
                           self._detector_origin)

            i_panel = 0
            for p_offset, p_size, origin, fast, slow in zip(
                    self._panel_offset, self._panel_size, self._panel_origin,
                    self._panel_fast, self._panel_slow):
                # ensure mutual orthogonality in presence of numerical rounding errors
                normal = fast.cross(slow)
                slow = normal.cross(fast)
                p = root.add_panel()
                p.set_type('unknown')
                p.set_raw_image_offset(p_offset)
                p.set_image_size(p_size)
                p.set_name('Panel%d' % i_panel)
                p.set_pixel_size(self._pixel_size)
                p.set_frame(fast.elems, slow.elems, origin.elems)
                i_panel += 1
            return detector

        return self._detector_factory.complex(
            self._detector_factory.sensor('unknown'), self._detector_origin,
            self._fast_axis, self._slow_axis, self._pixel_size,
            self._image_size, (0, 1.e9))
Beispiel #2
0
  def _detector(self):
    '''Return a working detector instance.'''
    if self._panel_origin is not None:
      from dxtbx.model import Detector
      detector = Detector()
      root = detector.hierarchy()
      root.set_frame(self._fast_axis, self._slow_axis, self._detector_origin)

      i_panel = 0
      for p_offset, p_size, origin, fast, slow in zip(
          self._panel_offset, self._panel_size, self._panel_origin,
          self._panel_fast, self._panel_slow):
        # ensure mutual orthogonality in presence of numerical rounding errors
        normal = fast.cross(slow)
        slow = normal.cross(fast)
        p = root.add_panel()
        p.set_type('unknown')
        p.set_raw_image_offset(p_offset)
        p.set_image_size(p_size)
        p.set_name('Panel%d' %i_panel)
        p.set_pixel_size(self._pixel_size)
        p.set_frame(fast.elems, slow.elems, origin.elems)
        i_panel += 1
      return detector

    return self._detector_factory.complex(
        self._detector_factory.sensor('unknown'), self._detector_origin,
        self._fast_axis, self._slow_axis, self._pixel_size,
        self._image_size, (0, 1.e9))
Beispiel #3
0
  def _detector(self, index=None):
    from dxtbx.model import Detector
    if index is None: index = 0
    d = Detector()
    root = d.hierarchy()

    all_addresses = self._src

    def recursive_add_node(a, b):
      # add a to b
      if a.is_panel():
        b.add_panel(a)
      else:
        g = b.add_group(a)
        for child in a:
          recursive_add_node(child, g)

    for address in all_addresses:
      self._src = [address]
      sub_d = None
      try:
        if 'rayonix' in address.lower():
          sub_d = FormatXTCRayonix._detector(self)
        elif 'cspad' in address.lower():
          sub_d = FormatXTCCspad._detector(self, index)
        elif 'jungfrau' in address.lower():
          sub_d = FormatXTCJungfrau._detector(self, index)
      except Exception:
        continue
      assert sub_d is not None, address
      recursive_add_node(sub_d.hierarchy(), root)
    self._src = all_addresses

    return d
def detector():
    detector = Detector()
    root = detector.hierarchy()
    root.set_name("D1")
    root.set_type("D")

    quad1 = root.add_group()
    quad1.set_name("Q1")
    quad1.set_type("Q")
    panel1 = quad1.add_panel()
    panel1.set_name("P1")
    panel1.set_type("P")
    panel2 = quad1.add_panel()
    panel2.set_name("P2")
    panel2.set_type("P")

    quad2 = root.add_group()
    quad2.set_name("Q2")
    quad2.set_type("Q")
    panel3 = quad2.add_panel()
    panel3.set_name("P3")
    panel3.set_type("P")
    panel4 = quad2.add_panel()
    panel4.set_name("P4")
    panel4.set_type("P")

    return detector
  def __init__(self):
    detector = Detector()
    root = detector.hierarchy()
    root.set_name("D1")
    root.set_type("D")

    quad1 = root.add_group()
    quad1.set_name("Q1")
    quad1.set_type("Q")
    panel1 = quad1.add_panel()
    panel1.set_name("P1")
    panel1.set_type("P")
    panel2 = quad1.add_panel()
    panel2.set_name("P2")
    panel2.set_type("P")

    quad2 = root.add_group()
    quad2.set_name("Q2")
    quad2.set_type("Q")
    panel3 = quad2.add_panel()
    panel3.set_name("P3")
    panel3.set_type("P")
    panel4 = quad2.add_panel()
    panel4.set_name("P4")
    panel4.set_type("P")


    self.detector = detector
Beispiel #6
0
    def _detector(self, index=None):
        if index is None:
            index = 0
        d = Detector()
        root = d.hierarchy()

        all_addresses = self.params.detector_address

        def recursive_add_node(a, b):
            # add a to b
            if a.is_panel():
                b.add_panel(a)
            else:
                g = b.add_group(a)
                for child in a:
                    recursive_add_node(child, g)

        for address in all_addresses:
            self.params.detector_address = [address]
            sub_d = None
            try:
                if "rayonix" in address.lower():
                    sub_d = FormatXTCRayonix._detector(self)
                elif "cspad" in address.lower():
                    sub_d = FormatXTCCspad._detector(self, index)
                elif "jungfrau" in address.lower():
                    sub_d = FormatXTCJungfrau._detector(self, index)
            except Exception:
                continue
            assert sub_d is not None, address
            recursive_add_node(sub_d.hierarchy(), root)
        self.params.detector_address = all_addresses

        return d
Beispiel #7
0
    def __call__(self):

        from dxtbx.model import Detector, Panel  # import dependency

        d1 = Detector()
        p = d1.add_panel()
        p.set_name("p1")
        p.set_type("panel")
        p.set_pixel_size((0.1, 0.1))
        p.set_image_size((100, 100))
        p.set_trusted_range((0, 1000))
        p.set_local_frame((1, 0, 0), (0, 1, 0), (0, 0, 1))

        p = d1.add_panel()
        p.set_name("p2")
        p.set_type("panel")
        p.set_pixel_size((0.2, 0.2))
        p.set_image_size((200, 200))
        p.set_trusted_range((0, 2000))
        p.set_local_frame((0, 1, 0), (1, 0, 0), (0, 0, 1))

        root = d1.hierarchy()
        g = root.add_group()
        g.set_name("g1")
        g.set_type("group")
        g.set_local_frame((0, 1, 0), (1, 0, 0), (0, 0, 2))
        g.add_panel(d1[0])

        g = root.add_group()
        g.set_name("g2")
        g.set_type("group")
        g.set_local_frame((0, 1, 0), (1, 0, 0), (0, 0, 4))
        g.add_panel(d1[1])

        d = d1.to_dict()
        d2 = Detector.from_dict(d)
        assert (len(d1) == len(d2))
        for p1, p2 in zip(d1, d2):
            assert (p1 == p2)
        assert (d1.hierarchy() == d2.hierarchy())
        assert (d1 == d2)

        print 'OK'
  def __call__(self):

    from dxtbx.model import Detector, Panel # import dependency

    d1 = Detector()
    p = d1.add_panel()
    p.set_name("p1")
    p.set_type("panel")
    p.set_pixel_size((0.1, 0.1))
    p.set_image_size((100, 100))
    p.set_trusted_range((0, 1000))
    p.set_local_frame((1, 0, 0), (0, 1, 0), (0, 0, 1))

    p = d1.add_panel()
    p.set_name("p2")
    p.set_type("panel")
    p.set_pixel_size((0.2, 0.2))
    p.set_image_size((200, 200))
    p.set_trusted_range((0, 2000))
    p.set_local_frame((0, 1, 0), (1, 0, 0), (0, 0, 1))

    root = d1.hierarchy()
    g = root.add_group()
    g.set_name("g1")
    g.set_type("group")
    g.set_local_frame((0, 1, 0), (1, 0, 0), (0, 0, 2))
    g.add_panel(d1[0])

    g = root.add_group()
    g.set_name("g2")
    g.set_type("group")
    g.set_local_frame((0, 1, 0), (1, 0, 0), (0, 0, 4))
    g.add_panel(d1[1])

    d = d1.to_dict()
    d2 = Detector.from_dict(d)
    assert(len(d1) == len(d2))
    for p1, p2 in zip(d1, d2):
      assert(p1 == p2)
    assert(d1.hierarchy() == d2.hierarchy())
    assert(d1 == d2)

    print 'OK'
Beispiel #9
0
def test_hierarchical_detector():
    '''Test pickling the detector object.'''
    p = Panel()
    p.set_local_frame((1, 0, 0), (0, 1, 0), (0, 0, 1))
    obj1 = Detector()
    root = obj1.hierarchy()
    root.add_panel(p)
    root.add_group()
    obj2 = pickle_then_unpickle(obj1)
    assert obj2.hierarchy()[0] == obj2[0]
    assert obj2.hierarchy()[0] in obj2
    assert obj2.hierarchy()[1].is_group()
    assert obj1 == obj2
Beispiel #10
0
def test_detector():
    d1 = Detector()
    p = d1.add_panel()
    p.set_name("p1")
    p.set_type("panel")
    p.set_pixel_size((0.1, 0.1))
    p.set_image_size((100, 100))
    p.set_trusted_range((0, 1000))
    p.set_local_frame((1, 0, 0), (0, 1, 0), (0, 0, 1))

    p = d1.add_panel()
    p.set_name("p2")
    p.set_type("panel")
    p.set_pixel_size((0.2, 0.2))
    p.set_image_size((200, 200))
    p.set_trusted_range((0, 2000))
    p.set_local_frame((0, 1, 0), (1, 0, 0), (0, 0, 1))

    root = d1.hierarchy()
    g = root.add_group()
    g.set_name("g1")
    g.set_type("group")
    g.set_local_frame((0, 1, 0), (1, 0, 0), (0, 0, 2))
    g.add_panel(d1[0])

    g = root.add_group()
    g.set_name("g2")
    g.set_type("group")
    g.set_local_frame((0, 1, 0), (1, 0, 0), (0, 0, 4))
    g.add_panel(d1[1])

    d = d1.to_dict()
    d2 = Detector.from_dict(d)
    assert len(d1) == len(d2)
    for p1, p2 in zip(d1, d2):
        assert p1 == p2
    assert d1.hierarchy() == d2.hierarchy()
    assert d1 == d2
Beispiel #11
0
def tst_hierarchical_detector():
  '''Test pickling the detector object.'''
  p = Panel()
  p.set_local_frame((1, 0, 0), (0, 1, 0), (0, 0, 1))
  obj1 = Detector()
  root = obj1.hierarchy()
  root.add_panel(p)
  root.add_group()
  obj2 = pickle_then_unpickle(obj1)
  assert(obj2.hierarchy()[0] == obj2[0])
  assert(obj2.hierarchy()[0] in obj2)
  assert(obj2.hierarchy()[1].is_group())
  assert(obj1 == obj2)
  print "OK"
Beispiel #12
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
Beispiel #13
0
from __future__ import print_function

from dxtbx.model import Detector

d = Detector()
p1 = d.add_panel()
p2 = d.add_panel()
p3 = d.add_panel()
p4 = d.add_panel()

root = d.hierarchy()
g = root.add_group()
g.add_panel(d[0])
g.add_panel(d[1])
root.add_panel(d[2])
root.add_panel(d[3])
print(d.to_dict())
    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
Beispiel #15
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
Beispiel #16
0



from dxtbx.model import Detector
d = Detector()
p1 = d.add_panel()
p2 = d.add_panel()
p3 = d.add_panel()
p4 = d.add_panel()


root = d.hierarchy()
g = root.add_group()
g.add_panel(d[0])
g.add_panel(d[1])
root.add_panel(d[2])
root.add_panel(d[3])
print d.to_dict()
Beispiel #17
0
class DetectorFactoryFromGroup(object):
  '''
  A class to create a detector model from a NXdetector_group

  '''

  def __init__(self, instrument, beam, idx = None):
    from dxtbx.model import Detector, Panel
    from cctbx.eltbx import attenuation_coefficient
    from dxtbx.model import ParallaxCorrectedPxMmStrategy
    from scitbx import matrix
    import os

    if idx is None:
      idx = 0

    assert len(instrument.detector_groups) == 1, "Multiple detectors not supported"

    nx_group = instrument.detector_groups[0].handle
    group_names = nx_group['group_names']
    group_indices = nx_group['group_index']
    group_parent = nx_group['group_parent']

    # Verify the NXdetector objects specified by the detector group are present
    expected_detectors = []
    root_name = None
    for i, parent_id in enumerate(group_parent):
      assert parent_id in [-1, 1], "Hierarchy of detectors not supported. Hierarchy of module components within detector elements is supported"

      if parent_id == -1:
        assert root_name is None, "Multiple roots not supported"
        root_name = group_names[i]
      else:
        expected_detectors.append(group_names[i])

    assert root_name is not None, "Detector root not found"
    assert sorted([os.path.basename(d.handle.name) for d in instrument.detectors]) == sorted(expected_detectors), \
      "Mismatch between detector group names and detectors available"

    root = None

    def set_frame(pg, transformation):
      ''' Function to set the local frame of a panel/panel group given an
      NXtransformation '''
      parent, cob = get_cummulative_change_of_basis(transformation)
      # set up the dxtbx d matrix.  Note use of homogenous coordinates.
      origin = matrix.col((cob * matrix.col((0,0,0,1)))[0:3])
      fast   = matrix.col((cob * matrix.col((1,0,0,1)))[0:3]) - origin
      slow   = matrix.col((cob * matrix.col((0,1,0,1)))[0:3]) - origin

      pg.set_local_frame(
        fast.elems,
        slow.elems,
        origin.elems)

      name = str(os.path.basename(transformation.name))
      pg.set_name(name)

    self.model = Detector()
    for nx_detector in instrument.detectors:
      # Get the detector type
      if 'type' in nx_detector.handle:
        detector_type = str(nx_detector.handle['type'][()])
      else:
        detector_type = "unknown"

      # get the set of leaf modules (handles nested modules)
      modules = []
      for nx_detector_module in nx_detector.modules:
        if len(find_class(nx_detector_module.handle, "NXdetector_module")) == 0:
          modules.append(nx_detector_module)

      n_modules = len(modules)
      # depends_on field for a detector will have NxM entries in it, where
      # N = number of images and M = number of detector modules
      assert len(nx_detector.handle['depends_on']) % n_modules == 0, "Couldn't find NXdetector_modules matching the list of dependencies for this detector"

      for module_number, nx_detector_module in enumerate(modules):
        # Get the depends_on starting point for this module and for this image
        depends_on = nx_detector.handle[nx_detector.handle['depends_on'][(idx//n_modules)+module_number]]
        panel_name = str(os.path.basename(nx_detector_module.handle.name))
        px_fast = int(nx_detector_module.handle['data_size'][0])
        px_slow = int(nx_detector_module.handle['data_size'][1])
        image_size = px_fast, px_slow
        fast_pixel_size = nx_detector_module.handle['fast_pixel_size'][()]
        slow_pixel_size = nx_detector_module.handle['slow_pixel_size'][()]
        pixel_size = fast_pixel_size, slow_pixel_size
        # XXX no units for pixel size in nx example file, plus fast_pixel_size isn't a standardized NXdetector_module field
        #fast_pixel_direction_units = fast_pixel_direction.attrs['units']
        #fast_pixel_size = convert_units(
        #  fast_pixel_direction_value,
        #  fast_pixel_direction_units,
        #  "mm")
        # Get the trusted range of pixel values
        underload = float(nx_detector['undefined_value'][()])  if 'undefined_value'  in nx_detector.handle else -400
        overload  = float(nx_detector['saturation_value'][()]) if 'saturation_value' in nx_detector.handle else 90000
        trusted_range = underload, overload

        # Set up the hierarchical detector by iteraing through the dependencies,
        # starting at the root
        chain = get_depends_on_chain_using_equipment_components(depends_on)
        pg = None
        for transform in reversed(chain):
          name = str(os.path.basename(transform.name))
          if pg is None: # The first transform will be the root of the hiearchy
            if root is None:
              root = self.model.hierarchy()
              set_frame(root, transform)
            else:
              assert root.get_name() == name, "Found multiple roots"
            pg = root
            continue

          # subsequent times through the loop, pg will be the parent of the
          # current transform
          pg_names = [child.get_name() for child in pg]
          if name in pg_names:
            pg = pg[pg_names.index(name)]
          else:
            pg = pg.add_group()
            set_frame(pg, transform)

        # pg is now this panel's parent
        p = pg.add_panel()
        fast = depends_on.attrs['vector']
        fast = matrix.col([-fast[0], fast[1], -fast[2]])
        slow = nx_detector_module.handle[depends_on.attrs['depends_on']].attrs['vector']
        slow = matrix.col([-slow[0], slow[1], -slow[2]])
        parent, cob = get_cummulative_change_of_basis(depends_on)
        origin = matrix.col((cob * matrix.col((0,0,0,1)))[0:3])

        p.set_local_frame(
          fast.elems,
          slow.elems,
          origin.elems)

        p.set_name(panel_name)
        p.set_pixel_size(pixel_size)
        p.set_image_size(image_size)
        p.set_type(detector_type)
        p.set_trusted_range(trusted_range)

        if 'sensor_thickness' in nx_detector.handle:
          # Get the detector thickness
          thickness = nx_detector.handle['sensor_thickness']
          thickness_value = float(thickness[()])
          thickness_units = thickness.attrs['units']
          thickness_value = float(convert_units(
            thickness_value,
            thickness_units,
            "mm"))
          p.set_thickness(thickness_value)

        # Get the detector material
        if 'sensor_material' in nx_detector.handle:
          material = str(nx_detector.handle['sensor_material'][()])
          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
          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()
          p.set_mu(table.mu_at_angstrom(wavelength) / 10.0)

        if 'sensor_thickness' in nx_detector.handle and 'sensor_material' in nx_detector.handle:
          p.set_px_mm_strategy(ParallaxCorrectedPxMmStrategy(mu, thickness_value))
Beispiel #18
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
Beispiel #19
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
Beispiel #20
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
Beispiel #21
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
        assert len(self.params.detector_address) == 1

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

        det = self._get_psana_detector(run)

        geom = det.pyda.geoaccess(self._get_event(index).run())
        pixel_size = 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], -abs(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))

        # Modules next
        for module_num in range(len(root.get_list_of_children())):
            pg1 = pg0.add_group()
            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.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 Epix 2x2 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(4):
                val = "ARRAY_D0M%dA%d" % (module_num, asic_num)
                p = pg1.add_panel()
                dim_slow = xx.shape[0]
                dim_fast = xx.shape[1]
                sensor_id = asic_num // 2  # There are 2X2 asics per module
                asic_in_sensor_id = asic_num % 2  # this number will be 0 or 1
                id_slow = sensor_id * (dim_slow // 2)
                id_fast = asic_in_sensor_id * (dim_fast // 2)
                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.set_local_frame(fast.elems, slow.elems, origin.elems)
                p.set_pixel_size((pixel_size, pixel_size))
                p.set_image_size((dim_fast // 2, dim_slow // 2))
                p.set_trusted_range((-1, 2e6))
                p.set_gain(factor_kev_angstrom / wavelength)
                p.set_name(val)
        self._cached_detector[run.run()] = d
        return d
Beispiel #22
0
    def _detector(self, index=None):
        run = self.get_run_from_index(index)
        if run.run() in self._cached_detector:
            return self._cached_detector[run.run()]
        import psana
        from dxtbx.model import Detector
        from scitbx.matrix import col

        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
        D0 = geom.get_top_geo().get_list_of_children()[0]
        xx, yy, zz = D0.get_pixel_coords()
        xx = xx / 1000.0  # to mm
        yy = yy / 1000.0  # to mm
        zz = zz / 1000.0  # to mm
        oriD0 = col((np.mean(xx), np.mean(yy), -np.mean(zz)))
        fp = col((xx[0][0][1], yy[0][0][1], zz[0][0][1]))
        sp = col((xx[0][1][0], yy[0][1][0], zz[0][1][0]))
        op = col((xx[0][0][0], yy[0][0][0], zz[0][0][0]))
        origin = oriD0
        fast = (fp - op).normalize()
        slow = (sp - op).normalize()
        pg0.set_local_frame(fast.elems, slow.elems, origin.elems)
        pg0.set_name("D%d" % (det_num))

        # Now deal with Qx
        for quad_num in range(2):
            pg1 = pg0.add_group()
            Qx = D0.get_list_of_children()[quad_num]
            xx, yy, zz = Qx.get_pixel_coords()
            xx = xx / 1000.0  # to mm
            yy = yy / 1000.0  # to mm
            zz = zz / 1000.0  # to mm
            oriQx = col((np.mean(xx), np.mean(yy), np.mean(zz)))
            fp = col((xx[0][1], yy[0][1], zz[0][1]))
            sp = col((xx[1][0], yy[1][0], zz[1][0]))
            op = col((xx[0][0], yy[0][0], zz[0][0]))
            origin = oriQx
            fast = (fp - op).normalize()
            slow = (sp - op).normalize()
            pg1.set_local_frame(fast.elems, slow.elems, origin.elems)
            pg1.set_name("D%dQ%d" % (det_num, quad_num))

            # Now deal with Az
            for asic_num in range(8):
                val = "ARRAY_D0Q%dA%d" % (quad_num, asic_num)
                p = pg1.add_panel()
                dim_slow = xx.shape[0]
                dim_fast = xx.shape[1]
                sensor_id = asic_num // 4  # There are 2X4 asics per quadrant
                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)
                oriAy = col(
                    (xx[id_slow][id_fast], yy[id_slow][id_fast], zz[id_slow][id_fast])
                )
                fp = col(
                    (
                        xx[id_slow][id_fast + 1],
                        yy[id_slow][id_fast + 1],
                        zz[id_slow][id_fast + 1],
                    )
                )
                sp = col(
                    (
                        xx[id_slow + 1][id_fast],
                        yy[id_slow + 1][id_fast],
                        zz[id_slow + 1][id_fast],
                    )
                )
                origin = oriAy - oriQx
                fast = (fp - oriAy).normalize()
                slow = (sp - oriAy).normalize()
                p.set_local_frame(fast.elems, slow.elems, origin.elems)
                p.set_pixel_size((pixel_size, pixel_size))
                p.set_image_size((dim_fast // 4, dim_slow // 2))
                p.set_trusted_range((-1, 2e6))
                p.set_name(val)
        self._cached_detector[run.run()] = d
        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
    def _detector(self):
        """Detector model, allowing for small offsets in the positions of 60
        detector modules"""

        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):
    '''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, 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

    # 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