def detectorbase_start(self): from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.open_file = self.open_file self.detectorbase.readHeader() self.detectorbase.parameters['SIZE1'] = 2527 self.detectorbase.parameters['SIZE2'] = 2463
def detectorbase_start(self): if not hasattr(self, "detectorbase") or self.detectorbase is None: from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.open_file = self.open_file self.detectorbase.readHeader()
class FormatSMVADSCDBG(FormatSMVADSC): """ Format class for reading images converted from pilatus to smv adsc""" @staticmethod def understand(image_file): """Check to see if this has the correct dimensions of a pilatus""" size, header = FormatSMVADSC.get_smv_header(image_file) if int(header["SIZE1"]) == 2463 and int(header["SIZE2"]) == 2527: return True return False def _start(self): # read the headers, then swap size1 and size2 FormatSMVADSC._start(self) self._header_dictionary["SIZE1"] = "2527" self._header_dictionary["SIZE2"] = "2463" def detectorbase_start(self): from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.open_file = self.open_file self.detectorbase.readHeader() self.detectorbase.parameters["SIZE1"] = 2527 self.detectorbase.parameters["SIZE2"] = 2463 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._header_dictionary["DISTANCE"]) beam_x = float(self._header_dictionary["BEAM_CENTER_X"]) beam_y = float(self._header_dictionary["BEAM_CENTER_Y"]) pixel_size = float(self._header_dictionary["PIXEL_SIZE"]) # size1 and size2 swapped here image_size = ( float(self._header_dictionary["SIZE2"]), float(self._header_dictionary["SIZE1"]), ) overload = 65535 underload = 0 return self._detector_factory.simple( "CCD", distance, (beam_y, beam_x), "+x", "-y", (pixel_size, pixel_size), image_size, (underload, overload), [], )
class FormatSMVADSCDBG(FormatSMVADSC): """ Format class for reading images converted from pilatus to smv adsc""" @staticmethod def understand(image_file): """Check to see if this has the correct dimensions of a pilatus""" size, header = FormatSMVADSC.get_smv_header(image_file) if int(header["SIZE1"]) == 2463 and int(header["SIZE2"]) == 2527: return True return False def _start(self): # read the headers, then swap size1 and size2 FormatSMVADSC._start(self) self._header_dictionary["SIZE1"] = "2527" self._header_dictionary["SIZE2"] = "2463" from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.readHeader() self.detectorbase.parameters["SIZE1"] = 2527 self.detectorbase.parameters["SIZE2"] = 2463 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._header_dictionary["DISTANCE"]) beam_x = float(self._header_dictionary["BEAM_CENTER_X"]) beam_y = float(self._header_dictionary["BEAM_CENTER_Y"]) pixel_size = float(self._header_dictionary["PIXEL_SIZE"]) # size1 and size2 swapped here image_size = (float(self._header_dictionary["SIZE2"]), float(self._header_dictionary["SIZE1"])) overload = 65535 underload = 0 return self._detector_factory.simple( "CCD", distance, (beam_y, beam_x), "+x", "-y", (pixel_size, pixel_size), image_size, (underload, overload), [], )
class FormatSMVADSCDBG(FormatSMVADSC): ''' Format class for reading images converted from pilatus to smv adsc''' @staticmethod def understand(image_file): '''Check to see if this has the correct dimensions of a pilatus''' size, header = FormatSMVADSC.get_smv_header(image_file) if int(header['SIZE1']) == 2463 and int(header['SIZE2']) == 2527: return True return False def _start(self): # read the headers, then swap size1 and size2 FormatSMVADSC._start(self) self._header_dictionary['SIZE1'] = '2527' self._header_dictionary['SIZE2'] = '2463' def detectorbase_start(self): from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.open_file = self.open_file self.detectorbase.readHeader() self.detectorbase.parameters['SIZE1'] = 2527 self.detectorbase.parameters['SIZE2'] = 2463 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._header_dictionary['DISTANCE']) beam_x = float(self._header_dictionary['BEAM_CENTER_X']) beam_y = float(self._header_dictionary['BEAM_CENTER_Y']) pixel_size = float(self._header_dictionary['PIXEL_SIZE']) # size1 and size2 swapped here image_size = (float(self._header_dictionary['SIZE2']), float(self._header_dictionary['SIZE1'])) overload = 65535 underload = 0 return self._detector_factory.simple('CCD', distance, (beam_y, beam_x), '+x', '-y', (pixel_size, pixel_size), image_size, (underload, overload), [])
def _start(self): FormatSMV._start(self) if not hasattr(self, "detectorbase") or self.detectorbase is None: from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.readHeader()
class FormatSMVADSCDBG(FormatSMVADSC): ''' Format class for reading images converted from pilatus to smv adsc''' @staticmethod def understand(image_file): '''Check to see if this has the correct dimensions of a pilatus''' size, header = FormatSMVADSC.get_smv_header(image_file) if int(header['SIZE1']) == 2463 and int(header['SIZE2']) == 2527: return True return False def _start(self): # read the headers, then swap size1 and size2 FormatSMVADSC._start(self) self._header_dictionary['SIZE1'] = '2527' self._header_dictionary['SIZE2'] = '2463' def detectorbase_start(self): from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.readHeader() self.detectorbase.parameters['SIZE1'] = 2527 self.detectorbase.parameters['SIZE2'] = 2463 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._header_dictionary['DISTANCE']) beam_x = float(self._header_dictionary['BEAM_CENTER_X']) beam_y = float(self._header_dictionary['BEAM_CENTER_Y']) pixel_size = float(self._header_dictionary['PIXEL_SIZE']) # size1 and size2 swapped here image_size = (float(self._header_dictionary['SIZE2']), float(self._header_dictionary['SIZE1'])) overload = 65535 underload = 0 return self._detector_factory.simple( 'CCD', distance, (beam_y, beam_x), '+x', '-y', (pixel_size, pixel_size), image_size, (underload, overload), [])
def _start(self): # read the headers, then swap size1 and size2 FormatSMVADSC._start(self) self._header_dictionary["SIZE1"] = "2527" self._header_dictionary["SIZE2"] = "2463" from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.readHeader() self.detectorbase.parameters["SIZE1"] = 2527 self.detectorbase.parameters["SIZE2"] = 2463
def detectorbase_start(self): self.detectorbase = SMVImage(self._image_file) self.detectorbase.open_file = self.open_file self.detectorbase.readHeader() self.detectorbase.parameters["SIZE1"] = 2527 self.detectorbase.parameters["SIZE2"] = 2463
class FormatSMVTimePix_SU(FormatSMV): '''Base format class to specifically recognise images from a Timepix-based detector, installed on a JEOL-2100 electron microscope at Stockholm University, which have been preprocessed by Wei Wan's RED software, to produce SMV files. See https://doi.org/10.1107/S0021889813027714 for RED. The detector itself has a 2x2 array of Timepix modules. Derived classes will either treat these separately as a multi-panel model, or as a single panel model.''' @staticmethod def understand(image_file): size, header = FormatSMV.get_smv_header(image_file) # only recognise TimePix_SU if header.get('BEAMLINE', '').upper() != 'TIMEPIX_SU': return False # check the header contains the things we're going to use wanted_header_items = [ 'BEAM_CENTER_X', 'BEAM_CENTER_Y', 'DISTANCE', 'WAVELENGTH', 'PIXEL_SIZE', 'OSC_START', 'OSC_RANGE', 'PHI', 'SIZE1', 'SIZE2', 'BYTE_ORDER', 'DETECTOR_SN' ] for header_item in wanted_header_items: if not header_item in header: return False return True def __init__(self, image_file, **kwargs): '''Initialise the image structure from the given file, including a proper model of the experiment.''' from dxtbx import IncorrectFormatError if not self.understand(image_file): raise IncorrectFormatError(self, image_file) FormatSMV.__init__(self, image_file, **kwargs) def _start(self): FormatSMV._start(self) def detectorbase_start(self): if not hasattr(self, "detectorbase") or self.detectorbase is None: from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.open_file = self.open_file self.detectorbase.readHeader() def _goniometer(self): '''Return a model for a simple single-axis goniometer. For this beamline this should be close to the provided values and neither aligned with the detector slow or fast axes.''' return self._goniometer_factory.known_axis((-0.755, -0.656, 0.0)) def _beam(self): '''Return an unpolarized beam model.''' wavelength = float(self._header_dictionary['WAVELENGTH']) return self._beam_factory.make_polarized_beam( sample_to_source=(0.0, 0.0, 1.0), wavelength=wavelength, polarization=(0, 1, 0), polarization_fraction=0.5) def _scan(self): '''Return the scan information for this image.''' import calendar format = self._scan_factory.format('SMV') exposure_time = float(self._header_dictionary['TIME']) epoch = None # PST, PDT timezones not recognised by default... epoch = 0 try: date_str = self._header_dictionary['DATE'] date_str = date_str.replace('PST', '').replace('PDT', '') except KeyError: date_str = '' for format_string in [ '%a %b %d %H:%M:%S %Y', '%a %b %d %H:%M:%S %Z %Y' ]: try: epoch = calendar.timegm(time.strptime(date_str, format_string)) break except ValueError: pass # assert(epoch) osc_start = float(self._header_dictionary['OSC_START']) osc_range = float(self._header_dictionary['OSC_RANGE']) return self._scan_factory.single(self._image_file, format, exposure_time, osc_start, osc_range, epoch)
class FormatSMVJHSim(FormatSMV): '''A class for reading SMV format JHSim images, and correctly constructing a model for the experiment from this.''' # all ADSC detectors generate images with an ADC offset of 40 # for Mar/Rayonix it is 10 # Rigaku SMV uses 20, and 5 for image plate formats # for one particular simulation, I used 1 ADC_OFFSET = 1 image_pedestal = 1 @staticmethod def understand(image_file): '''Check to see if this looks like an JHSim SMV format image, i.e. we can make sense of it. From JH: "The best way to identify images from any of my simulators is to look for BEAMLINE=fake in the header."''' size, header = FormatSMV.get_smv_header(image_file) if header.get('BEAMLINE') == 'fake': return True else: return False def __init__(self, image_file, **kwargs): '''Initialise the image structure from the given file, including a proper model of the experiment.''' from dxtbx import IncorrectFormatError if not self.understand(image_file): raise IncorrectFormatError(self, image_file) FormatSMV.__init__(self, image_file, **kwargs) return def _start(self): FormatSMV._start(self) def detectorbase_start(self): if not hasattr(self, "detectorbase") or self.detectorbase is None: from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.open_file = self.open_file self.detectorbase.readHeader() def _goniometer(self): '''Return a model for a simple single-axis goniometer. This should probably be checked against the image header.''' return self._goniometer_factory.single_axis() 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._header_dictionary['DISTANCE']) beam_x = float(self._header_dictionary['BEAM_CENTER_X']) beam_y = float(self._header_dictionary['BEAM_CENTER_Y']) pixel_size = float(self._header_dictionary['PIXEL_SIZE']) image_size = (float(self._header_dictionary['SIZE1']), float(self._header_dictionary['SIZE2'])) image_pedestal = 1 try: image_pedestal = float(self._header_dictionary['ADC_OFFSET']) except (KeyError): pass overload = 65535 - image_pedestal underload = 1 - image_pedestal # interpret beam center conventions image_width_mm = pixel_size * image_size[0] image_height_mm = pixel_size * image_size[1] adxv_beam_center = (beam_x, beam_y) mosflm_beam_center = (image_height_mm - adxv_beam_center[1], adxv_beam_center[0]) xds_beam_center = (adxv_beam_center[0] / pixel_size, (image_height_mm - adxv_beam_center[1]) / pixel_size) cctbx_beam_center = (adxv_beam_center[0] + pixel_size, image_height_mm - adxv_beam_center[1] + pixel_size) # Guess whether this is mimicking a Pilatus, if so set detector type so # that spot-finding parameters are appropriate if pixel_size == 0.172: stype = 'SENSOR_PAD' else: stype = 'CCD' return self._detector_factory.simple(stype, distance, cctbx_beam_center, '+x', '-y', (pixel_size, pixel_size), image_size, (underload, overload), []) def _beam(self): '''Return a simple model for the beam.''' wavelength = float(self._header_dictionary['WAVELENGTH']) return self._beam_factory.simple(wavelength) def _scan(self): '''Return the scan information for this image.''' import calendar format = self._scan_factory.format('SMV') exposure_time = 1 epoch = None # PST, PDT timezones not recognised by default... epoch = 0 try: date_str = self._header_dictionary['DATE'] date_str = date_str.replace('PST', '').replace('PDT', '') except KeyError, e: date_str = '' for format_string in [ '%a %b %d %H:%M:%S %Y', '%a %b %d %H:%M:%S %Z %Y' ]: try: epoch = calendar.timegm(time.strptime(date_str, format_string)) break except ValueError, e: pass
class FormatSMVTimePix_SU(FormatSMV): """Base format class to specifically recognise images from a Timepix-based detector, installed on a JEOL-2100 electron microscope at Stockholm University, which have been preprocessed by Wei Wan's RED software, to produce SMV files. See https://doi.org/10.1107/S0021889813027714 for RED. The detector itself has a 2x2 array of Timepix modules. Derived classes will either treat these separately as a multi-panel model, or as a single panel model.""" @staticmethod def understand(image_file): size, header = FormatSMV.get_smv_header(image_file) # only recognise TimePix_SU if header.get("BEAMLINE", "").upper() != "TIMEPIX_SU": return False # check the header contains the things we're going to use wanted_header_items = [ "BEAM_CENTER_X", "BEAM_CENTER_Y", "DISTANCE", "WAVELENGTH", "PIXEL_SIZE", "OSC_START", "OSC_RANGE", "PHI", "SIZE1", "SIZE2", "BYTE_ORDER", "DETECTOR_SN", ] if any(item not in header for item in wanted_header_items): return False return True def detectorbase_start(self): if not hasattr(self, "detectorbase") or self.detectorbase is None: self.detectorbase = SMVImage(self._image_file) self.detectorbase.open_file = self.open_file self.detectorbase.readHeader() def _goniometer(self): """Return a model for a simple single-axis goniometer. For this beamline this should be close to the provided values and neither aligned with the detector slow or fast axes.""" return self._goniometer_factory.known_axis((-0.755, -0.656, 0.0)) def _beam(self): """Return an unpolarized beam model.""" wavelength = float(self._header_dictionary["WAVELENGTH"]) return self._beam_factory.make_polarized_beam( sample_to_source=(0.0, 0.0, 1.0), wavelength=wavelength, polarization=(0, 1, 0), polarization_fraction=0.5, ) def _scan(self): """Return the scan information for this image.""" format = self._scan_factory.format("SMV") exposure_time = float(self._header_dictionary["TIME"]) epoch = None # PST, PDT timezones not recognised by default... epoch = 0 try: date_str = self._header_dictionary["DATE"] date_str = date_str.replace("PST", "").replace("PDT", "") except KeyError: date_str = "" for format_string in [ "%a %b %d %H:%M:%S %Y", "%a %b %d %H:%M:%S %Z %Y" ]: try: epoch = calendar.timegm(time.strptime(date_str, format_string)) break except ValueError: pass # assert(epoch) osc_start = float(self._header_dictionary["OSC_START"]) osc_range = float(self._header_dictionary["OSC_RANGE"]) return self._scan_factory.single(self._image_file, format, exposure_time, osc_start, osc_range, epoch)
class FormatSMVADSC(FormatSMV): """A class for reading SMV format ADSC images, and correctly constructing a model for the experiment from this.""" @staticmethod def understand(image_file): """Check to see if this looks like an ADSC SMV format image, i.e. we can make sense of it. Essentially that will be if it contains all of the keys we are looking for and not some we are not (i.e. that belong to a Rigaku Saturn.)""" size, header = FormatSMV.get_smv_header(image_file) # do not understand JHSim images if header.get("BEAMLINE") == "fake": return False # do not understand Timepix_SU images if header.get("BEAMLINE", "").upper() == "TIMEPIX_SU": return False # this used to include TIME wanted_header_items = [ "BEAM_CENTER_X", "BEAM_CENTER_Y", "DISTANCE", "WAVELENGTH", "PIXEL_SIZE", "OSC_START", "OSC_RANGE", "SIZE1", "SIZE2", "BYTE_ORDER", ] if any(item not in header for item in wanted_header_items): return False unwanted_header_items = ["DTREK_DATE_TIME"] if any(item in header for item in unwanted_header_items): return False return True def detectorbase_start(self): if not hasattr(self, "detectorbase") or self.detectorbase is None: self.detectorbase = SMVImage(self._image_file) self.detectorbase.open_file = self.open_file self.detectorbase.readHeader() def _goniometer(self): """Return a model for a simple single-axis goniometer. Invert the axis if the rotation range is negative.""" if float(self._header_dictionary["OSC_RANGE"]) > 0: return self._goniometer_factory.single_axis() else: return self._goniometer_factory.single_axis_reverse() def _adsc_trusted_range(self, pedestal=None): """Return a 16 bit trusted range shifted to account for any image pedestal that is present""" if pedestal is None: pedestal = int(self._header_dictionary.get("IMAGE_PEDESTAL", 0)) overload = 65535 - pedestal underload = -1 - pedestal return underload, overload def _adsc_module_gain(self, model=None): """Return an appropriate gain value in ADU per captured X-ray for an ADSC CCD module. If the model is None (unknown) then make a guess based on header details""" # Values are based on a combination of manufacturer datasheets, # James Holton's list at http://bl831.als.lbl.gov/xtalsize.html and # empirical guesswork based on spot finding results. The accuracy should # not be expected to be better than 20% and indeed may be worse than that. # Values may refer to gain in ADU per incident photon rather than the # more appropriate ADU per captured photon. # Get the binning level bin_lev = str(self._header_dictionary.get("BIN")) if model is None: # guesswork based on the header details npx1 = int(self._header_dictionary["SIZE1"]) npx2 = int(self._header_dictionary["SIZE2"]) px_sz = float(self._header_dictionary["PIXEL_SIZE"]) if npx1 == npx2 == 2304 and px_sz == 0.0816: model = "Q4" # or Q4R elif npx1 == npx2 == 4096 and px_sz == 0.0512: model = "Q210" # or Q210R bin none or 1x1 elif npx1 == npx2 == 2048 and px_sz == 0.1024: model = "Q210" # or Q210R bin 2x2 bin_lev = "2x2" elif npx1 == npx2 == 6144 and px_sz == 0.0512: model = "Q315" # or Q315R bin none or 1x1 elif npx1 == npx2 == 3072 and px_sz == 0.1024: model = "Q315" # or Q315R bin 2x2 bin_lev = "2x2" elif npx1 == npx2 == 4168 and px_sz == 0.0648: model = "Q270" # or Q270R bin none or 1x1 elif npx1 == npx2 == 2084 and px_sz == 0.0324: model = "Q270" # or Q270R bin 2x2 bin_lev = "2x2" else: # Unidentified model return 1.0 model = model.upper() if model.startswith("Q270"): # Don't know the difference between binning modes in this case return 2.8 if model.startswith("Q4"): # https://web.archive.org/web/20051224172252/http://www.adsc-xray.com:80/prod_compare.html # Don't know the difference between binning modes in this case return 1.25 # Get binning mode HW/SW bin_type = self._header_dictionary.get("BIN_TYPE") if bin_lev.upper() == "NONE": bin_type = None elif bin_type != "HW": bin_type = "SW" if bin_type == "SW": # return 0.6 This does not look believable. Default to 2.4 instead return 2.4 if bin_type != "HW": # assume unbinned return 2.4 elif model.endswith("R"): # e.g. Q315r, HW binning return 1.8 else: # e.g. Q315, HW binning return 2.4 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._header_dictionary["DISTANCE"]) beam_x = float(self._header_dictionary["BEAM_CENTER_X"]) beam_y = float(self._header_dictionary["BEAM_CENTER_Y"]) pixel_size = float(self._header_dictionary["PIXEL_SIZE"]) image_size = ( float(self._header_dictionary["SIZE1"]), float(self._header_dictionary["SIZE2"]), ) return self._detector_factory.simple( "CCD", distance, (beam_y, beam_x), "+x", "-y", (pixel_size, pixel_size), image_size, self._adsc_trusted_range(), [], gain=self._adsc_module_gain(), pedestal=int(self._header_dictionary.get("IMAGE_PEDESTAL", 0)), ) def _beam(self): """Return a simple model for the beam.""" wavelength = float(self._header_dictionary["WAVELENGTH"]) return self._beam_factory.simple(wavelength) def _scan(self): """Return the scan information for this image.""" format = self._scan_factory.format("SMV") exposure_time = float(self._header_dictionary["TIME"]) epoch = None # PST, PDT timezones not recognised by default... epoch = 0 try: date_str = self._header_dictionary["DATE"] date_str = date_str.replace("PST", "").replace("PDT", "") except KeyError: date_str = "" for format_string in [ "%a %b %d %H:%M:%S %Y", "%a %b %d %H:%M:%S %Z %Y" ]: try: epoch = calendar.timegm(time.strptime(date_str, format_string)) break except ValueError: pass # assert(epoch) osc_start = float(self._header_dictionary["OSC_START"]) osc_range = abs(float(self._header_dictionary["OSC_RANGE"])) return self._scan_factory.single(self._image_file, format, exposure_time, osc_start, osc_range, epoch) def get_raw_data(self): """Get the pixel intensities (i.e. read the image and return as a flex array of integers.)""" assert len(self.get_detector()) == 1 panel = self.get_detector()[0] image_size = panel.get_image_size() return self._get_endianic_raw_data(size=image_size)
class FormatSMVJHSim(FormatSMV): """A class for reading SMV format JHSim images, and correctly constructing a model for the experiment from this.""" # all ADSC detectors generate images with an ADC offset of 40 # for Mar/Rayonix it is 10 # Rigaku SMV uses 20, and 5 for image plate formats # for one particular simulation, I used 1 ADC_OFFSET = 1 image_pedestal = 1 @staticmethod def understand(image_file): """Check to see if this looks like an JHSim SMV format image, i.e. we can make sense of it. From JH: "The best way to identify images from any of my simulators is to look for BEAMLINE=fake in the header.".""" size, header = FormatSMV.get_smv_header(image_file) if header.get("BEAMLINE") == "fake": return True else: return False def __init__(self, image_file, **kwargs): """Initialise the image structure from the given file, including a proper model of the experiment.""" from dxtbx import IncorrectFormatError if not self.understand(image_file): raise IncorrectFormatError(self, image_file) FormatSMV.__init__(self, image_file, **kwargs) return def _start(self): FormatSMV._start(self) def detectorbase_start(self): if not hasattr(self, "detectorbase") or self.detectorbase is None: from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.open_file = self.open_file self.detectorbase.readHeader() def _goniometer(self): """Return a model for a simple single-axis goniometer. This should probably be checked against the image header.""" return self._goniometer_factory.single_axis() 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._header_dictionary["DISTANCE"]) beam_x = float(self._header_dictionary["BEAM_CENTER_X"]) beam_y = float(self._header_dictionary["BEAM_CENTER_Y"]) pixel_size = float(self._header_dictionary["PIXEL_SIZE"]) image_size = ( float(self._header_dictionary["SIZE1"]), float(self._header_dictionary["SIZE2"]), ) image_pedestal = 1 try: image_pedestal = float(self._header_dictionary["ADC_OFFSET"]) except (KeyError): pass overload = 65535 - image_pedestal underload = 1 - image_pedestal # interpret beam center conventions image_height_mm = pixel_size * image_size[1] adxv_beam_center = (beam_x, beam_y) cctbx_beam_center = ( adxv_beam_center[0] + pixel_size, image_height_mm - adxv_beam_center[1] + pixel_size, ) # Guess whether this is mimicking a Pilatus, if so set detector type so # that spot-finding parameters are appropriate if pixel_size == 0.172: stype = "SENSOR_PAD" else: stype = "CCD" return self._detector_factory.simple( stype, distance, cctbx_beam_center, "+x", "-y", (pixel_size, pixel_size), image_size, (underload, overload), [], ) def _beam(self): """Return a simple model for the beam.""" wavelength = float(self._header_dictionary["WAVELENGTH"]) return self._beam_factory.simple(wavelength) def _scan(self): """Return the scan information for this image.""" import calendar format = self._scan_factory.format("SMV") exposure_time = 1 epoch = None # PST, PDT timezones not recognised by default... epoch = 0 try: date_str = self._header_dictionary["DATE"] date_str = date_str.replace("PST", "").replace("PDT", "") except KeyError: date_str = "" for format_string in [ "%a %b %d %H:%M:%S %Y", "%a %b %d %H:%M:%S %Z %Y" ]: try: epoch = calendar.timegm(time.strptime(date_str, format_string)) break except ValueError: pass # assert(epoch) osc_start = float(self._header_dictionary["OSC_START"]) osc_range = float(self._header_dictionary["OSC_RANGE"]) return self._scan_factory.single(self._image_file, format, exposure_time, osc_start, osc_range, epoch) def get_raw_data(self): """Get the pixel intensities (i.e. read the image and return as a flex array of integers.)""" assert len(self.get_detector()) == 1 panel = self.get_detector()[0] image_size = panel.get_image_size() raw_data = self._get_endianic_raw_data(size=image_size) # apply image pedestal, will result in *negative pixel values* # this is a horrible idea since raw_data is unsigned # see all instances of image_pedestal in dxtbx image_pedestal = self._header_dictionary.get("ADC_OFFSET", 1) raw_data -= int(image_pedestal) return raw_data
def detectorbase_start(self): from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.readHeader() self.detectorbase.parameters['SIZE1'] = 2527 self.detectorbase.parameters['SIZE2'] = 2463
class FormatSMVADSC(FormatSMV): '''A class for reading SMV format ADSC images, and correctly constructing a model for the experiment from this.''' @staticmethod def understand(image_file): '''Check to see if this looks like an ADSC SMV format image, i.e. we can make sense of it. Essentially that will be if it contains all of the keys we are looking for and not some we are not (i.e. that belong to a Rigaku Saturn.)''' size, header = FormatSMV.get_smv_header(image_file) wanted_header_items = ['BEAM_CENTER_X', 'BEAM_CENTER_Y', 'DISTANCE', 'WAVELENGTH', 'PIXEL_SIZE', 'OSC_START', 'OSC_RANGE', 'SIZE1', 'SIZE2', 'BYTE_ORDER', 'TIME'] for header_item in wanted_header_items: if not header_item in header: return 0 unwanted_header_items = ['DTREK_DATE_TIME'] for header_item in unwanted_header_items: if header_item in header: return False return True def __init__(self, image_file, **kwargs): '''Initialise the image structure from the given file, including a proper model of the experiment.''' assert(self.understand(image_file)) FormatSMV.__init__(self, image_file, **kwargs) return def _start(self): FormatSMV._start(self) def detectorbase_start(self): if not hasattr(self, "detectorbase") or self.detectorbase is None: from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.readHeader() def _goniometer(self): '''Return a model for a simple single-axis goniometer. This should probably be checked against the image header.''' return self._goniometer_factory.single_axis() 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._header_dictionary['DISTANCE']) beam_x = float(self._header_dictionary['BEAM_CENTER_X']) beam_y = float(self._header_dictionary['BEAM_CENTER_Y']) pixel_size = float(self._header_dictionary['PIXEL_SIZE']) image_size = (float(self._header_dictionary['SIZE1']), float(self._header_dictionary['SIZE2'])) overload = 65535 underload = 1 return self._detector_factory.simple( 'CCD', distance, (beam_y, beam_x), '+x', '-y', (pixel_size, pixel_size), image_size, (underload, overload), []) def _beam(self): '''Return a simple model for the beam.''' wavelength = float(self._header_dictionary['WAVELENGTH']) return self._beam_factory.simple(wavelength) def _scan(self): '''Return the scan information for this image.''' import calendar format = self._scan_factory.format('SMV') exposure_time = float(self._header_dictionary['TIME']) epoch = None # PST, PDT timezones not recognised by default... epoch = 0 try: date_str = self._header_dictionary['DATE'] date_str = date_str.replace('PST', '').replace('PDT', '') except KeyError, e: date_str = '' for format_string in ['%a %b %d %H:%M:%S %Y', '%a %b %d %H:%M:%S %Z %Y']: try: epoch = calendar.timegm(time.strptime(date_str, format_string)) break except ValueError, e: pass
class FormatSMVADSC(FormatSMV): '''A class for reading SMV format ADSC images, and correctly constructing a model for the experiment from this.''' @staticmethod def understand(image_file): '''Check to see if this looks like an ADSC SMV format image, i.e. we can make sense of it. Essentially that will be if it contains all of the keys we are looking for and not some we are not (i.e. that belong to a Rigaku Saturn.)''' size, header = FormatSMV.get_smv_header(image_file) # do not understand JHSim images if header.get('BEAMLINE') == 'fake': return False # do not understand Timepix_SU images if header.get('BEAMLINE') == 'TimePix_SU': return False # this used to include TIME wanted_header_items = ['BEAM_CENTER_X', 'BEAM_CENTER_Y', 'DISTANCE', 'WAVELENGTH', 'PIXEL_SIZE', 'OSC_START', 'OSC_RANGE', 'SIZE1', 'SIZE2', 'BYTE_ORDER'] for header_item in wanted_header_items: if not header_item in header: return False unwanted_header_items = ['DTREK_DATE_TIME'] for header_item in unwanted_header_items: if header_item in header: return False return True def __init__(self, image_file, **kwargs): '''Initialise the image structure from the given file, including a proper model of the experiment.''' from dxtbx import IncorrectFormatError if not self.understand(image_file): raise IncorrectFormatError(self, image_file) FormatSMV.__init__(self, image_file, **kwargs) return def _start(self): FormatSMV._start(self) def detectorbase_start(self): if not hasattr(self, "detectorbase") or self.detectorbase is None: from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.open_file = self.open_file self.detectorbase.readHeader() def _goniometer(self): '''Return a model for a simple single-axis goniometer. This should probably be checked against the image header.''' return self._goniometer_factory.single_axis() 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._header_dictionary['DISTANCE']) beam_x = float(self._header_dictionary['BEAM_CENTER_X']) beam_y = float(self._header_dictionary['BEAM_CENTER_Y']) pixel_size = float(self._header_dictionary['PIXEL_SIZE']) image_size = (float(self._header_dictionary['SIZE1']), float(self._header_dictionary['SIZE2'])) overload = 65535 underload = 1 return self._detector_factory.simple( 'CCD', distance, (beam_y, beam_x), '+x', '-y', (pixel_size, pixel_size), image_size, (underload, overload), []) def _beam(self): '''Return a simple model for the beam.''' wavelength = float(self._header_dictionary['WAVELENGTH']) return self._beam_factory.simple(wavelength) def _scan(self): '''Return the scan information for this image.''' import calendar format = self._scan_factory.format('SMV') exposure_time = float(self._header_dictionary['TIME']) epoch = None # PST, PDT timezones not recognised by default... epoch = 0 try: date_str = self._header_dictionary['DATE'] date_str = date_str.replace('PST', '').replace('PDT', '') except KeyError, e: date_str = '' for format_string in ['%a %b %d %H:%M:%S %Y', '%a %b %d %H:%M:%S %Z %Y']: try: epoch = calendar.timegm(time.strptime(date_str, format_string)) break except ValueError, e: pass
class FormatSMVADSC(FormatSMV): '''A class for reading SMV format ADSC images, and correctly constructing a model for the experiment from this.''' @staticmethod def understand(image_file): '''Check to see if this looks like an ADSC SMV format image, i.e. we can make sense of it. Essentially that will be if it contains all of the keys we are looking for and not some we are not (i.e. that belong to a Rigaku Saturn.)''' size, header = FormatSMV.get_smv_header(image_file) # do not understand JHSim images if header.get('BEAMLINE') == 'fake': return False # do not understand Timepix_SU images if header.get('BEAMLINE', '').upper() == 'TIMEPIX_SU': return False # this used to include TIME wanted_header_items = [ 'BEAM_CENTER_X', 'BEAM_CENTER_Y', 'DISTANCE', 'WAVELENGTH', 'PIXEL_SIZE', 'OSC_START', 'OSC_RANGE', 'SIZE1', 'SIZE2', 'BYTE_ORDER' ] for header_item in wanted_header_items: if not header_item in header: return False unwanted_header_items = ['DTREK_DATE_TIME'] for header_item in unwanted_header_items: if header_item in header: return False return True def __init__(self, image_file, **kwargs): '''Initialise the image structure from the given file, including a proper model of the experiment.''' from dxtbx import IncorrectFormatError if not self.understand(image_file): raise IncorrectFormatError(self, image_file) FormatSMV.__init__(self, image_file, **kwargs) def _start(self): FormatSMV._start(self) def detectorbase_start(self): if not hasattr(self, "detectorbase") or self.detectorbase is None: from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.open_file = self.open_file self.detectorbase.readHeader() def _goniometer(self): '''Return a model for a simple single-axis goniometer. Invert the axis if the rotation range is negative.''' if float(self._header_dictionary['OSC_RANGE']) > 0: return self._goniometer_factory.single_axis() else: return self._goniometer_factory.single_axis_reverse() def _adsc_module_gain(self, model=None): '''Return an appropriate gain value in ADU per captured X-ray for an ADSC CCD module. If the model is None (unknown) then make a guess based on header details''' # Values are based on a combination of manufacturer datasheets, # James Holton's list at http://bl831.als.lbl.gov/xtalsize.html and # empirical guesswork based on spot finding results. The accuracy should # not be expected to be better than 20% and indeed may be worse than that. # Values may refer to gain in ADU per incident photon rather than the # more appropriate ADU per captured photon. # Get the binning level bin_lev = str(self._header_dictionary.get('BIN')) if model is None: # guesswork based on the header details npx1 = int(self._header_dictionary['SIZE1']) npx2 = int(self._header_dictionary['SIZE2']) px_sz = float(self._header_dictionary['PIXEL_SIZE']) if npx1 == npx2 == 2304 and px_sz == 0.0816: model = 'Q4' # or Q4R elif npx1 == npx2 == 4096 and px_sz == 0.0512: model = 'Q210' # or Q210R bin none or 1x1 elif npx1 == npx2 == 2048 and px_sz == 0.1024: model = 'Q210' # or Q210R bin 2x2 bin_lev = '2x2' elif npx1 == npx2 == 6144 and px_sz == 0.0512: model = 'Q315' # or Q315R bin none or 1x1 elif npx1 == npx2 == 3072 and px_sz == 0.1024: model = 'Q315' # or Q315R bin 2x2 bin_lev = '2x2' elif npx1 == npx2 == 4168 and px_sz == 0.0648: model = 'Q270' # or Q270R bin none or 1x1 elif npx1 == npx2 == 2084 and px_sz == 0.0324: model = 'Q270' # or Q270R bin 2x2 bin_lev = '2x2' else: # Unidentified model return 1.0 model = model.upper() if model.startswith('Q270'): # Don't know the difference between binning modes in this case return 2.8 if model.startswith('Q4'): # https://web.archive.org/web/20051224172252/http://www.adsc-xray.com:80/prod_compare.html # Don't know the difference between binning modes in this case return 1.25 # Get binning mode HW/SW bin_type = self._header_dictionary.get('BIN_TYPE') if bin_lev.upper() == 'NONE': bin_type = None elif bin_type != 'HW': bin_type = 'SW' if bin_type == 'SW': #return 0.6 This does not look believable. Default to 2.4 instead return 2.4 if bin_type != 'HW': # assume unbinned return 2.4 elif model.endswith('R'): # e.g. Q315r, HW binning return 1.8 else: # e.g. Q315, HW binning return 2.4 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._header_dictionary['DISTANCE']) beam_x = float(self._header_dictionary['BEAM_CENTER_X']) beam_y = float(self._header_dictionary['BEAM_CENTER_Y']) pixel_size = float(self._header_dictionary['PIXEL_SIZE']) image_size = (float(self._header_dictionary['SIZE1']), float(self._header_dictionary['SIZE2'])) if 'IMAGE_PEDESTAL' in self._header_dictionary: pedestal = int(self._header_dictionary['IMAGE_PEDESTAL']) else: pedestal = 0 overload = 65535 - pedestal underload = pedestal - 1 return self._detector_factory.simple('CCD', distance, (beam_y, beam_x), '+x', '-y', (pixel_size, pixel_size), image_size, (underload, overload), [], gain=self._adsc_module_gain()) def _beam(self): '''Return a simple model for the beam.''' wavelength = float(self._header_dictionary['WAVELENGTH']) return self._beam_factory.simple(wavelength) def _scan(self): '''Return the scan information for this image.''' import calendar format = self._scan_factory.format('SMV') exposure_time = float(self._header_dictionary['TIME']) epoch = None # PST, PDT timezones not recognised by default... epoch = 0 try: date_str = self._header_dictionary['DATE'] date_str = date_str.replace('PST', '').replace('PDT', '') except KeyError: date_str = '' for format_string in [ '%a %b %d %H:%M:%S %Y', '%a %b %d %H:%M:%S %Z %Y' ]: try: epoch = calendar.timegm(time.strptime(date_str, format_string)) break except ValueError: pass # assert(epoch) osc_start = float(self._header_dictionary['OSC_START']) osc_range = abs(float(self._header_dictionary['OSC_RANGE'])) return self._scan_factory.single(self._image_file, format, exposure_time, osc_start, osc_range, epoch) def get_raw_data(self): '''Get the pixel intensities (i.e. read the image and return as a flex array of integers.)''' from boost.python import streambuf from dxtbx import read_uint16, read_uint16_bs, is_big_endian from scitbx.array_family import flex assert (len(self.get_detector()) == 1) panel = self.get_detector()[0] size = panel.get_image_size() f = FormatSMVADSC.open_file(self._image_file, 'rb') f.read(self._header_size) if self._header_dictionary['BYTE_ORDER'] == 'big_endian': big_endian = True else: big_endian = False if big_endian == is_big_endian(): raw_data = read_uint16(streambuf(f), int(size[0] * size[1])) else: raw_data = read_uint16_bs(streambuf(f), int(size[0] * size[1])) image_size = panel.get_image_size() raw_data.reshape(flex.grid(image_size[1], image_size[0])) # if we subtract PEDESTAL is this still raw? if 'IMAGE_PEDESTAL' in self._header_dictionary: raw_data -= int(self._header_dictionary['IMAGE_PEDESTAL']) return raw_data
class FormatSMVTimePix_SU(FormatSMV): '''A class for reading SMV format images from the RED software, where the main identifying feature is BEAMLINE=TimePix_SU. This is intended to construct a model for an electron diffraction experiment using a microscope at Stockholm University.''' @staticmethod def understand(image_file): '''Check to see if this looks like an ADSC SMV format image, i.e. we can make sense of it. Essentially that will be if it contains all of the keys we are looking for and not some we are not (i.e. that belong to a Rigaku Saturn.)''' size, header = FormatSMV.get_smv_header(image_file) # only recognise TimePix_SU if header.get('BEAMLINE') != 'TimePix_SU': return False # check the header contains the things we're going to use wanted_header_items = ['BEAM_CENTER_X', 'BEAM_CENTER_Y', 'DISTANCE', 'WAVELENGTH', 'PIXEL_SIZE', 'OSC_START', 'OSC_RANGE', 'PHI', 'SIZE1', 'SIZE2', 'BYTE_ORDER', 'DETECTOR_SN'] for header_item in wanted_header_items: if not header_item in header: return False # check the pixel size is 55 microns if not float(header['PIXEL_SIZE']) == 0.055: return False # check there are 512*512 pixels if not (header['SIZE1']) == '512': return False if not (header['SIZE2']) == '512': return False return True def __init__(self, image_file, **kwargs): '''Initialise the image structure from the given file, including a proper model of the experiment.''' from dxtbx import IncorrectFormatError if not self.understand(image_file): raise IncorrectFormatError(self, image_file) FormatSMV.__init__(self, image_file, **kwargs) def _start(self): FormatSMV._start(self) def detectorbase_start(self): if not hasattr(self, "detectorbase") or self.detectorbase is None: from iotbx.detectors import SMVImage self.detectorbase = SMVImage(self._image_file) self.detectorbase.open_file = self.open_file self.detectorbase.readHeader() def _goniometer(self): '''Return a model for a simple single-axis goniometer. For this beamline this should be close to the provided values and neither aligned with the detector slow or fast axes.''' return self._goniometer_factory.known_axis((-0.755, -0.656, 0.0)) def _detector(self): '''4 panel detector, 55 micron pixels except for pixels at the outer edge of each chip, which are 165 microns wide.''' from scitbx import matrix # expect 55 mu pixels here, but make it general anyway pixel_size = tuple([float(self._header_dictionary['PIXEL_SIZE'])] * 2) image_size = (int(self._header_dictionary['SIZE1']), int(self._header_dictionary['SIZE2'])) panel_size = tuple([int(e/2) for e in image_size]) # outer pixels have three times the width panel_size_mm = (pixel_size[0] * 3 + (panel_size[0] - 2) * pixel_size[0], pixel_size[1] * 3 + (panel_size[1] - 2) * pixel_size[1]) image_size_mm = (panel_size_mm[0] * 2, panel_size_mm[1] * 2) trusted_range = (-1, 65535) material = 'Si' thickness = 0.3 # assume 300 mu thick # Initialise detector frame fast = matrix.col((1.0, 0.0, 0.0)) slow = matrix.col((0.0, -1.0, 0.0)) beam_centre = (float(self._header_dictionary['BEAM_CENTER_X']), float(self._header_dictionary['BEAM_CENTER_Y'])) bx_px, by_px = beam_centre # the beam centre is in pixels. We want to convert to mm, taking the # different size of outer pixels into account. Use this local function # to do that def px_to_mm(px, px_size_1d, panel_size_1d): mm = 0 if px > 1: # add first outer pixel mm += px_size_1d * 3 else: # or fraction of first outer pixel mm += px * px_size_1d * 3 return mm if px > panel_size_1d - 1: # add full panel of inner pixels mm += (panel_size_1d - 2) * px_size_1d else: # or fraction of inner pixels mm += (px - 1) * px_size_1d return mm if px > panel_size_1d: # add second outer pixel mm += px_size_1d * 3 else: # or fraction of second outer pixel mm += (px - (panel_size_1d - 1)) * px_size_1d * 3 return mm if px > panel_size_1d + 1: # add first outer pixel of second panel mm += px_size_1d * 3 else: # or fraction of first outer pixel of second panel mm += (px - panel_size_1d) * px_size_1d * 3 return mm if px > (2 * panel_size_1d - 1): # add second full panel of inner pixels mm += (panel_size_1d - 2) * px_size_1d # plus remaining fraction of the second outer pixel mm += (px - (2 * panel_size_1d - 1)) * px_size_1d * 3 else: # or fraction of inner pixels of the second panel mm += (px - panel_size_1d - 1) * px_size_1d return mm bx_mm = px_to_mm(bx_px, pixel_size[0], panel_size[0]) by_mm = px_to_mm(by_px, pixel_size[1], panel_size[1]) beam_centre_mm = (bx_mm, by_mm) # the beam centre is defined from the origin along fast, slow. To determine # the lab frame origin we place the beam centre down the -z axis cntr = matrix.col((0.0, 0.0, -1 * float(self._header_dictionary['DISTANCE']))) orig = cntr - bx_mm * fast - by_mm * slow d = Detector() root = d.hierarchy() root.set_local_frame( fast.elems, slow.elems, orig.elems) self.coords = {} panel_idx = 0 # set panel extent in pixel numbers and x, y mm shifts. Note that the # outer pixels are 0.165 mm in size. These are excluded from the panel # extents. pnl_data = [] pnl_data.append({'xmin':1, 'ymin':1, 'xmax':255, 'ymax':255, 'xmin_mm': 1 * 0.165, 'ymin_mm': 1 * 0.165}) pnl_data.append({'xmin':257, 'ymin':1, 'xmax':511, 'ymax':255, 'xmin_mm': 3 * 0.165 + (511 - 257) * pixel_size[0], 'ymin_mm': 1 * 0.165}) pnl_data.append({'xmin':1, 'ymin':257, 'xmax':255, 'ymax':511, 'xmin_mm': 1 * 0.165, 'ymin_mm': 3 * 0.165 + (511 - 257) * pixel_size[1]}) pnl_data.append({'xmin':257, 'ymin':257, 'xmax':511, 'ymax':511, 'xmin_mm': 3 * 0.165 + (511 - 257) * pixel_size[0], 'ymin_mm': 3 * 0.165 + (511 - 257) * pixel_size[1]}) # redefine fast, slow for the local frame fast = matrix.col((1.0, 0.0, 0.0)) slow = matrix.col((0.0, 1.0, 0.0)) for ipanel, pd in enumerate(pnl_data): xmin = pd['xmin'] xmax = pd['xmax'] ymin = pd['ymin'] ymax = pd['ymax'] xmin_mm = pd['xmin_mm'] ymin_mm = pd['ymin_mm'] 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(trusted_range) p.set_pixel_size((pixel_size[0], pixel_size[1])) 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 def _beam(self): '''Return an unpolarized beam model.''' wavelength = float(self._header_dictionary['WAVELENGTH']) return self._beam_factory.make_polarized_beam( sample_to_source=(0.0, 0.0, 1.0), wavelength=wavelength, polarization=(0, 1, 0), polarization_fraction=0.5) def _scan(self): '''Return the scan information for this image.''' import calendar format = self._scan_factory.format('SMV') exposure_time = float(self._header_dictionary['TIME']) epoch = None # PST, PDT timezones not recognised by default... epoch = 0 try: date_str = self._header_dictionary['DATE'] date_str = date_str.replace('PST', '').replace('PDT', '') except KeyError: date_str = '' for format_string in ['%a %b %d %H:%M:%S %Y', '%a %b %d %H:%M:%S %Z %Y']: try: epoch = calendar.timegm(time.strptime(date_str, format_string)) break except ValueError: pass # assert(epoch) osc_start = float(self._header_dictionary['OSC_START']) osc_range = float(self._header_dictionary['OSC_RANGE']) return self._scan_factory.single( self._image_file, format, exposure_time, osc_start, osc_range, epoch) def get_raw_data(self): '''Get the pixel intensities (i.e. read the image and return as a flex array of integers.)''' from boost.python import streambuf from dxtbx import read_uint16, read_uint16_bs, is_big_endian from scitbx.array_family import flex f = self.open_file(self._image_file, 'rb') f.read(self._header_size) if self._header_dictionary['BYTE_ORDER'] == 'big_endian': big_endian = True else: big_endian = False if big_endian == is_big_endian(): raw_data = read_uint16(streambuf(f), int(512 * 512)) else: raw_data = read_uint16_bs(streambuf(f), int(512 * 512)) image_size = (512,512) raw_data.reshape(flex.grid(image_size[1], image_size[0])) # split into separate panels self._raw_data = [] d = self.get_detector() for panel in d: xmin, ymin, xmax, ymax = self.coords[panel.get_name()] self._raw_data.append(raw_data[ymin:ymax,xmin:xmax]) return tuple(self._raw_data)