def __init__(self, plots = False): # Do we make scatterplots? self.do_plots = plots # Let's say we have a scan of 100 images self.image_range = (1, 100) # Make a random P1 crystal a = random.uniform(10,50) * \ self.random_direction_close_to(matrix.col((1, 0, 0))) b = random.uniform(10,50) * \ self.random_direction_close_to(matrix.col((0, 1, 0))) c = random.uniform(10,50) * \ self.random_direction_close_to(matrix.col((0, 0, 1))) self.xl = crystal_model(a, b, c, space_group_symbol = "P 1") # Make a beam with wavelength in the range 0.8--1.2 and s0 direction close # to 0,0,1 s0 = random.uniform(0.8, 1.2) * \ self.random_direction_close_to(matrix.col((0, 0, 1))) self.beam = Beam(s0) # Make a standard goniometer model along X self.goniometer = Goniometer((1,0,0)) # Make a simple single panel detector d1 = matrix.col((1, 0, 0)) d2 = matrix.col((0, -1, 0)) npx_fast = 1475 npx_slow = 1679 pix_size_f = pix_size_s = 0.172 from dxtbx.model.experiment import detector_factory self.detector = detector_factory.make_detector("PAD", d1, d2, matrix.col((0, 0, -110)), (pix_size_f, pix_size_s), (npx_fast, npx_slow), (0, 2e20))
def test_elliptical_distortion(run_in_tmpdir): """Create distortion maps for elliptical distortion using a dummy experiments with a small detector, for speed. Check those maps seem sensible""" # Make a detector model d = make_detector() # The beam is also essential for a experiments to be serialisable b = Beam((0, 0, 1), 1.0) # Create and write out a experiments imageset = ImageSet(ImageSetData(Reader(None, ["non-existent.cbf"]), None)) imageset.set_detector(d) imageset.set_beam(b) experiments = ExperimentListFactory.from_imageset_and_crystal( imageset, None) experiments.as_json("dummy.expt") # Centre of distortion will be the far corner from the origin of the first # panel centre_xy = d[0].get_image_size_mm() # Generate distortion maps cmd = ("dials.generate_distortion_maps dummy.expt " "mode=ellipse centre_xy={},{} " "phi=0 l1=1.0 l2=0.95").format(*centre_xy) easy_run.fully_buffered(command=cmd).raise_if_errors() # Load the maps with open("dx.pickle", "rb") as f: dx = pickle.load(f) with open("dy.pickle", "rb") as f: dy = pickle.load(f) # Check there are 4 maps each assert len(dx) == len(dy) == 4 # Ellipse has phi=0, so all correction is in the dy map for arr in dx: assert min(arr) == max(arr) == 0.0 # The ellipse correction is centred at the middle of the detector and all in # the Y direction. Therefore we expect a few things from the dy maps: # # (1) Within each panel the columns of the array are identical. # (2) The two upper panels should be the same # (3) The two lower panels should be the same. # (4) One column from an upper panel is a negated, reversed column from a # lower panel. # # All together expect the 4 dy maps to look something like this: # # /-----------\ /-----------\ # |-3 -3 -3 -3| |-3 -3 -3 -3| # |-2 -2 -2 -2| |-2 -2 -2 -2| # |-1 -1 -1 -1| |-1 -1 -1 -1| # | 0 0 0 0| | 0 0 0 0| # \-----------/ \-----------/ # /-----------\ /-----------\ # | 0 0 0 0| | 0 0 0 0| # | 1 1 1 1| | 1 1 1 1| # | 2 2 2 2| | 2 2 2 2| # | 3 3 3 3| | 3 3 3 3| # \-----------/ \-----------/ # So the fundamental data is all in the first column of first panel's map col0 = dy[0].matrix_copy_column(0) # The correction should be 5% of the distance from the ellipse centre to a # corrected pixel (l2 = 0.95 above) along the slow axis. Check that is the # case (for the first pixel at least) vec_centre_to_first_px = matrix.col(d[0].get_pixel_lab_coord( (0.5, 0.5))) - matrix.col(d[0].get_lab_coord(centre_xy)) dist_centre_to_first_px = vec_centre_to_first_px.dot( matrix.col(d[0].get_slow_axis())) corr_mm = dist_centre_to_first_px * 0.05 corr_px = corr_mm / d[0].get_pixel_size()[1] assert col0[0] == pytest.approx(corr_px) # Test (1) from above list for panel 0 for i in range(1, 50): assert (col0 == dy[0].matrix_copy_column(i)).all_eq(True) # Test (2) assert (dy[0] == dy[1]).all_eq(True) # Test (3) assert (dy[2] == dy[3]).all_eq(True) # Test (4) assert col0 == pytest.approx(-1.0 * dy[2].matrix_copy_column(0).reversed()) # Test (1) for panel 2 as well, which then covers everything needed col0 = dy[2].matrix_copy_column(0) for i in range(1, 50): assert (col0 == dy[2].matrix_copy_column(i)).all_eq(True)