def get_maxima(self, threshold=5.0): '''Run diffdump, printpeaks to get a list of diffraction maxima at their image positions, to allow for further analysis.''' if not self._image: raise RuntimeError('image not set') if not os.path.exists(self._image): raise RuntimeError('image %s does not exist' % \ self._image) dd = Diffdump() dd.set_image(self._image) header = dd.readheader() beam = header['raw_beam'] pixel = header['pixel'] template, directory = image2template_directory(self._image) image_number = image2image(os.path.split(self._image)[-1]) spot_file = '%s.spt' % template_number2image( template, image_number) self.start() self.input('template "%s"' % template) self.input('directory "%s"' % directory) self.input('findspots local find %d file %s' % \ (image_number, spot_file)) self.input('go') self.close_wait() self.check_for_errors() output = open(os.path.join(self.get_working_directory(), spot_file)).readlines() os.remove(os.path.join(self.get_working_directory(), spot_file)) peaks = [] for record in output[3:-2]: lst = record.split() x = float(lst[0]) y = float(lst[1]) i = float(lst[4]) / float(lst[5]) x /= pixel[0] y /= pixel[1] if i < threshold: continue # this is Mosflm right? Swap X & Y!! peaks.append((y, x, i)) return peaks
def epocher(images): '''Get a list of epochs for each image in this list, returning as a list of tuples.''' result = [] for i in images: dd = Diffdump() dd.set_image(i) header = dd.readheader() e = header['epoch'] result.append((i, e)) return result
def _read_headers(self): '''Get the image headers for all of the images - this is not designed to be called externally.''' self._headers = { } t = time.time() for i in self._images: dd = Diffdump() image = self.imagename(i) dd.set_image(image) header = dd.readheader() self._headers[i] = header return
def get_maxima(self): '''Run diffdump, printpeaks to get a list of diffraction maxima at their image positions, to allow for further analysis.''' if not self._image: raise RuntimeError('image not set') if not os.path.exists(self._image): raise RuntimeError('image %s does not exist' % \ self._image) dd = Diffdump() dd.set_image(self._image) header = dd.readheader() beam = header['raw_beam'] pixel = header['pixel'] self.add_command_line(self._image) self.start() self.close_wait() self.check_for_errors() # results were ok, so get all of the output out output = self.get_all_output() peaks = [] for record in output: if not 'Peak' in record[:4]: continue lst = record.replace(':', ' ').split() x = float(lst[4]) y = float(lst[6]) i = float(lst[-1]) x += beam[0] y += beam[1] x /= pixel[0] y /= pixel[1] peaks.append((x, y, i)) return peaks
def accumulate(images): '''Accumulate dose as a function of image epoch.''' dose = { } integrated_dose = { } for i in images: dd = Diffdump() dd.set_image(i) header = dd.readheader() d = header['exposure_time'] e = header['epoch'] dose[e] = d keys = dose.keys() keys.sort() accum = 0.0 for k in keys: integrated_dose[k] = accum + 0.5 * dose[k] accum += dose[k] # ok, now check that the value for the maximum dose is < 1e6 - elsewise # chef may explode. or write out ****** as the values are too large for # an f8.1 format statement. max_dose = max([integrated_dose[k] for k in keys]) factor = 1.0 while max_dose / factor > 1.0e6: factor *= 10.0 Debug.write('Doses scaled by %5.2e' % factor) # now divide all of those doses by factor for k in keys: integrated_dose[k] /= factor return integrated_dose, factor
def test_i(self): idxref = self.Idxref() self._index_remove_masked_regions() for file in ['SPOT.XDS']: idxref.set_input_data_file(file, self._indxr_payload[file]) idxref.set_data_range(self._indxr_images[0][0], self._indxr_images[0][1]) idxref.set_background_range(self._indxr_images[0][0], self._indxr_images[0][1]) # set the phi start etc correctly blocks = self._index_select_images_i() for block in blocks[:1]: starting_frame = block[0] dd = Diffdump() dd.set_image(self.get_image_name(starting_frame)) starting_angle = dd.readheader()['phi_start'] idxref.set_starting_frame(starting_frame) idxref.set_starting_angle(starting_angle) idxref.add_spot_range(block[0], block[1]) for block in blocks[1:]: idxref.add_spot_range(block[0], block[1]) #mosflm_beam_centre = self.get_beam_centre() #xds_beam_centre = beam_centre_mosflm_to_xds( #mosflm_beam_centre[0], mosflm_beam_centre[1], self.get_header()) from dxtbx.serialize.xds import to_xds converter = to_xds(self.get_imageset()) xds_beam_centre = converter.detector_origin idxref.set_beam_centre(xds_beam_centre[0], xds_beam_centre[1]) idxref.run() return idxref.get_fraction_rmsd_rmsphi()
def accumulate(images): '''Accumulate dose as a function of image epoch.''' dose = {} integrated_dose = {} for i in images: dd = Diffdump() dd.set_image(i) header = dd.readheader() d = header['exposure_time'] e = header['epoch'] dose[e] = d keys = sorted(dose.keys()) accum = 0.0 for k in keys: integrated_dose[k] = accum + 0.5 * dose[k] accum += dose[k] # ok, now check that the value for the maximum dose is < 1e6 - elsewise # chef may explode. or write out ****** as the values are too large for # an f8.1 format statement. max_dose = max([integrated_dose[k] for k in keys]) factor = 1.0 while max_dose / factor > 1.0e6: factor *= 10.0 Debug.write('Doses scaled by %5.2e' % factor) # now divide all of those doses by factor for k in keys: integrated_dose[k] /= factor return integrated_dose, factor
assert 0.0 <= i[0] <= 2.0 assert 0.0 <= i[1] <= 2.0 assert math.fabs((dot(x, d) / math.sqrt(dot(x, x) * dot(d, d))) - 1) < 0.001 if __name__ == "__main_work__": work_equation_of_line() if __name__ == "__main__": from xia2.Wrappers.XIA.Diffdump import Diffdump bm = BackstopMask(sys.argv[1]) dd = Diffdump() dd.set_image(sys.argv[2]) header = dd.readheader() def format_limits(limits): assert len(limits) == 4 result = "limits quad" for l in limits: result += " %.1f %.1f" % l return result print(format_limits(bm.calculate_mask_mosflm(header)))
def gain(image): """Get the gain from an image.""" dd = Diffdump() dd.set_image(image) return dd.gain()
assert 0.0 <= i[1] <= 2.0 assert math.fabs((dot(x, d) / math.sqrt(dot(x, x) * dot(d, d))) - 1) < 0.001 return if __name__ == "__main_work__": work_equation_of_line() if __name__ == "__main__": from xia2.Wrappers.XIA.Diffdump import Diffdump bm = BackstopMask(sys.argv[1]) dd = Diffdump() dd.set_image(sys.argv[2]) header = dd.readheader() def format_limits(limits): assert len(limits) == 4 result = "limits quad" for l in limits: result += " %.1f %.1f" % l return result print format_limits(bm.calculate_mask_mosflm(header))
def mosflm_check_indexer_solution(indexer): distance = indexer.get_indexer_distance() axis = matrix.col([0, 0, 1]) beam = indexer.get_indexer_beam_centre() cell = indexer.get_indexer_cell() wavelength = indexer.get_wavelength() space_group_number = l2s(indexer.get_indexer_lattice()) spacegroup = sgtbx.space_group_symbols(space_group_number).hall() phi = indexer.get_header()['phi_width'] sg = sgtbx.space_group(spacegroup) if not (sg.n_ltr() - 1): # primitive solution - just return ... something return None, None, None, None # FIXME need to raise an exception if this is not available! m_matrix = indexer.get_indexer_payload('mosflm_orientation_matrix') # N.B. in the calculation below I am using the Cambridge frame # and Mosflm definitions of X & Y... m_elems = [] for record in m_matrix[:3]: record = record.replace('-', ' -') for e in map(float, record.split()): m_elems.append(e / wavelength) mi = matrix.sqr(m_elems) m = mi.inverse() A = matrix.col(m.elems[0:3]) B = matrix.col(m.elems[3:6]) C = matrix.col(m.elems[6:9]) # now select the images - start with the images that the indexer # used for indexing, though can interrogate the FrameProcessor # interface of the indexer to put together a completely different # list if I like... images = [] for i in indexer.get_indexer_images(): for j in i: if not j in images: images.append(j) images.sort() # now construct the reciprocal-space peak list n.b. should # really run this in parallel... spots_r = [] spots_r_j = { } for i in images: image = indexer.get_image_name(i) dd = Diffdump() dd.set_image(image) header = dd.readheader() phi = header['phi_start'] + 0.5 * header['phi_width'] pixel = header['pixel'] wavelength = header['wavelength'] peaks = locate_maxima(image) spots_r_j[i] = [] for p in peaks: x, y, isigma = p if isigma < 5.0: continue xp = pixel[0] * y - beam[0] yp = pixel[1] * x - beam[1] scale = wavelength * math.sqrt( xp * xp + yp * yp + distance * distance) X = distance / scale X -= 1.0 / wavelength Y = - xp / scale Z = yp / scale S = matrix.col([X, Y, Z]) rtod = 180.0 / math.pi spots_r.append(S.rotate(axis, - phi / rtod)) spots_r_j[i].append(S.rotate(axis, - phi / rtod)) # now reindex the reciprocal space spot list and count - n.b. need # to transform the Bravais lattice to an assumed spacegroup and hence # to a cctbx spacegroup! # lists = [spots_r_j[j] for j in spots_r_j] lists = [] lists.append(spots_r) for l in lists: absent = 0 present = 0 total = 0 for spot in l: hkl = (m * spot).elems total += 1 ihkl = map(nint, hkl) if math.fabs(hkl[0] - ihkl[0]) > 0.1: continue if math.fabs(hkl[1] - ihkl[1]) > 0.1: continue if math.fabs(hkl[2] - ihkl[2]) > 0.1: continue # now determine if it is absent if sg.is_sys_absent(ihkl): absent += 1 else: present += 1 # now perform the analysis on these numbers... sd = math.sqrt(absent) if total: Debug.write('Counts: %d %d %d %.3f' % \ (total, present, absent, (absent - 3 * sd) / total)) else: Debug.write('Not enough spots found for analysis') return False, None, None, None if (absent - 3 * sd) / total < 0.008: return False, None, None, None # in here need to calculate the new orientation matrix for the # primitive basis and reconfigure the indexer - somehow... # ok, so the bases are fine, but what I will want to do is reorder them # to give the best primitive choice of unit cell... sgp = sg.build_derived_group(True, False) lattice_p = s2l(sgp.type().number()) symm = crystal.symmetry(unit_cell = cell, space_group = sgp) rdx = symm.change_of_basis_op_to_best_cell() symm_new = symm.change_basis(rdx) # now apply this to the reciprocal-space orientation matrix mi # cb_op = sgtbx.change_of_basis_op(rdx) cb_op = rdx R = cb_op.c_inv().r().as_rational().as_float().transpose().inverse() mi_r = mi * R # now re-derive the cell constants, just to be sure m_r = mi_r.inverse() Ar = matrix.col(m_r.elems[0:3]) Br = matrix.col(m_r.elems[3:6]) Cr = matrix.col(m_r.elems[6:9]) a = math.sqrt(Ar.dot()) b = math.sqrt(Br.dot()) c = math.sqrt(Cr.dot()) rtod = 180.0 / math.pi alpha = rtod * Br.angle(Cr) beta = rtod * Cr.angle(Ar) gamma = rtod * Ar.angle(Br) # print '%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f' % \ # (a, b, c, alpha, beta, gamma) cell = uctbx.unit_cell((a, b, c, alpha, beta, gamma)) amat = [wavelength * e for e in mi_r.elems] bmat = matrix.sqr(cell.fractionalization_matrix()) umat = mi_r * bmat.inverse() # yuk! surely I don't need to do this... # I do need to do this, and don't call me shirley! new_matrix = ['%s\n' % r for r in \ format_matrix((a, b, c, alpha, beta, gamma), amat, umat.elems).split('\n')] # ok - this gives back the right matrix in the right setting - excellent! # now need to apply this back at base to the results of the indexer. # N.B. same should be applied to the same calculations for the XDS # version of this. return True, lattice_p, new_matrix, (a, b, c, alpha, beta, gamma)
def mosflm_check_indexer_solution(indexer): distance = indexer.get_indexer_distance() axis = matrix.col([0, 0, 1]) beam = indexer.get_indexer_beam_centre() cell = indexer.get_indexer_cell() wavelength = indexer.get_wavelength() space_group_number = l2s(indexer.get_indexer_lattice()) spacegroup = sgtbx.space_group_symbols(space_group_number).hall() phi = indexer.get_header()['phi_width'] sg = sgtbx.space_group(spacegroup) if not (sg.n_ltr() - 1): # primitive solution - just return ... something return None, None, None, None # FIXME need to raise an exception if this is not available! m_matrix = indexer.get_indexer_payload('mosflm_orientation_matrix') # N.B. in the calculation below I am using the Cambridge frame # and Mosflm definitions of X & Y... m_elems = [] for record in m_matrix[:3]: record = record.replace('-', ' -') for e in map(float, record.split()): m_elems.append(e / wavelength) mi = matrix.sqr(m_elems) m = mi.inverse() A = matrix.col(m.elems[0:3]) B = matrix.col(m.elems[3:6]) C = matrix.col(m.elems[6:9]) # now select the images - start with the images that the indexer # used for indexing, though can interrogate the FrameProcessor # interface of the indexer to put together a completely different # list if I like... images = [] for i in indexer.get_indexer_images(): for j in i: if not j in images: images.append(j) images.sort() # now construct the reciprocal-space peak list n.b. should # really run this in parallel... spots_r = [] spots_r_j = {} for i in images: image = indexer.get_image_name(i) dd = Diffdump() dd.set_image(image) header = dd.readheader() phi = header['phi_start'] + 0.5 * header['phi_width'] pixel = header['pixel'] wavelength = header['wavelength'] peaks = locate_maxima(image) spots_r_j[i] = [] for p in peaks: x, y, isigma = p if isigma < 5.0: continue xp = pixel[0] * y - beam[0] yp = pixel[1] * x - beam[1] scale = wavelength * math.sqrt(xp * xp + yp * yp + distance * distance) X = distance / scale X -= 1.0 / wavelength Y = -xp / scale Z = yp / scale S = matrix.col([X, Y, Z]) rtod = 180.0 / math.pi spots_r.append(S.rotate(axis, -phi / rtod)) spots_r_j[i].append(S.rotate(axis, -phi / rtod)) # now reindex the reciprocal space spot list and count - n.b. need # to transform the Bravais lattice to an assumed spacegroup and hence # to a cctbx spacegroup! # lists = [spots_r_j[j] for j in spots_r_j] lists = [] lists.append(spots_r) for l in lists: absent = 0 present = 0 total = 0 for spot in l: hkl = (m * spot).elems total += 1 ihkl = map(nint, hkl) if math.fabs(hkl[0] - ihkl[0]) > 0.1: continue if math.fabs(hkl[1] - ihkl[1]) > 0.1: continue if math.fabs(hkl[2] - ihkl[2]) > 0.1: continue # now determine if it is absent if sg.is_sys_absent(ihkl): absent += 1 else: present += 1 # now perform the analysis on these numbers... sd = math.sqrt(absent) if total: Debug.write('Counts: %d %d %d %.3f' % \ (total, present, absent, (absent - 3 * sd) / total)) else: Debug.write('Not enough spots found for analysis') return False, None, None, None if (absent - 3 * sd) / total < 0.008: return False, None, None, None # in here need to calculate the new orientation matrix for the # primitive basis and reconfigure the indexer - somehow... # ok, so the bases are fine, but what I will want to do is reorder them # to give the best primitive choice of unit cell... sgp = sg.build_derived_group(True, False) lattice_p = s2l(sgp.type().number()) symm = crystal.symmetry(unit_cell=cell, space_group=sgp) rdx = symm.change_of_basis_op_to_best_cell() symm_new = symm.change_basis(rdx) # now apply this to the reciprocal-space orientation matrix mi # cb_op = sgtbx.change_of_basis_op(rdx) cb_op = rdx R = cb_op.c_inv().r().as_rational().as_float().transpose().inverse() mi_r = mi * R # now re-derive the cell constants, just to be sure m_r = mi_r.inverse() Ar = matrix.col(m_r.elems[0:3]) Br = matrix.col(m_r.elems[3:6]) Cr = matrix.col(m_r.elems[6:9]) a = math.sqrt(Ar.dot()) b = math.sqrt(Br.dot()) c = math.sqrt(Cr.dot()) rtod = 180.0 / math.pi alpha = rtod * Br.angle(Cr) beta = rtod * Cr.angle(Ar) gamma = rtod * Ar.angle(Br) # print '%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f' % \ # (a, b, c, alpha, beta, gamma) cell = uctbx.unit_cell((a, b, c, alpha, beta, gamma)) amat = [wavelength * e for e in mi_r.elems] bmat = matrix.sqr(cell.fractionalization_matrix()) umat = mi_r * bmat.inverse() # yuk! surely I don't need to do this... # I do need to do this, and don't call me shirley! new_matrix = ['%s\n' % r for r in \ format_matrix((a, b, c, alpha, beta, gamma), amat, umat.elems).split('\n')] # ok - this gives back the right matrix in the right setting - excellent! # now need to apply this back at base to the results of the indexer. # N.B. same should be applied to the same calculations for the XDS # version of this. return True, lattice_p, new_matrix, (a, b, c, alpha, beta, gamma)
def gain(image): '''Get the gain from an image.''' dd = Diffdump() dd.set_image(image) return dd.gain()
def _index(self): '''Actually do the autoindexing using the data prepared by the previous method.''' images_str = '%d to %d' % tuple(self._indxr_images[0]) for i in self._indxr_images[1:]: images_str += ', %d to %d' % tuple(i) cell_str = None if self._indxr_input_cell: cell_str = '%.2f %.2f %.2f %.2f %.2f %.2f' % \ self._indxr_input_cell # then this is a proper autoindexing run - describe this # to the journal entry #if len(self._fp_directory) <= 50: #dirname = self._fp_directory #else: #dirname = '...%s' % self._fp_directory[-46:] dirname = self.get_directory() Journal.block('autoindexing', self._indxr_sweep_name, 'XDS', {'images':images_str, 'target cell':cell_str, 'target lattice':self._indxr_input_lattice, 'template':self.get_template(), 'directory':dirname}) idxref = self.Idxref() self._index_remove_masked_regions() for file in ['SPOT.XDS']: idxref.set_input_data_file(file, self._indxr_payload[file]) idxref.set_data_range(self._indxr_images[0][0], self._indxr_images[0][1]) idxref.set_background_range(self._indxr_images[0][0], self._indxr_images[0][1]) # set the phi start etc correctly if self._i_or_ii == None: self._i_or_ii = self.decide_i_or_ii() Debug.write('Selecting I or II, chose %s' % self._i_or_ii) if self._i_or_ii == 'i': blocks = self._index_select_images_i() for block in blocks[:1]: starting_frame = block[0] dd = Diffdump() dd.set_image(self.get_image_name(starting_frame)) starting_angle = dd.readheader()['phi_start'] idxref.set_starting_frame(starting_frame) idxref.set_starting_angle(starting_angle) idxref.add_spot_range(block[0], block[1]) for block in blocks[1:]: idxref.add_spot_range(block[0], block[1]) else: for block in self._indxr_images[:1]: starting_frame = block[0] dd = Diffdump() dd.set_image(self.get_image_name(starting_frame)) starting_angle = dd.readheader()['phi_start'] idxref.set_starting_frame(starting_frame) idxref.set_starting_angle(starting_angle) idxref.add_spot_range(block[0], block[1]) for block in self._indxr_images[1:]: idxref.add_spot_range(block[0], block[1]) # FIXME need to also be able to pass in the known unit # cell and lattice if already available e.g. from # the helper... indirectly if self._indxr_user_input_lattice: idxref.set_indexer_user_input_lattice(True) if self._indxr_input_lattice and self._indxr_input_cell: idxref.set_indexer_input_lattice(self._indxr_input_lattice) idxref.set_indexer_input_cell(self._indxr_input_cell) Debug.write('Set lattice: %s' % self._indxr_input_lattice) Debug.write('Set cell: %f %f %f %f %f %f' % \ self._indxr_input_cell) original_cell = self._indxr_input_cell elif self._indxr_input_lattice: idxref.set_indexer_input_lattice(self._indxr_input_lattice) original_cell = None else: original_cell = None # FIXED need to set the beam centre here - this needs to come # from the input .xinfo object or header, and be converted # to the XDS frame... done. #mosflm_beam_centre = self.get_beam_centre() #xds_beam_centre = beam_centre_mosflm_to_xds( #mosflm_beam_centre[0], mosflm_beam_centre[1], self.get_header()) from dxtbx.serialize.xds import to_xds converter = to_xds(self.get_imageset()) xds_beam_centre = converter.detector_origin idxref.set_beam_centre(xds_beam_centre[0], xds_beam_centre[1]) # fixme need to check if the lattice, cell have been set already, # and if they have, pass these in as input to the indexing job. done = False while not done: try: done = idxref.run() # N.B. in here if the IDXREF step was being run in the first # pass done is FALSE however there should be a refined # P1 orientation matrix etc. available - so keep it! except XDSException, e: # inspect this - if we have complaints about not # enough reflections indexed, and we have a target # unit cell, and they are the same, well ignore it if 'solution is inaccurate' in str(e): Debug.write( 'XDS complains solution inaccurate - ignoring') done = idxref.continue_from_error() elif ('insufficient percentage (< 70%)' in str(e) or 'insufficient percentage (< 50%)' in str(e)) and \ original_cell: done = idxref.continue_from_error() lattice, cell, mosaic = \ idxref.get_indexing_solution() # compare solutions for j in range(3): # allow two percent variation in unit cell length if math.fabs((cell[j] - original_cell[j]) / \ original_cell[j]) > 0.02 and \ not Flags.get_relax(): Debug.write('XDS unhappy and solution wrong') raise e # and two degree difference in angle if math.fabs(cell[j + 3] - original_cell[j + 3]) \ > 2.0 and not Flags.get_relax(): Debug.write('XDS unhappy and solution wrong') raise e Debug.write('XDS unhappy but solution ok') elif 'insufficient percentage (< 70%)' in str(e) or \ 'insufficient percentage (< 50%)' in str(e): Debug.write('XDS unhappy but solution probably ok') done = idxref.continue_from_error() else: raise e