def make_images(data, tag): pixel_size = 0.1 # mm/pixel detector = DetectorFactory.simple( 'PAD', 100, (pixel_size * data.focus()[1] / 2, pixel_size * data.focus()[2] / 2), '+x', '-y', (pixel_size, pixel_size), (data.focus()[2], data.focus()[1]), (-1, 1e6 - 1), [], None) beam = BeamFactory.simple(1.0) sf = ScanFactory() scan = sf.make_scan(image_range=(1, 180), exposure_times=0.1, oscillation=(0, 1.0), epochs=range(180), deg=True) # write images in each of three directions for slice_id in [0, 1, 2]: for idx in xrange(data.focus()[slice_id]): if slice_id == 0: # slow data_slice = data[idx:idx + 1, :, :] data_slice.reshape(flex.grid(data.focus()[1], data.focus()[2])) filename = "fft_frame_%s_mf_%04d.cbf" % (tag, idx) elif slice_id == 1: # med data_slice = data[:, idx:idx + 1, :] data_slice.reshape(flex.grid(data.focus()[0], data.focus()[2])) filename = "fft_frame_%s_sf_%04d.cbf" % (tag, idx) elif slice_id == 2: # fast data_slice = data[:, :, idx:idx + 1] data_slice.reshape(flex.grid(data.focus()[0], data.focus()[1])) filename = "fft_frame_%s_sm_%04d.cbf" % (tag, idx) print['slow', 'med', 'fast'][slice_id], idx FormatCBFMini.as_file(detector, beam, None, scan, data_slice, filename)
def __call__(self, imageset): """ Override the parameters """ from dxtbx.imageset import ImageSequence, ImageSetFactory from dxtbx.model import BeamFactory from dxtbx.model import DetectorFactory from dxtbx.model import GoniometerFactory from dxtbx.model import ScanFactory from copy import deepcopy if self.params.geometry.convert_sequences_to_stills: imageset = ImageSetFactory.imageset_from_anyset(imageset) for j in imageset.indices(): imageset.set_scan(None, j) imageset.set_goniometer(None, j) if not isinstance(imageset, ImageSequence): if self.params.geometry.convert_stills_to_sequences: imageset = self.convert_stills_to_sequence(imageset) if isinstance(imageset, ImageSequence): beam = BeamFactory.from_phil(self.params.geometry, imageset.get_beam()) detector = DetectorFactory.from_phil( self.params.geometry, imageset.get_detector(), beam ) goniometer = GoniometerFactory.from_phil( self.params.geometry, imageset.get_goniometer() ) scan = ScanFactory.from_phil( self.params.geometry, deepcopy(imageset.get_scan()) ) i0, i1 = scan.get_array_range() j0, j1 = imageset.get_scan().get_array_range() if i0 < j0 or i1 > j1: imageset = self.extrapolate_imageset( imageset=imageset, beam=beam, detector=detector, goniometer=goniometer, scan=scan, ) else: imageset.set_beam(beam) imageset.set_detector(detector) imageset.set_goniometer(goniometer) imageset.set_scan(scan) else: for i in range(len(imageset)): beam = BeamFactory.from_phil(self.params.geometry, imageset.get_beam(i)) detector = DetectorFactory.from_phil( self.params.geometry, imageset.get_detector(i), beam ) goniometer = GoniometerFactory.from_phil( self.params.geometry, imageset.get_goniometer(i) ) scan = ScanFactory.from_phil(self.params.geometry, imageset.get_scan(i)) imageset.set_beam(beam, i) imageset.set_detector(detector, i) imageset.set_goniometer(goniometer, i) imageset.set_scan(scan, i) return imageset
def generate_reflections(self): # Build a mock scan for a 3 degree sweep from dxtbx.model import ScanFactory sf = ScanFactory() self.scan = sf.make_scan(image_range=(1, 1), exposure_times=0.1, oscillation=(0, 3.0), epochs=range(1), deg=True) sweep_range = self.scan.get_oscillation_range(deg=False) # Create a scans ExperimentList, only for generating reflections experiments = ExperimentList() experiments.append( Experiment(beam=self.beam, detector=self.detector, goniometer=self.gonio, scan=self.scan, crystal=self.crystal, imageset=None)) # Create a ScansRayPredictor ray_predictor = ScansRayPredictor(experiments, sweep_range) # Generate rays - only to work out which hkls are predicted resolution = 2.0 index_generator = IndexGenerator( self.crystal.get_unit_cell(), space_group(space_group_symbols(1).hall()).type(), resolution) indices = index_generator.to_array() rays = ray_predictor(indices) # Make a standard reflection_table and copy in the ray data self.reflections = flex.reflection_table.empty_standard(len(rays)) self.reflections.update(rays)
def tst_scan(self): from dxtbx.model import Scan, ScanFactory from scitbx.array_family import flex s1 = Scan((1, 3), (1.0, 0.2), flex.double([0.1, 0.1, 0.1]), flex.double([0.1, 0.2, 0.3])) d = s1.to_dict() s2 = ScanFactory.from_dict(d) assert (d['image_range'] == (1, 3)) assert (d['oscillation'] == (1.0, 0.2)) assert (d['exposure_time'] == [0.1, 0.1, 0.1]) assert (d['epochs'] == [0.1, 0.2, 0.3]) assert (s1 == s2) # Test with a template and partial dictionary d2 = {'exposure_time': [0.2, 0.2, 0.2]} s3 = ScanFactory.from_dict(d2, d) assert (s3.get_image_range() == (1, 3)) assert (s3.get_oscillation() == (1.0, 0.2)) assert (list(s3.get_exposure_times()) == [0.2, 0.2, 0.2]) assert (list(s3.get_epochs()) == [0.1, 0.2, 0.3]) assert (s2 != s3) # Test with a partial epoch d3 = {'image_range': (1, 10), 'epochs': [0.1, 0.2]} s4 = ScanFactory.from_dict(d3, d) assert (abs(s4.get_epochs()[2] - 0.3) < 1e-7) assert (abs(s4.get_epochs()[9] - 1.0) < 1e-7) print 'OK'
def __init__(self, override_fdp=None): # Set up detector distance = 100 pixel_size = 0.1 image_size = (1000, 1000) beam_centre_mm = ( pixel_size * image_size[0] / 2, pixel_size * image_size[1] / 2, ) self.detector = DetectorFactory().simple( "CCD", distance, beam_centre_mm, "+x", "-y", (pixel_size, pixel_size), image_size, ) # Set up beam self.beam = BeamFactory().simple(wavelength=1) # Set up scan sequence_width = 90.0 osc_start = 0.0 image_width = 0.2 oscillation = (osc_start, image_width) nframes = int(math.ceil(sequence_width / image_width)) image_range = (1, nframes) exposure_times = 0.0 epochs = [0] * nframes self.scan = ScanFactory().make_scan(image_range, exposure_times, oscillation, epochs, deg=True) # Set up goniometer self.goniometer = GoniometerFactory.known_axis( self.detector[0].get_fast_axis()) # Set up simulated structure factors self.sfall = self.fcalc_from_pdb(resolution=1.6, algorithm="direct", override_fdp=override_fdp) # Set up crystal self.crystal = Crystal( real_space_a=(50, 0, 0), real_space_b=(0, 60, 0), real_space_c=(0, 0, 70), space_group_symbol="P1", ) axis = matrix.col(elems=(-0.14480368275412925, -0.6202131724405818, -0.7709523423610766)) self.crystal.set_U( axis.axis_and_angle_as_r3_rotation_matrix(angle=0.625126343998969))
def create_models(self, cmdline_overrides=None): from dxtbx.model import ScanFactory from libtbx.phil import parse from dials.test.algorithms.refinement.setup_geometry import Extract if cmdline_overrides is None: cmdline_overrides = [] overrides = """geometry.parameters.crystal.a.length.range = 10 50 geometry.parameters.crystal.b.length.range = 10 50 geometry.parameters.crystal.c.length.range = 10 50""" master_phil = parse( """ include scope dials.test.algorithms.refinement.geometry_phil """, process_includes=True, ) # Extract models models = Extract(master_phil, overrides, cmdline_args=cmdline_overrides) self.detector = models.detector self.goniometer = models.goniometer self.crystal = models.crystal self.beam = models.beam # Make a scan of 1-20 * 0.5 deg images sf = ScanFactory() self.scan = sf.make_scan((1, 20), 0.5, (0, 0.5), list(range(20))) # Generate an ExperimentList self.experiments = ExperimentList() self.experiments.append( Experiment( beam=self.beam, detector=self.detector, goniometer=self.goniometer, scan=self.scan, crystal=self.crystal, imageset=None, )) # Create a reflection predictor for the experiments self.ref_predictor = ScansExperimentsPredictor(self.experiments) # Create scan-varying parameterisations of these models, with 3 samples self.det_param = ScanVaryingDetectorParameterisationSinglePanel( self.detector, self.scan.get_array_range(), 3) self.s0_param = ScanVaryingBeamParameterisation( self.beam, self.scan.get_array_range(), 3, self.goniometer) self.xlo_param = ScanVaryingCrystalOrientationParameterisation( self.crystal, self.scan.get_array_range(), 3) self.xluc_param = ScanVaryingCrystalUnitCellParameterisation( self.crystal, self.scan.get_array_range(), 3) self.gon_param = ScanVaryingGoniometerParameterisation( self.goniometer, self.scan.get_array_range(), 3, self.beam)
def __call__(self, imageset): ''' Override the parameters ''' from dxtbx.imageset import ImageSet from dxtbx.imageset import ImageSweep from dxtbx.model import BeamFactory from dxtbx.model import DetectorFactory from dxtbx.model import GoniometerFactory from dxtbx.model import ScanFactory from copy import deepcopy if self.params.geometry.convert_sweeps_to_stills: imageset = ImageSet(reader=imageset.reader()) if not isinstance(imageset, ImageSweep): if self.params.geometry.convert_stills_to_sweeps: imageset = self.convert_stills_to_sweep(imageset) if isinstance(imageset, ImageSweep): beam = BeamFactory.from_phil( self.params.geometry, imageset.get_beam()) detector = DetectorFactory.from_phil( self.params.geometry, imageset.get_detector(), beam) goniometer = GoniometerFactory.from_phil( self.params.geometry, imageset.get_goniometer()) scan = ScanFactory.from_phil( self.params.geometry, deepcopy(imageset.get_scan())) i0, i1 = scan.get_array_range() j0, j1 = imageset.get_scan().get_array_range() imageset.set_beam(beam) imageset.set_detector(detector) imageset.set_goniometer(goniometer) imageset.set_scan(scan) else: for i in range(len(imageset)): beam = BeamFactory.from_phil( self.params.geometry, imageset.get_beam(i)) detector = DetectorFactory.from_phil( self.params.geometry, imageset.get_detector(i), beam) goniometer = GoniometerFactory.from_phil( self.params.geometry, imageset.get_goniometer(i)) scan = ScanFactory.from_phil( self.params.geometry, imageset.get_scan(i)) imageset.set_beam(beam, i) imageset.set_detector(detector, i) imageset.set_goniometer(goniometer, i) imageset.set_scan(scan, i) return imageset
def create_experiments(image_start=1): # Create models from libtbx.phil import parse overrides = """geometry.parameters.crystal.a.length.range = 10 50 geometry.parameters.crystal.b.length.range = 10 50 geometry.parameters.crystal.c.length.range = 10 50""" master_phil = parse( """ include scope dials.test.algorithms.refinement.geometry_phil """, process_includes=True, ) from dials.test.algorithms.refinement.setup_geometry import Extract models = Extract(master_phil, overrides) detector = models.detector goniometer = models.goniometer crystal = models.crystal beam = models.beam # Build a mock scan for a 72 degree sequence from dxtbx.model import ScanFactory sf = ScanFactory() scan = sf.make_scan( image_range=(image_start, image_start + 720 - 1), exposure_times=0.1, oscillation=(0, 0.1), epochs=list(range(720)), deg=True, ) # No matter what image_start is, scan should start at 0.0 and end at 72.0 deg assert scan.get_oscillation_range(deg=True) == (0.0, 72.0) # Create an ExperimentList experiments = ExperimentList() experiments.append( Experiment( beam=beam, detector=detector, goniometer=goniometer, scan=scan, crystal=crystal, imageset=None, ) ) return experiments
def imagesweep_from_dict(d, check_format=True, directory=None): """Construct and image sweep from the dictionary.""" # Get the template (required) template = load_path(str(d["template"]), directory=directory) # If the scan isn't set, find all available files scan_dict = d.get("scan") if scan_dict is None: image_range = None else: image_range = scan_dict.get("image_range") # Set the models with the exisiting models as templates beam = BeamFactory.from_dict(d.get("beam")) goniometer = GoniometerFactory.from_dict(d.get("goniometer")) detector = DetectorFactory.from_dict(d.get("detector")) scan = ScanFactory.from_dict(d.get("scan")) # Construct the sweep try: sweep = ImageSetFactory.from_template( template, image_range, beam=beam, detector=detector, goniometer=goniometer, scan=scan, check_format=check_format, )[0] except Exception: indices = range(image_range[0], image_range[1] + 1) sweep = ImageSetFactory.make_sweep( template, indices, beam=beam, detector=detector, goniometer=goniometer, scan=scan, check_format=check_format, ) # Set some external lookups if "mask" in d and d["mask"] is not None and d["mask"] is not "": path = load_path(d["mask"], directory=directory) with open(path) as infile: sweep.external_lookup.mask.filename = path sweep.external_lookup.mask.data = ImageBool(pickle.load(infile)) if "gain" in d and d["gain"] is not None and d["gain"] is not "": path = load_path(d["gain"], directory=directory) with open(path) as infile: sweep.external_lookup.gain.filename = path sweep.external_lookup.gain.data = ImageDouble(pickle.load(infile)) if "pedestal" in d and d["pedestal"] is not None and d["pedestal"] is not "": path = load_path(d["pedestal"], directory=directory) with open(path) as infile: sweep.external_lookup.pedestal.filename = path sweep.external_lookup.pedestal.data = ImageDouble(pickle.load(infile)) # Return the sweep return sweep
def experiment(): beam = BeamFactory.make_beam(wavelength=0.97625, sample_to_source=(0, 0, 1)) detector = DetectorFactory.simple( sensor="PAD", distance=265.27, beam_centre=(210.7602, 205.27684), fast_direction="+x", slow_direction="-y", pixel_size=(0.172, 0.172), image_size=(2463, 2527), trusted_range=(-1, 1e8), ) goniometer = GoniometerFactory.single_axis() scan = ScanFactory.make_scan( image_range=(1, 20), exposure_times=0.067, oscillation=(82, 0.15), epochs=[0] * 20, ) isetdata = ImageSetData( reader=Format.Reader(None, ["path"] * len(scan)), masker=None ) iset = ImageSequence( isetdata, beam=beam, detector=detector, goniometer=goniometer, scan=scan ) return Experiment( imageset=iset, beam=beam, detector=detector, goniometer=goniometer, scan=scan )
def imagesweep_from_dict(d, check_format=True): '''Construct and image sweep from the dictionary.''' from dxtbx.imageset import ImageSetFactory from dxtbx.model import BeamFactory, DetectorFactory, GoniometerFactory, ScanFactory from dxtbx.serialize.filename import load_path # Get the template (required) template = load_path(str(d['template'])) # If the scan isn't set, find all available files scan_dict = d.get('scan') if scan_dict is None: image_range = None else: image_range = scan_dict.get('image_range') # Set the models with the exisiting models as templates beam = BeamFactory.from_dict(d.get('beam')) goniometer = GoniometerFactory.from_dict(d.get('goniometer')) detector = DetectorFactory.from_dict(d.get('detector')) scan = ScanFactory.from_dict(d.get('scan')) # Construct the sweep try: sweep = ImageSetFactory.from_template(template, image_range, beam=beam, detector=detector, goniometer=goniometer, scan=scan, check_format=check_format)[0] except Exception: indices = range(image_range[0], image_range[1] + 1) sweep = ImageSetFactory.make_sweep(template, indices, beam=beam, detector=detector, goniometer=goniometer, scan=scan, check_format=check_format) # Set some external lookups if 'mask' in d and d['mask'] is not None and d['mask'] is not "": with open(d['mask']) as infile: sweep.external_lookup.mask.filename = d['mask'] sweep.external_lookup.mask.data = ImageBool(pickle.load(infile)) if 'gain' in d and d['gain'] is not None and d['gain'] is not "": with open(d['gain']) as infile: sweep.external_lookup.gain.filename = d['gain'] sweep.external_lookup.gain.data = ImageDouble(pickle.load(infile)) if 'pedestal' in d and d['pedestal'] is not None and d[ 'pedestal'] is not "": with open(d['pedestal']) as infile: sweep.external_lookup.pedestal.filename = d['pedestal'] sweep.external_lookup.pedestal.data = ImageDouble( pickle.load(infile)) # Return the sweep return sweep
def setup_models(args): """setup the experimental models""" # Setup experimental models master_phil = parse( """ include scope dials.test.algorithms.refinement.geometry_phil """, process_includes=True, ) models = setup_geometry.Extract(master_phil, cmdline_args=args) detector = models.detector goniometer = models.goniometer crystal = models.crystal beam = models.beam # Build a mock scan for a 180 degree sequence sf = ScanFactory() scan = sf.make_scan( image_range=(1, 180), exposure_times=0.1, oscillation=(0, 1.0), epochs=list(range(180)), deg=True, ) sequence_range = scan.get_oscillation_range(deg=False) im_width = scan.get_oscillation(deg=False)[1] assert sequence_range == (0.0, math.pi) assert approx_equal(im_width, 1.0 * math.pi / 180.0) experiments = ExperimentList() experiments.append( Experiment( beam=beam, detector=detector, goniometer=goniometer, scan=scan, crystal=crystal, imageset=None, ) ) return experiments
def generate_reflections(self): # Build a mock scan for a 3 degree sequence sf = ScanFactory() self.scan = sf.make_scan( image_range=(1, 1), exposure_times=0.1, oscillation=(0, 3.0), epochs=list(range(1)), deg=True, ) sequence_range = self.scan.get_oscillation_range(deg=False) # Create a scans ExperimentList, only for generating reflections experiments = ExperimentList() experiments.append( Experiment( beam=self.beam, detector=self.detector, goniometer=self.gonio, scan=self.scan, crystal=self.crystal, imageset=None, )) # Create a ScansRayPredictor ray_predictor = ScansRayPredictor(experiments, sequence_range) # Generate rays - only to work out which hkls are predicted resolution = 2.0 index_generator = IndexGenerator( self.crystal.get_unit_cell(), space_group(space_group_symbols(1).hall()).type(), resolution, ) indices = index_generator.to_array() rays = ray_predictor(indices) # Make a standard reflection_table and copy in the ray data self.reflections = flex.reflection_table.empty_standard(len(rays)) self.reflections.update(rays) # Set dummy observed variances to allow statistical weights to be set self.reflections["xyzobs.mm.variance"] += (1e-3, 1e-3, 1e-6)
def _scan(self): """Dummy scan for this image""" alpha = self._header_dictionary.get('alphaTilt', 0.0) dalpha = 1.0 exposure = self._header_dictionary.get('integrationTime', 0.0) fname = os.path.split(self._image_file)[-1] # assume final number before the extension is the image number s = fname.split("_")[-1].split(".")[0] index = int(re.match('.*?([0-9]+)$', s).group(1)) return ScanFactory.make_scan((index, index), exposure, (alpha, dalpha), {index: 0})
def test_extract_experiment_data(): """Test basic operation of the extract_experiment_data function. Does not test extraction of data from scan-varying models""" # Set up an Experiment with idealised geometry from dxtbx.model import BeamFactory from dxtbx.model import GoniometerFactory from dxtbx.model import Crystal from dxtbx.model import ScanFactory from dxtbx.model.experiment_list import Experiment beam = BeamFactory.make_beam(unit_s0=(0, 0, -1), wavelength=1.0) goniometer = GoniometerFactory.known_axis((1, 0, 0)) a = (100, 0, 0) b = (0, 90, 0) c = (0, 0, 80) crystal = Crystal(a, b, c, space_group_symbol="P1") scan = ScanFactory.make_scan( image_range=(1, 91), exposure_times=0.1, oscillation=(0, 1.0), epochs=list(range(91)), deg=True, ) exp = Experiment(beam=beam, goniometer=goniometer, scan=scan, crystal=crystal) # Extract experiment data dat = extract_experiment_data(exp, scale=100) # Check results are as expected za = dat["zone_axes"] # At the first image the c axis is aligned antiparallel with the beam vector, # while the a and b axes are orthogonal. The zone axis calculation is scaled # by 100 (i.e. the max cell dimension, which is the default), therefore we # expect the zone axis [uvw] = [0 0 -100/80] assert za[0].elems == pytest.approx((0, 0, -100 / 80)) # At the start of the 91st image the crystal has rotated by 90 degrees, so # now c is orthogonal to the beam while b is anti-parallel to it. The zone # axis is now expected to be [uvw] = [0 -100/90 0] assert za[-1].elems == pytest.approx((0, -100 / 90, 0)) rsa = dat["real_space_axes"] a, b, c = rsa[0] assert a.elems == pytest.approx(crystal.get_real_space_vectors()[0]) assert b.elems == pytest.approx(crystal.get_real_space_vectors()[1]) assert c.elems == pytest.approx(crystal.get_real_space_vectors()[2])
def test_experimentlist_imagesequence_decode(mocker): # These models are shared between experiments beam = Beam(s0=(0, 0, -1)) detector = Detector() gonio = Goniometer() # Construct the experiment list experiments = ExperimentList() for i in range(3): experiments.append( Experiment( beam=beam, detector=detector, scan=ScanFactory.make_scan( image_range=(i + 1, i + 1), exposure_times=[1], oscillation=(0, 0), epochs=[0], ), goniometer=gonio, )) # Convert experiment list to dict and manually insert a shared imageset d = experiments.to_dict() d["imageset"].append({ "__id__": "ImageSequence", "template": "Puck3_10_1_####.cbf.gz" }) for e in d["experiment"]: e["imageset"] = 0 # Monkeypatch this function as we don't actually have an imageset make_sequence = mocker.patch.object(ExperimentListDict, "_make_sequence") # Ensure that if make_sequence is called more than once it returns a different # value each time make_sequence.side_effect = lambda *args, **kwargs: mocker.MagicMock() # Decode the dict to get a new experiment list experiments2 = ExperimentListDict(d).decode() # This function should only be called once per imageset make_sequence.assert_called_once() # Verify that this experiment is as we expect assert len(experiments2) == 3 assert len(experiments2.imagesets()) == 1 assert len(experiments2.goniometers()) == 1 assert len(experiments2.detectors()) == 1 assert len(experiments2.beams()) == 1 assert len(experiments2.scans()) == 3 for expt in experiments2: assert expt.imageset is experiments2.imagesets()[0]
def import_geometry(xds_inp=None, dials_json=None): assert (xds_inp, dials_json).count(None) == 1 geom_kwds = set([ "DIRECTION_OF_DETECTOR_X-AXIS", "DIRECTION_OF_DETECTOR_Y-AXIS", "DETECTOR_DISTANCE", "ORGX", "ORGY", "ROTATION_AXIS", # "X-RAY_WAVELENGTH", "INCIDENT_BEAM_DIRECTION", "SEGMENT", "DIRECTION_OF_SEGMENT_X-AXIS", "DIRECTION_OF_SEGMENT_Y-AXIS", "SEGMENT_DISTANCE", "SEGMENT_ORGX", "SEGMENT_ORGY" ]) # FIXME in case of multi-segment detector.. if xds_inp: inp = get_xdsinp_keyword(xds_inp) inp = filter(lambda x: x[0] in geom_kwds, inp) return map(lambda x: "%s= %s" % x, inp) elif dials_json: import dxtbx.imageset from dxtbx.serialize.load import _decode_dict from dxtbx.model import BeamFactory from dxtbx.model import DetectorFactory from dxtbx.model import GoniometerFactory from dxtbx.model import ScanFactory from dxtbx.serialize.xds import to_xds j = json.loads(open(dials_json).read(), object_hook=_decode_dict) # dummy sweep = dxtbx.imageset.ImageSetFactory.from_template( "####", image_range=[1, 1], check_format=False)[0] sweep.set_detector(DetectorFactory.from_dict(j["detector"][0])) sweep.set_beam(BeamFactory.from_dict(j["beam"][0])) sweep.set_goniometer(GoniometerFactory.from_dict(j["goniometer"][0])) sweep.set_scan( ScanFactory.make_scan(image_range=[1, 1], exposure_times=[1], oscillation=[1, 2], epochs=[0])) # dummy sio = cStringIO.StringIO() to_xds(sweep).XDS_INP(sio) inp = get_xdsinp_keyword(inp_str=sio.getvalue()) inp = filter(lambda x: x[0] in geom_kwds, inp) return map(lambda x: "%s= %s" % x, inp) return []
def test_scan(): from dxtbx.model import Scan, ScanFactory from scitbx.array_family import flex s1 = Scan((1, 3), (1.0, 0.2), flex.double([0.1, 0.1, 0.1]), flex.double([0.1, 0.2, 0.3]), 0) d = s1.to_dict() s2 = ScanFactory.from_dict(d) assert d['image_range'] == (1, 3) assert d['oscillation'] == (1.0, 0.2) assert d['exposure_time'] == [0.1, 0.1, 0.1] assert d['epochs'] == [0.1, 0.2, 0.3] assert d['batch_offset'] == 0 assert s1 == s2 # Test with a template and partial dictionary d2 = {'exposure_time': [0.2, 0.2, 0.2]} s3 = ScanFactory.from_dict(d2, d) assert s3.get_image_range() == (1, 3) assert s3.get_oscillation() == (1.0, 0.2) assert list(s3.get_exposure_times()) == [0.2, 0.2, 0.2] assert list(s3.get_epochs()) == [0.1, 0.2, 0.3] assert s2 != s3 # Test with a partial epoch d3 = { 'image_range': (1, 10), 'epochs': [0.1, 0.2], } s4 = ScanFactory.from_dict(d3, d) assert s4.get_epochs()[2] == pytest.approx(0.3) assert s4.get_epochs()[9] == pytest.approx(1.0) d4 = {'batch_offset': 100} s5 = ScanFactory.from_dict(d4, d) assert s5.get_batch_offset() == 100 assert s5.get_batch_range() == (101, 103)
def test_scan(): s1 = Scan( (1, 3), (1.0, 0.2), flex.double([0.1, 0.1, 0.1]), flex.double([0.1, 0.2, 0.3]), 0, ) d = s1.to_dict() s2 = ScanFactory.from_dict(d) assert d["image_range"] == (1, 3) assert d["oscillation"] == (1.0, 0.2) assert d["exposure_time"] == [0.1, 0.1, 0.1] assert d["epochs"] == [0.1, 0.2, 0.3] assert d["batch_offset"] == 0 assert s1 == s2 # Test with a template and partial dictionary d2 = {"exposure_time": [0.2, 0.2, 0.2]} s3 = ScanFactory.from_dict(d2, d) assert s3.get_image_range() == (1, 3) assert s3.get_oscillation() == (1.0, 0.2) assert list(s3.get_exposure_times()) == [0.2, 0.2, 0.2] assert list(s3.get_epochs()) == [0.1, 0.2, 0.3] assert s2 != s3 # Test with a partial epoch d3 = {"image_range": (1, 10), "epochs": [0.1, 0.2]} s4 = ScanFactory.from_dict(d3, d) assert s4.get_epochs()[2] == pytest.approx(0.3) assert s4.get_epochs()[9] == pytest.approx(1.0) d4 = {"batch_offset": 100} s5 = ScanFactory.from_dict(d4, d) assert s5.get_batch_offset() == 100 assert s5.get_batch_range() == (101, 103)
def _scan(self): """Dummy scan for this image""" format = self._scan_factory.format("CBF") exposure_time = float( self._cif_header_dictionary["Exposure_period"].split()[0]) fname = os.path.split(self._image_file)[-1] index = int(fname.split("_")[-1].split(".")[0]) return ScanFactory.make_scan( image_range=(index, index), exposure_times=exposure_time, oscillation=(0, 1), epochs={index: 0}, )
def _scan(self): """Scan model for this image, filling out any unavailable items with dummy values""" alpha = self._header_dictionary.get("alphaTilt", 0.0) dalpha = self._header_dictionary.get("tiltPerImage", 1.0) exposure = self._header_dictionary.get("integrationTime", 0.0) oscillation = (alpha, dalpha) fname = os.path.split(self._image_file)[-1] # assume that the final number before the extension is the image number s = fname.split("_")[-1].split(".")[0] try: index = int(re.match(".*?([0-9]+)$", s).group(1)) except AttributeError: index = 1 return ScanFactory.make_scan((index, index), exposure, oscillation, {index: 0})
def load_models(obj): try: beam = BeamFactory.from_dict(blist[obj['beam']]) except Exception: beam = None try: dobj = dlist[obj['detector']] detector = DetectorFactory.from_dict(dobj) except Exception: detector = None try: gonio = GoniometerFactory.from_dict(glist[obj['goniometer']]) except Exception: gonio = None try: scan = ScanFactory.from_dict(slist[obj['scan']]) except Exception: scan = None return beam, detector, gonio, scan
geometry.parameters.crystal.a.length.range=40 50; geometry.parameters.crystal.b.length.range=40 50; geometry.parameters.crystal.c.length.range=40 50; geometry.parameters.random_seed = 42""" models = setup_geometry.Extract(master_phil, cmdline_args=args, local_overrides=param) crystal = models.crystal mydetector = models.detector mygonio = models.goniometer mybeam = models.beam # Build a mock scan for a 1.5 degree wedge. Only used for generating indices near # the Ewald sphere sf = ScanFactory() myscan = sf.make_scan(image_range=(1, 1), exposure_times=0.1, oscillation=(0, 1.5), epochs=range(1), deg=True) sweep_range = myscan.get_oscillation_range(deg=False) im_width = myscan.get_oscillation(deg=False)[1] assert approx_equal(im_width, 1.5 * pi / 180.) # Build experiment lists stills_experiments = ExperimentList() stills_experiments.append( Experiment(beam=mybeam, detector=mydetector, crystal=crystal,
def test_fd_derivatives(): """Test derivatives of the prediction equation""" from libtbx.phil import parse # Import model builder from dials.test.algorithms.refinement.setup_geometry import Extract # Create models overrides = """geometry.parameters.crystal.a.length.range = 10 50 geometry.parameters.crystal.b.length.range = 10 50 geometry.parameters.crystal.c.length.range = 10 50""" master_phil = parse( """ include scope dials.test.algorithms.refinement.geometry_phil """, process_includes=True, ) models = Extract(master_phil, overrides) mydetector = models.detector mygonio = models.goniometer mycrystal = models.crystal mybeam = models.beam # Build a mock scan for a 72 degree sequence from dxtbx.model import ScanFactory sf = ScanFactory() myscan = sf.make_scan( image_range=(1, 720), exposure_times=0.1, oscillation=(0, 0.1), epochs=list(range(720)), deg=True, ) # Create a parameterisation of the crystal unit cell from dials.algorithms.refinement.parameterisation.crystal_parameters import ( CrystalUnitCellParameterisation, ) xluc_param = CrystalUnitCellParameterisation(mycrystal) # Create an ExperimentList experiments = ExperimentList() experiments.append( Experiment( beam=mybeam, detector=mydetector, goniometer=mygonio, scan=myscan, crystal=mycrystal, imageset=None, )) # Build a prediction parameterisation for two theta prediction pred_param = TwoThetaPredictionParameterisation( experiments, detector_parameterisations=None, beam_parameterisations=None, xl_orientation_parameterisations=None, xl_unit_cell_parameterisations=[xluc_param], ) # Generate some reflections obs_refs, ref_predictor = generate_reflections(experiments) # Build a ReflectionManager with overloads for handling 2theta residuals refman = TwoThetaReflectionManager(obs_refs, experiments, outlier_detector=None) # Build a TwoThetaExperimentsPredictor ref_predictor = TwoThetaExperimentsPredictor(experiments) # Make a target for the least squares 2theta residual target = TwoThetaTarget(experiments, ref_predictor, refman, pred_param) # Keep only reflections that pass inclusion criteria and have predictions reflections = refman.get_matches() # Get analytical gradients an_grads = pred_param.get_gradients(reflections) # Get finite difference gradients p_vals = pred_param.get_param_vals() deltas = [1.0e-7] * len(p_vals) for i in range(len(deltas)): val = p_vals[i] p_vals[i] -= deltas[i] / 2.0 pred_param.set_param_vals(p_vals) target.predict() reflections = refman.get_matches() rev_state = reflections["2theta_resid"].deep_copy() p_vals[i] += deltas[i] pred_param.set_param_vals(p_vals) target.predict() reflections = refman.get_matches() fwd_state = reflections["2theta_resid"].deep_copy() p_vals[i] = val fd = fwd_state - rev_state fd /= deltas[i] # compare with analytical calculation assert approx_equal(fd, an_grads[i]["d2theta_dp"], eps=1.0e-6) # return to the initial state pred_param.set_param_vals(p_vals)
def test_refinement(dials_regression): """Test a refinement run""" # Get a beam and detector from a experiments. This one has a CS-PAD, but that # is irrelevant data_dir = os.path.join(dials_regression, "refinement_test_data", "hierarchy_test") experiments_path = os.path.join(data_dir, "datablock.json") assert os.path.exists(experiments_path) # load models from dxtbx.model.experiment_list import ExperimentListFactory experiments = ExperimentListFactory.from_serialized_format( experiments_path, check_format=False) im_set = experiments.imagesets()[0] detector = deepcopy(im_set.get_detector()) beam = im_set.get_beam() # Invent a crystal, goniometer and scan for this test from dxtbx.model import Crystal crystal = Crystal((40.0, 0.0, 0.0), (0.0, 40.0, 0.0), (0.0, 0.0, 40.0), space_group_symbol="P1") orig_xl = deepcopy(crystal) from dxtbx.model import GoniometerFactory goniometer = GoniometerFactory.known_axis((1.0, 0.0, 0.0)) # Build a mock scan for a 180 degree sequence from dxtbx.model import ScanFactory sf = ScanFactory() scan = sf.make_scan( image_range=(1, 1800), exposure_times=0.1, oscillation=(0, 0.1), epochs=list(range(1800)), deg=True, ) sequence_range = scan.get_oscillation_range(deg=False) im_width = scan.get_oscillation(deg=False)[1] assert sequence_range == (0.0, pi) assert approx_equal(im_width, 0.1 * pi / 180.0) # Build an experiment list experiments = ExperimentList() experiments.append( Experiment( beam=beam, detector=detector, goniometer=goniometer, scan=scan, crystal=crystal, imageset=None, )) # simulate some reflections refs, _ = generate_reflections(experiments) # change unit cell a bit (=0.1 Angstrom length upsets, 0.1 degree of # alpha and beta angles) from dials.algorithms.refinement.parameterisation.crystal_parameters import ( CrystalUnitCellParameterisation, ) xluc_param = CrystalUnitCellParameterisation(crystal) cell_params = crystal.get_unit_cell().parameters() cell_params = [ a + b for a, b in zip(cell_params, [0.1, -0.1, 0.1, 0.1, -0.1, 0.0]) ] from cctbx.uctbx import unit_cell from rstbx.symmetry.constraints.parameter_reduction import symmetrize_reduce_enlarge from scitbx import matrix new_uc = unit_cell(cell_params) newB = matrix.sqr(new_uc.fractionalization_matrix()).transpose() S = symmetrize_reduce_enlarge(crystal.get_space_group()) S.set_orientation(orientation=newB) X = tuple([e * 1.0e5 for e in S.forward_independent_parameters()]) xluc_param.set_param_vals(X) # reparameterise the crystal at the perturbed geometry xluc_param = CrystalUnitCellParameterisation(crystal) # Dummy parameterisations for other models beam_param = None xlo_param = None det_param = None # parameterisation of the prediction equation from dials.algorithms.refinement.parameterisation.parameter_report import ( ParameterReporter, ) pred_param = TwoThetaPredictionParameterisation(experiments, det_param, beam_param, xlo_param, [xluc_param]) param_reporter = ParameterReporter(det_param, beam_param, xlo_param, [xluc_param]) # reflection manager refman = TwoThetaReflectionManager(refs, experiments, nref_per_degree=20) # reflection predictor ref_predictor = TwoThetaExperimentsPredictor(experiments) # target function target = TwoThetaTarget(experiments, ref_predictor, refman, pred_param) # minimisation engine from dials.algorithms.refinement.engine import ( LevenbergMarquardtIterations as Refinery, ) refinery = Refinery( target=target, prediction_parameterisation=pred_param, log=None, max_iterations=20, ) # Refiner from dials.algorithms.refinement.refiner import Refiner refiner = Refiner( experiments=experiments, pred_param=pred_param, param_reporter=param_reporter, refman=refman, target=target, refinery=refinery, ) refiner.run() # compare crystal with original crystal refined_xl = refiner.get_experiments()[0].crystal # print refined_xl assert refined_xl.is_similar_to(orig_xl, uc_rel_length_tolerance=0.001, uc_abs_angle_tolerance=0.01)
def test(): # Build models, with a larger crystal than default in order to get plenty of # reflections on the 'still' image overrides = """ geometry.parameters.crystal.a.length.range=40 50; geometry.parameters.crystal.b.length.range=40 50; geometry.parameters.crystal.c.length.range=40 50; geometry.parameters.random_seed = 42""" master_phil = parse( """ include scope dials.test.algorithms.refinement.geometry_phil """, process_includes=True, ) models = Extract(master_phil, overrides) mydetector = models.detector mygonio = models.goniometer mycrystal = models.crystal mybeam = models.beam # Build a mock scan for a 3 degree sweep from dxtbx.model import ScanFactory sf = ScanFactory() myscan = sf.make_scan( image_range=(1, 1), exposure_times=0.1, oscillation=(0, 3.0), epochs=list(range(1)), deg=True, ) sweep_range = myscan.get_oscillation_range(deg=False) # Create parameterisations of these models det_param = DetectorParameterisationSinglePanel(mydetector) s0_param = BeamParameterisation(mybeam, mygonio) xlo_param = CrystalOrientationParameterisation(mycrystal) xluc_param = CrystalUnitCellParameterisation(mycrystal) # Create a scans ExperimentList, only for generating reflections experiments = ExperimentList() experiments.append( Experiment( beam=mybeam, detector=mydetector, goniometer=mygonio, scan=myscan, crystal=mycrystal, imageset=None, )) # Create a stills ExperimentList stills_experiments = ExperimentList() stills_experiments.append( Experiment(beam=mybeam, detector=mydetector, crystal=mycrystal, imageset=None)) # Generate rays - only to work out which hkls are predicted ray_predictor = ScansRayPredictor(experiments, sweep_range) resolution = 2.0 index_generator = IndexGenerator( mycrystal.get_unit_cell(), space_group(space_group_symbols(1).hall()).type(), resolution, ) indices = index_generator.to_array() rays = ray_predictor(indices) # Make a standard reflection_table and copy in the ray data reflections = flex.reflection_table.empty_standard(len(rays)) reflections.update(rays) # Build a standard prediction parameterisation for the stills experiment to do # FD calculation (not used for its analytical gradients) pred_param = StillsPredictionParameterisation( stills_experiments, detector_parameterisations=[det_param], beam_parameterisations=[s0_param], xl_orientation_parameterisations=[xlo_param], xl_unit_cell_parameterisations=[xluc_param], ) # Make a managed SphericalRelpStillsReflectionPredictor reflection predictor # for the first (only) experiment ref_predictor = Predictor(stills_experiments) # Predict these reflections in place. Must do this ahead of calculating # the analytical gradients so quantities like s1 are correct ref_predictor.update() ref_predictor.predict(reflections) # calculate analytical gradients ag = AnalyticalGradients( stills_experiments, detector_parameterisation=det_param, beam_parameterisation=s0_param, xl_orientation_parameterisation=xlo_param, xl_unit_cell_parameterisation=xluc_param, ) an_grads = ag.get_beam_gradients(reflections) an_grads.update(ag.get_crystal_orientation_gradients(reflections)) an_grads.update(ag.get_crystal_unit_cell_gradients(reflections)) # get finite difference gradients p_vals = pred_param.get_param_vals() deltas = [1.0e-7] * len(p_vals) fd_grads = [] p_names = pred_param.get_param_names() for i, delta in enumerate(deltas): # save parameter value val = p_vals[i] # calc reverse state p_vals[i] -= delta / 2.0 pred_param.set_param_vals(p_vals) ref_predictor.update() ref_predictor.predict(reflections) x, y, _ = reflections["xyzcal.mm"].deep_copy().parts() s1 = reflections["s1"].deep_copy() rev_state = s1 # calc forward state p_vals[i] += delta pred_param.set_param_vals(p_vals) ref_predictor.update() ref_predictor.predict(reflections) x, y, _ = reflections["xyzcal.mm"].deep_copy().parts() s1 = reflections["s1"].deep_copy() fwd_state = s1 # reset parameter to saved value p_vals[i] = val # finite difference - currently for s1 only fd = fwd_state - rev_state inv_delta = 1.0 / delta s1_grads = fd * inv_delta # store gradients fd_grads.append({"name": p_names[i], "ds1": s1_grads}) # return to the initial state pred_param.set_param_vals(p_vals) for i, fd_grad in enumerate(fd_grads): ## compare FD with analytical calculations print("\n\nParameter {0}: {1}".format(i, fd_grad["name"])) print("d[s1]/dp for the first reflection") print("finite diff", fd_grad["ds1"][0]) try: an_grad = an_grads[fd_grad["name"]] except KeyError: continue print("checking analytical vs finite difference gradients for s1") for a, b in zip(fd_grad["ds1"], an_grad["ds1"]): assert a == pytest.approx(b, abs=1e-7)
class Simulation(object): def __init__(self, override_fdp=None): # Set up detector distance = 100 pixel_size = 0.1 image_size = (1000, 1000) beam_centre_mm = ( pixel_size * image_size[0] / 2, pixel_size * image_size[1] / 2, ) self.detector = DetectorFactory().simple( "CCD", distance, beam_centre_mm, "+x", "-y", (pixel_size, pixel_size), image_size, ) # Set up beam self.beam = BeamFactory().simple(wavelength=1) # Set up scan sequence_width = 90.0 osc_start = 0.0 image_width = 0.2 oscillation = (osc_start, image_width) nframes = int(math.ceil(sequence_width / image_width)) image_range = (1, nframes) exposure_times = 0.0 epochs = [0] * nframes self.scan = ScanFactory().make_scan( image_range, exposure_times, oscillation, epochs, deg=True ) # Set up goniometer self.goniometer = GoniometerFactory.known_axis(self.detector[0].get_fast_axis()) # Set up simulated structure factors self.sfall = self.fcalc_from_pdb( resolution=1.6, algorithm="direct", override_fdp=override_fdp ) # Set up crystal self.crystal = Crystal( real_space_a=(50, 0, 0), real_space_b=(0, 60, 0), real_space_c=(0, 0, 70), space_group_symbol="P1", ) axis = matrix.col( elems=(-0.14480368275412925, -0.6202131724405818, -0.7709523423610766) ) self.crystal.set_U( axis.axis_and_angle_as_r3_rotation_matrix(angle=0.625126343998969) ) def fcalc_from_pdb(self, resolution, algorithm=None, override_fdp=None): pdb_inp = pdb.input(source_info=None, lines=_pdb_lines) xray_structure = pdb_inp.xray_structure_simple() wavelength = self.beam.get_wavelength() # # take a detour to calculate anomalous contribution of every atom scatterers = xray_structure.scatterers() for sc in scatterers: expected_henke = henke.table(sc.element_symbol()).at_angstrom(wavelength) sc.fp = expected_henke.fp() sc.fdp = override_fdp if override_fdp is not None else expected_henke.fdp() # how do we do bulk solvent? primitive_xray_structure = xray_structure.primitive_setting() P1_primitive_xray_structure = primitive_xray_structure.expand_to_p1() fcalc = P1_primitive_xray_structure.structure_factors( d_min=resolution, anomalous_flag=True, algorithm=algorithm ).f_calc() return fcalc.amplitudes() def set_varying_beam(self, along="fast", npixels_drift=5): assert along in ["fast", "slow", "both"] num_scan_points = self.scan.get_num_images() + 1 s0 = matrix.col(self.beam.get_s0()) beam_centre_px = self.detector[0].get_beam_centre_px(s0) if along == "fast": start_beam_centre = ( beam_centre_px[0] - npixels_drift / 2, beam_centre_px[1], ) end_beam_centre = (beam_centre_px[0] + npixels_drift / 2, beam_centre_px[1]) elif along == "slow": start_beam_centre = ( beam_centre_px[0], beam_centre_px[1] - npixels_drift / 2, ) end_beam_centre = (beam_centre_px[0], beam_centre_px[1] + npixels_drift / 2) elif along == "both": offset = math.sqrt(2.0) * npixels_drift / 4.0 start_beam_centre = (beam_centre_px[0] - offset, beam_centre_px[1] - offset) end_beam_centre = (beam_centre_px[0] + offset, beam_centre_px[1] + offset) start_lab = matrix.col(self.detector[0].get_pixel_lab_coord(start_beam_centre)) end_lab = matrix.col(self.detector[0].get_pixel_lab_coord(end_beam_centre)) axis = start_lab.cross(end_lab).normalize() full_angle = start_lab.angle(end_lab) angle_step = full_angle / self.scan.get_num_images() angles = [e * angle_step for e in range(num_scan_points)] start_s0 = start_lab.normalize() * s0.length() s0_list = [start_s0.rotate_around_origin(axis=axis, angle=e) for e in angles] self.beam.set_s0_at_scan_points(s0_list)
def test2(): """Test on simulated data""" # Get models for reflection prediction import dials.test.algorithms.refinement.setup_geometry as setup_geometry from libtbx.phil import parse overrides = """geometry.parameters.crystal.a.length.value = 77 geometry.parameters.crystal.b.length.value = 77 geometry.parameters.crystal.c.length.value = 37""" master_phil = parse( """ include scope dials.test.algorithms.refinement.geometry_phil """, process_includes=True, ) from dxtbx.model import Crystal models = setup_geometry.Extract(master_phil) crystal = Crystal( real_space_a=(2.62783398111729, -63.387215823567125, -45.751375737456975), real_space_b=(15.246640559660356, -44.48254330406616, 62.50501032727026), real_space_c=(-76.67246874451074, -11.01804131886244, 10.861322446352226), space_group_symbol="I 2 3", ) detector = models.detector goniometer = models.goniometer beam = models.beam # Build a mock scan for a 180 degree sweep from dxtbx.model import ScanFactory sf = ScanFactory() scan = sf.make_scan( image_range=(1, 1800), exposure_times=0.1, oscillation=(0, 0.1), epochs=range(1800), deg=True, ) # Build an experiment list from dxtbx.model.experiment_list import ExperimentList, Experiment experiments = ExperimentList() experiments.append( Experiment( beam=beam, detector=detector, goniometer=goniometer, scan=scan, crystal=crystal, imageset=None, )) # Generate all indices in a 1.5 Angstrom sphere from dials.algorithms.spot_prediction import IndexGenerator from cctbx.sgtbx import space_group, space_group_symbols resolution = 1.5 index_generator = IndexGenerator( crystal.get_unit_cell(), space_group(space_group_symbols(1).hall()).type(), resolution, ) indices = index_generator.to_array() # Predict rays within the sweep range from dials.algorithms.refinement.prediction import ScansRayPredictor sweep_range = scan.get_oscillation_range(deg=False) ray_predictor = ScansRayPredictor(experiments, sweep_range) obs_refs = ray_predictor(indices) # Take only those rays that intersect the detector from dials.algorithms.spot_prediction import ray_intersection intersects = ray_intersection(detector, obs_refs) obs_refs = obs_refs.select(intersects) # Make a reflection predictor and re-predict for all these reflections. The # result is the same, but we gain also the flags and xyzcal.px columns from dials.algorithms.refinement.prediction import ExperimentsPredictor ref_predictor = ExperimentsPredictor(experiments) obs_refs["id"] = flex.int(len(obs_refs), 0) obs_refs = ref_predictor(obs_refs) # Copy 'observed' centroids from the predicted ones, applying sinusoidal # offsets obs_x, obs_y, obs_z = obs_refs["xyzcal.mm"].parts() # obs_z is in range (0, pi). Calculate offsets for phi at twice that # frequency im_width = scan.get_oscillation(deg=False)[1] z_off = flex.sin(2 * obs_z) * im_width obs_z += z_off # Calculate offsets for x pixel_size = detector[0].get_pixel_size() x_off = flex.sin(20 * obs_z) * pixel_size[0] # Calculate offsets for y with a phase-shifted sine wave from math import pi y_off = flex.sin(4 * obs_z + pi / 6) * pixel_size[1] # Incorporate the offsets into the 'observed' centroids obs_z += z_off obs_x += x_off obs_y += y_off obs_refs["xyzobs.mm.value"] = flex.vec3_double(obs_x, obs_y, obs_z) # Now do centroid analysis of the residuals results = CentroidAnalyser(obs_refs, debug=True)() # FIXME this test shows that the suggested interval width heuristic is not # yet robust. This simulation function seems a useful direction to proceed # in though raise RuntimeError("test2 failed") print("OK") return
def test(): from cctbx.sgtbx import space_group, space_group_symbols # We will set up a mock scan from dxtbx.model import ScanFactory from dxtbx.model.experiment_list import Experiment, ExperimentList from libtbx.phil import parse from scitbx import matrix from scitbx.array_family import flex from dials.algorithms.refinement.prediction.managed_predictors import ( ScansExperimentsPredictor, ScansRayPredictor, ) # Reflection prediction from dials.algorithms.spot_prediction import IndexGenerator # Building experimental models from dials.test.algorithms.refinement.setup_geometry import Extract master_phil = parse( """ include scope dials.test.algorithms.refinement.geometry_phil include scope dials.test.algorithms.refinement.minimiser_phil """, process_includes=True, ) overrides = """geometry.parameters.crystal.a.length.range = 10 50 geometry.parameters.crystal.b.length.range = 10 50 geometry.parameters.crystal.c.length.range = 10 50""" models = Extract(master_phil, local_overrides=overrides) mydetector = models.detector mygonio = models.goniometer mycrystal = models.crystal mybeam = models.beam ############################# # Generate some reflections # ############################# # All indices in a 2.0 Angstrom sphere resolution = 2.0 index_generator = IndexGenerator( mycrystal.get_unit_cell(), space_group(space_group_symbols(1).hall()).type(), resolution, ) indices = index_generator.to_array() # Build a mock scan for a 30 degree sequence sf = ScanFactory() myscan = sf.make_scan( image_range=(1, 300), exposure_times=0.1, oscillation=(0, 0.1), epochs=list(range(300)), deg=True, ) sequence_range = myscan.get_oscillation_range(deg=False) assert sequence_range == pytest.approx((0.0, math.pi / 6.0)) im_width = myscan.get_oscillation(deg=False)[1] assert im_width == pytest.approx(0.1 * math.pi / 180.0) # Create an ExperimentList for ScansRayPredictor experiments = ExperimentList() experiments.append( Experiment( beam=mybeam, detector=mydetector, goniometer=mygonio, scan=myscan, crystal=mycrystal, imageset=None, )) # Select those that are excited in a 30 degree sequence and get angles ray_predictor = ScansRayPredictor(experiments, sequence_range) obs_refs = ray_predictor(indices) # Set the experiment number obs_refs["id"] = flex.int(len(obs_refs), 0) # Calculate intersections ref_predictor = ScansExperimentsPredictor(experiments) obs_refs = ref_predictor(obs_refs) print("Total number of observations made", len(obs_refs)) s0 = matrix.col(mybeam.get_s0()) spindle = matrix.col(mygonio.get_rotation_axis()) for ref in obs_refs.rows(): # get the s1 vector of this reflection s1 = matrix.col(ref["s1"]) r = s1 - s0 r_orig = r.rotate_around_origin(spindle, -1.0, deg=True) # is it outside the Ewald sphere (i.e. entering)? test = (s0 + r_orig).length() > s0.length() assert ref["entering"] == test
def _scan_from_dict(obj): ''' Get the scan from a dictionary. ''' from dxtbx.model import ScanFactory return ScanFactory.from_dict(obj)