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.''' detector = FormatCBFMini._detector(self) for f0, s0, f1, s1 in determine_pilatus_mask(detector): detector[0].add_mask(f0, s0, f1, s1) 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.""" 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