def _prepare_pointless_hklin(working_directory, hklin, phi_width): '''Prepare some data for pointless - this will take only 180 degrees of data if there is more than this (through a "rebatch" command) else will simply return hklin.''' # also remove blank images? if not Flags.get_microcrystal() and not Flags.get_small_molecule(): Debug.write('Excluding blank images') hklout = os.path.join( working_directory, '%s_noblank.mtz' % (os.path.split(hklin)[-1][:-4])) FileHandler.record_temporary_file(hklout) hklin = remove_blank(hklin, hklout) # find the number of batches md = Mtzdump() md.set_working_directory(working_directory) auto_logfiler(md) md.set_hklin(hklin) md.dump() batches = max(md.get_batches()) - min(md.get_batches()) phi_limit = 180 if batches * phi_width < phi_limit or Flags.get_small_molecule(): return hklin hklout = os.path.join( working_directory, '%s_prepointless.mtz' % (os.path.split(hklin)[-1][:-4])) rb = Rebatch() rb.set_working_directory(working_directory) auto_logfiler(rb) rb.set_hklin(hklin) rb.set_hklout(hklout) first = min(md.get_batches()) last = first + int(phi_limit / phi_width) Debug.write('Preparing data for pointless - %d batches (%d degrees)' % \ ((last - first), phi_limit)) rb.limit_batches(first, last) # we will want to delete this one exit FileHandler.record_temporary_file(hklout) return hklout
def _updated_aimless(self): '''Generate a correctly configured Aimless...''' aimless = None if not self._scalr_corrections: aimless = self._factory.Aimless() else: aimless = self._factory.Aimless( partiality_correction = self._scalr_correct_partiality, absorption_correction = self._scalr_correct_absorption, decay_correction = self._scalr_correct_decay) if Flags.get_microcrystal(): # fiddly little data sets - allow more rapid scaling... aimless.set_scaling_parameters('rotation', 2.0) if self._scalr_correct_decay: aimless.set_bfactor(bfactor=True, brotation = 2.0) if Flags.get_small_molecule(): aimless.set_scaling_parameters('rotation', 15.0) aimless.set_bfactor(bfactor=False) aimless.set_surface_tie(PhilIndex.params.ccp4.aimless.surface_tie) aimless.set_surface_link(PhilIndex.params.ccp4.aimless.surface_link) return aimless
def merge(self): '''Actually merge the already scaled reflections.''' self.check_hklin() self.check_hklout() if not self._onlymerge: raise RuntimeError, 'for scaling use scale()' if not self._scalepack: self.set_task('Merging scaled reflections from %s => %s' % \ (os.path.split(self.get_hklin())[-1], os.path.split(self.get_hklout())[-1])) else: self.set_task('Merging reflections from %s => scalepack %s' % \ (os.path.split(self.get_hklin())[-1], os.path.split(self.get_hklout())[-1])) self._xmlout = os.path.join(self.get_working_directory(), '%d_aimless.xml' % self.get_xpid()) self.start() self.input('xmlout %d_aimless.xml' % self.get_xpid()) if not Flags.get_small_molecule(): self.input('bins 20') self.input('run 1 all') self.input('scales constant') self.input('initial unity') self.input('sdcorrection both noadjust 1.0 0.0 0.0') if self._anomalous: self.input('anomalous on') else: self.input('anomalous off') if self._scalepack: self.input('output polish unmerged') self.input('output unmerged') self.close_wait() # check for errors try: self.check_for_errors() self.check_ccp4_errors() self.check_aimless_errors() status = self.get_ccp4_status() if 'Error' in status: raise RuntimeError, '[AIMLESS] %s' % status except RuntimeError, e: try: os.remove(self.get_hklout()) except: pass raise e
def reindex(self): '''Actually perform the reindexing.''' if PhilIndex.params.ccp4.reindex.program == 'reindex': return self.reindex_old() self.check_hklin() self.check_hklout() if not self._spacegroup and not self._operator: raise RuntimeError, 'reindex requires spacegroup or operator' if self._operator: self._operator = self._operator.replace('[', '').replace(']', '') Debug.write('Reindex... %s %s' % (self._spacegroup, self._operator)) if self._spacegroup and Flags.get_small_molecule() and False: if not self._operator or self._operator.replace(' ', '') == 'h,k,l': return self.cctbx_reindex() self.start() if self._spacegroup: if type(self._spacegroup) == type(0): spacegroup = Syminfo.spacegroup_number_to_name( self._spacegroup) elif self._spacegroup[0] in '0123456789': spacegroup = Syminfo.spacegroup_number_to_name( int(self._spacegroup)) else: spacegroup = self._spacegroup self.input('spacegroup \'%s\'' % spacegroup) if self._operator: # likewise self.input('reindex \'%s\'' % self._operator) else: self.input('reindex \'h,k,l\'') self.close_wait() # check for errors try: self.check_for_errors() except RuntimeError, e: try: os.remove(self.get_hklout()) except: pass raise e
def _estimate_resolution_limit(self, hklin, batch_range=None): params = PhilIndex.params.xia2.settings.resolution m = Merger() m.set_working_directory(self.get_working_directory()) from xia2.lib.bits import auto_logfiler auto_logfiler(m) m.set_hklin(hklin) m.set_limit_rmerge(params.rmerge) m.set_limit_completeness(params.completeness) m.set_limit_cc_half(params.cc_half) m.set_limit_isigma(params.isigma) m.set_limit_misigma(params.misigma) if Flags.get_small_molecule(): m.set_nbins(20) if batch_range is not None: start, end = batch_range m.set_batch_range(start, end) m.run() if params.completeness: r_comp = m.get_resolution_completeness() else: r_comp = 0.0 if params.cc_half: r_cc_half = m.get_resolution_cc_half() else: r_cc_half = 0.0 if params.rmerge: r_rm = m.get_resolution_rmerge() else: r_rm = 0.0 if params.isigma: r_uis = m.get_resolution_isigma() else: r_uis = 0.0 if params.misigma: r_mis = m.get_resolution_misigma() else: r_mis = 0.0 resolution = max([r_comp, r_rm, r_uis, r_mis, r_cc_half]) return resolution
def _do_indexing(self, method=None): indexer = self.Index() for indxr in self._indxr_indexers: indexer.add_spot_filename(indxr._indxr_payload["spot_list"]) indexer.add_sweep_filename(indxr._indxr_payload["datablock.json"]) if PhilIndex.params.dials.index.phil_file is not None: indexer.set_phil_file(PhilIndex.params.dials.index.phil_file) if PhilIndex.params.dials.index.max_cell: indexer.set_max_cell(PhilIndex.params.dials.index.max_cell) if Flags.get_small_molecule(): indexer.set_min_cell(3) if PhilIndex.params.dials.fix_geometry: indexer.set_detector_fix('all') indexer.set_beam_fix('all') if self._indxr_input_lattice: indexer.set_indexer_input_lattice(self._indxr_input_lattice) Debug.write('Set lattice: %s' % self._indxr_input_lattice) if self._indxr_input_cell: indexer.set_indexer_input_cell(self._indxr_input_cell) Debug.write('Set cell: %f %f %f %f %f %f' % \ self._indxr_input_cell) original_cell = self._indxr_input_cell if method is None: if PhilIndex.params.dials.index.method is None: method = 'fft3d' Debug.write('Choosing indexing method: %s' % method) else: method = PhilIndex.params.dials.index.method indexer.run(method) if not os.path.exists(indexer.get_experiments_filename()): raise RuntimeError("Indexing has failed: %s does not exist." %indexer.get_experiments_filename()) elif not os.path.exists(indexer.get_indexed_filename()): raise RuntimeError("Indexing has failed: %s does not exist." %indexer.get_indexed_filename()) return indexer
def _index_select_images(self): '''Select correct images based on image headers.''' if Flags.get_small_molecule(): return self._index_select_images_small_molecule() if Flags.get_microcrystal(): return self._index_select_images_microcrystal() phi_width = self.get_phi_width() images = self.get_matching_images() if Flags.get_interactive(): selected_images = index_select_images_user(phi_width, images, Chatter) else: selected_images = index_select_images_lone(phi_width, images) for image in selected_images: Debug.write('Selected image %s' % image) self.add_indexer_image_wedge(image) return
def run(self): '''Run colspot.''' #image_header = self.get_header() ## crank through the header dictionary and replace incorrect ## information with updated values through the indexer ## interface if available... ## need to add distance, wavelength - that should be enough... #if self.get_distance(): #image_header['distance'] = self.get_distance() #if self.get_wavelength(): #image_header['wavelength'] = self.get_wavelength() #if self.get_two_theta(): #image_header['two_theta'] = self.get_two_theta() header = imageset_to_xds(self.get_imageset()) xds_inp = open(os.path.join(self.get_working_directory(), 'XDS.INP'), 'w') # what are we doing? xds_inp.write('JOB=COLSPOT\n') xds_inp.write('MAXIMUM_NUMBER_OF_PROCESSORS=%d\n' % \ self._parallel) #if image_header['detector'] in ('pilatus', 'dectris'): if self.get_imageset().get_detector()[0].get_type() == 'SENSOR_PAD': xds_inp.write('MINIMUM_NUMBER_OF_PIXELS_IN_A_SPOT=%d\n' % self._params.minimum_pixels_per_spot) for record in header: xds_inp.write('%s\n' % record) name_template = os.path.join(self.get_directory(), self.get_template().replace('#', '?')) record = 'NAME_TEMPLATE_OF_DATA_FRAMES=%s\n' % \ name_template xds_inp.write(record) xds_inp.write('DATA_RANGE=%d %d\n' % self._data_range) for spot_range in self._spot_range: xds_inp.write('SPOT_RANGE=%d %d\n' % spot_range) xds_inp.write('BACKGROUND_RANGE=%d %d\n' % \ self._background_range) # microcrystals have very mall spots, perhaps? if Flags.get_microcrystal(): xds_inp.write('MINIMUM_NUMBER_OF_PIXELS_IN_A_SPOT=1\n') if Flags.get_small_molecule(): xds_inp.write('STRONG_PIXEL=5\n') # FIXME should probably be moved to a phil parameter xds_inp.close() # copy the input file... shutil.copyfile(os.path.join(self.get_working_directory(), 'XDS.INP'), os.path.join(self.get_working_directory(), '%d_COLSPOT.INP' % self.get_xpid())) # write the input data files... for file_name in self._input_data_files_list: src = self._input_data_files[file_name] dst = os.path.join( self.get_working_directory(), file_name) if src != dst: shutil.copyfile(src, dst) self.start() self.close_wait() xds_check_version_supported(self.get_all_output()) # copy the LP file shutil.copyfile(os.path.join(self.get_working_directory(), 'COLSPOT.LP'), os.path.join(self.get_working_directory(), '%d_COLSPOT.LP' % self.get_xpid())) # gather the output files for file in self._output_data_files_list: self._output_data_files[file] = os.path.join( self.get_working_directory(), file) return
def decide_spacegroup(self): '''Given data indexed in the correct pointgroup, have a guess at the spacegroup.''' if not self._xdsin: self.check_hklin() self.set_task('Computing the correct spacegroup for %s' % \ self.get_hklin()) else: Debug.write('Pointless using XDS input file %s' % \ self._xdsin) self.set_task('Computing the correct spacegroup for %s' % \ self.get_xdsin()) # FIXME this should probably be a standard CCP4 keyword if self._xdsin: self.add_command_line('xdsin') self.add_command_line(self._xdsin) self.add_command_line('xmlout') self.add_command_line('%d_pointless.xml' % self.get_xpid()) self.add_command_line('hklout') self.add_command_line('pointless.mtz') self.start() self.input('lauegroup hklin') self.input('setting symmetry-based') if Flags.get_small_molecule(): self.input('chirality nonchiral') self.close_wait() # check for errors self.check_for_errors() hklin_spacegroup = '' xml_file = os.path.join(self.get_working_directory(), '%d_pointless.xml' % self.get_xpid()) mend_pointless_xml(xml_file) if not os.path.exists(xml_file) and \ os.path.exists('%s.xml' % xml_file): xml_file = '%s.xml' % xml_file dom = xml.dom.minidom.parse(xml_file) sg_list = dom.getElementsByTagName('SpacegroupList')[0] sg_node = sg_list.getElementsByTagName('Spacegroup')[0] best_prob = float(sg_node.getElementsByTagName( 'TotalProb')[0].childNodes[0].data.strip()) # FIXME 21/NOV/06 in here record a list of valid spacegroups # (that is, those which are as likely as the most likely) # for later use... self._spacegroup = sg_node.getElementsByTagName( 'SpacegroupName')[0].childNodes[0].data.strip() self._spacegroup_reindex_operator = sg_node.getElementsByTagName( 'ReindexOperator')[0].childNodes[0].data.strip() self._spacegroup_reindex_matrix = tuple( map(float, sg_node.getElementsByTagName( 'ReindexMatrix')[0].childNodes[0].data.split())) # get a list of "equally likely" spacegroups for node in sg_list.getElementsByTagName('Spacegroup'): prob = float(node.getElementsByTagName( 'TotalProb')[0].childNodes[0].data.strip()) name = node.getElementsByTagName( 'SpacegroupName')[0].childNodes[0].data.strip() if math.fabs(prob - best_prob) < 0.01: # this is jolly likely! self._likely_spacegroups.append(name) # now parse the output looking for the unit cell information - # this should look familiar from mtzdump output = self.get_all_output() length = len(output) a = 0.0 b = 0.0 c = 0.0 alpha = 0.0 beta = 0.0 gamma = 0.0 self._cell_info['datasets'] = [] self._cell_info['dataset_info'] = { } for i in range(length): line = output[i][:-1] if 'Dataset ID, ' in line: block = 0 while output[block * 5 + i + 2].strip(): dataset_number = int( output[5 * block + i + 2].split()[0]) project = output[5 * block + i + 2][10:].strip() crystal = output[5 * block + i + 3][10:].strip() dataset = output[5 * block + i + 4][10:].strip() cell = map(float, output[5 * block + i + 5].strip( ).split()) wavelength = float(output[5 * block + i + 6].strip()) dataset_id = '%s/%s/%s' % \ (project, crystal, dataset) self._cell_info['datasets'].append(dataset_id) self._cell_info['dataset_info'][dataset_id] = { } self._cell_info['dataset_info'][ dataset_id]['wavelength'] = wavelength self._cell_info['dataset_info'][ dataset_id]['cell'] = cell self._cell_info['dataset_info'][ dataset_id]['id'] = dataset_number block += 1 for dataset in self._cell_info['datasets']: cell = self._cell_info['dataset_info'][dataset]['cell'] a += cell[0] b += cell[1] c += cell[2] alpha += cell[3] beta += cell[4] gamma += cell[5] n = len(self._cell_info['datasets']) self._cell = (a / n, b / n, c / n, alpha / n, beta / n, gamma / n) return 'ok'
def decide_pointgroup(self): '''Decide on the correct pointgroup for hklin.''' if not self._xdsin: self.check_hklin() self.set_task('Computing the correct pointgroup for %s' % \ self.get_hklin()) else: Debug.write('Pointless using XDS input file %s' % \ self._xdsin) self.set_task('Computing the correct pointgroup for %s' % \ self.get_xdsin()) # FIXME this should probably be a standard CCP4 keyword if self._xdsin: self.add_command_line('xdsin') self.add_command_line(self._xdsin) self.add_command_line('xmlout') self.add_command_line('%d_pointless.xml' % self.get_xpid()) if self._hklref: self.add_command_line('hklref') self.add_command_line(self._hklref) self.start() self.input('systematicabsences off') self.input('setting symmetry-based') if self._hklref: from xia2.Handlers.Phil import PhilIndex dev = PhilIndex.params.xia2.settings.developmental if dev.pointless_tolerance > 0.0: self.input('tolerance %f' % dev.pointless_tolerance) # may expect more %age variation for small molecule data if Flags.get_small_molecule() and self._hklref: self.input('tolerance 5.0') if Flags.get_small_molecule(): self.input('chirality nonchiral') if self._input_laue_group: self.input('lauegroup %s' % self._input_laue_group) self.close_wait() # check for errors self.check_for_errors() # check for fatal errors output = self.get_all_output() for j, record in enumerate(output): if 'FATAL ERROR message:' in record: raise RuntimeError, 'Pointless error: %s' % output[j+1].strip() hklin_spacegroup = '' hklin_lattice = '' for o in self.get_all_output(): if 'Spacegroup from HKLIN file' in o: # hklin_spacegroup = o.split(':')[-1].strip() hklin_spacegroup = spacegroup_name_xHM_to_old( o.replace( 'Spacegroup from HKLIN file :', '').strip()) hklin_lattice = Syminfo.get_lattice(hklin_spacegroup) if 'No alternative indexing possible' in o: # then the XML file will be broken - no worries... self._pointgroup = hklin_spacegroup self._confidence = 1.0 self._totalprob = 1.0 self._reindex_matrix = [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0] self._reindex_operator = 'h,k,l' return 'ok' if '**** Incompatible symmetries ****' in o: raise RuntimeError, \ 'reindexing against a reference with different symmetry' if '***** Stopping because cell discrepancy between files' in o: raise RuntimeError, 'incompatible unit cells between data sets' if 'L-test suggests that the data may be twinned' in o: self._probably_twinned = True # parse the XML file for the information I need... xml_file = os.path.join(self.get_working_directory(), '%d_pointless.xml' % self.get_xpid()) mend_pointless_xml(xml_file) # catch the case sometimes on ppc mac where pointless adds # an extra .xml on the end... if not os.path.exists(xml_file) and \ os.path.exists('%s.xml' % xml_file): xml_file = '%s.xml' % xml_file if not self._hklref: dom = xml.dom.minidom.parse(xml_file) try: best = dom.getElementsByTagName('BestSolution')[0] except IndexError, e: raise RuntimeError, 'error getting solution from pointless' self._pointgroup = best.getElementsByTagName( 'GroupName')[0].childNodes[0].data self._confidence = float(best.getElementsByTagName( 'Confidence')[0].childNodes[0].data) self._totalprob = float(best.getElementsByTagName( 'TotalProb')[0].childNodes[0].data) self._reindex_matrix = map(float, best.getElementsByTagName( 'ReindexMatrix')[0].childNodes[0].data.split()) self._reindex_operator = clean_reindex_operator( best.getElementsByTagName( 'ReindexOperator')[0].childNodes[0].data.strip())
def run(self): '''Run integrate.''' #image_header = self.get_header() ## crank through the header dictionary and replace incorrect ## information with updated values through the indexer ## interface if available... ## need to add distance, wavelength - that should be enough... #if self.get_distance(): #image_header['distance'] = self.get_distance() #if self.get_wavelength(): #image_header['wavelength'] = self.get_wavelength() #if self.get_two_theta(): #image_header['two_theta'] = self.get_two_theta() header = imageset_to_xds(self.get_imageset()) xds_inp = open(os.path.join(self.get_working_directory(), 'XDS.INP'), 'w') # what are we doing? xds_inp.write('JOB=INTEGRATE\n') xds_inp.write('MAXIMUM_NUMBER_OF_PROCESSORS=%d\n' % \ self._parallel) from xia2.Handlers.Phil import PhilIndex xds_params = PhilIndex.params.xds if xds_params.profile_grid_size: ab, c = xds_params.profile_grid_size assert(ab > 0 and ab < 22 and (ab % 2) == 1) assert(c > 0 and c < 22 and (c % 2) == 1) xds_inp.write( 'NUMBER_OF_PROFILE_GRID_POINTS_ALONG_ALPHA/BETA= %d\n' % ab) xds_inp.write( 'NUMBER_OF_PROFILE_GRID_POINTS_ALONG_GAMMA= %d\n' % c) if Flags.get_xparallel() > 1: xds_inp.write('MAXIMUM_NUMBER_OF_JOBS=%d\n' % \ Flags.get_xparallel()) elif Flags.get_xparallel() == -1: chunk_width = 30.0 phi_width = self.get_phi_width() nchunks = int( (self._data_range[1] - self._data_range[0] + 1) * \ phi_width / chunk_width) Debug.write('Xparallel: -1 using %d chunks' % nchunks) xds_inp.write('MAXIMUM_NUMBER_OF_JOBS=%d\n' % nchunks) profile_fitting = PhilIndex.params.xds.integrate.profile_fitting if not profile_fitting: xds_inp.write('PROFILE_FITTING=FALSE\n') # write out lots of output xds_inp.write('TEST=2\n') if self._params.delphi: xds_inp.write('DELPHI=%.1f\n' % self._params.delphi) elif Flags.get_small_molecule(): xds_inp.write('DELPHI=%.1f\n' % \ xds_params.delphi_small) else: xds_inp.write('DELPHI=%.1f\n' % \ xds_params.delphi) if self._refined_xparm: xds_inp.write('REFINE(INTEGRATE)=%s\n' % ' '.join(self._params.refine_final)) else: xds_inp.write('REFINE(INTEGRATE)=%s\n' % ' '.join(self._params.refine)) if self._params.fix_scale: if _running_xds_version() >= 20130330: xds_inp.write('DATA_RANGE_FIXED_SCALE_FACTOR= %d %d 1\n' % self._data_range) else: xds_inp.write('FIXED_SCALE_FACTOR=TRUE\n') # check for updated input parameters or ones from phil if self._updates.has_key('BEAM_DIVERGENCE') and \ self._updates.has_key('BEAM_DIVERGENCE_E.S.D.'): xds_inp.write( 'BEAM_DIVERGENCE=%f BEAM_DIVERGENCE_E.S.D.=%f\n' % \ (self._updates['BEAM_DIVERGENCE'], self._updates['BEAM_DIVERGENCE_E.S.D.'])) elif self._params.beam_divergence and self._params.beam_divergence_esd: xds_inp.write( 'BEAM_DIVERGENCE=%f BEAM_DIVERGENCE_E.S.D.=%f\n' % \ (self._params.beam_divergence, self._params.beam_divergence_esd)) if self._updates.has_key('REFLECTING_RANGE') and \ self._updates.has_key('REFLECTING_RANGE_E.S.D.'): xds_inp.write( 'REFLECTING_RANGE=%f REFLECTING_RANGE_E.S.D.=%f\n' % \ (self._updates['REFLECTING_RANGE'], self._updates['REFLECTING_RANGE_E.S.D.'])) elif self._params.reflecting_range and self._params.reflecting_range_esd: xds_inp.write( 'REFLECTING_RANGE=%f REFLECTING_RANGE_E.S.D.=%f\n' % \ (self._params.reflecting_range, self._params.reflecting_range_esd)) for record in header: xds_inp.write('%s\n' % record) name_template = os.path.join(self.get_directory(), self.get_template().replace('#', '?')) record = 'NAME_TEMPLATE_OF_DATA_FRAMES=%s\n' % \ name_template xds_inp.write(record) xds_inp.write('DATA_RANGE=%d %d\n' % self._data_range) # xds_inp.write('MINIMUM_ZETA=0.1\n') xds_inp.close() # copy the input file... shutil.copyfile(os.path.join(self.get_working_directory(), 'XDS.INP'), os.path.join(self.get_working_directory(), '%d_INTEGRATE.INP' % self.get_xpid())) # write the input data files... for file_name in self._input_data_files_list: src = self._input_data_files[file_name] dst = os.path.join( self.get_working_directory(), file_name) if src != dst: shutil.copyfile(src, dst) self.start() self.close_wait() xds_check_version_supported(self.get_all_output()) xds_check_error(self.get_all_output()) # look for errors # like this perhaps - what the hell does this mean? # !!! ERROR !!! "STRONGHKL": ASSERT VIOLATION # copy the LP file shutil.copyfile(os.path.join(self.get_working_directory(), 'INTEGRATE.LP'), os.path.join(self.get_working_directory(), '%d_INTEGRATE.LP' % self.get_xpid())) # gather the output files for file in self._output_data_files_list: self._output_data_files[file] = os.path.join( self.get_working_directory(), file) self._integrate_hkl = os.path.join(self.get_working_directory(), 'INTEGRATE.HKL') # look through integrate.lp for some useful information # to help with the analysis space_group_number = 0 mosaics = [] for o in open(os.path.join( self.get_working_directory(), 'INTEGRATE.LP')).readlines(): if 'SPACE_GROUP_NUMBER' in o: space_group_number = int(o.split()[-1]) if 'CRYSTAL MOSAICITY (DEGREES)' in o: mosaic = float(o.split()[-1]) mosaics.append(mosaic) assert len(mosaics) > 0, "XDS refinement failed (no mosaic spread range reported)" self._min_mosaic = min(mosaics) self._max_mosaic = max(mosaics) self._mean_mosaic = sum(mosaics) / len(mosaics) Debug.write( 'Mosaic spread range: %.3f %.3f %.3f' % \ (self._min_mosaic, self._mean_mosaic, self._max_mosaic)) stats = _parse_integrate_lp(os.path.join( self.get_working_directory(), 'INTEGRATE.LP')) self._per_image_statistics = stats self._updates = _parse_integrate_lp_updates(os.path.join( self.get_working_directory(), 'INTEGRATE.LP')) return
def run(self, method): from xia2.Handlers.Streams import Debug Debug.write('Running dials.index') self.clear_command_line() for f in self._sweep_filenames: self.add_command_line(f) for f in self._spot_filenames: self.add_command_line(f) self.add_command_line('indexing.method=%s' % method) nproc = Flags.get_parallel() self.set_cpu_threads(nproc) self.add_command_line('indexing.nproc=%i' % nproc) if Flags.get_small_molecule(): self.add_command_line('filter_ice=false') if self._reflections_per_degree is not None: self.add_command_line( 'reflections_per_degree=%i' %self._reflections_per_degree) if self._fft3d_n_points is not None: self.add_command_line( 'fft3d.reciprocal_space_grid.n_points=%i' %self._fft3d_n_points) if self._close_to_spindle_cutoff is not None: self.add_command_line( 'close_to_spindle_cutoff=%f' %self._close_to_spindle_cutoff) if self._outlier_algorithm: self.add_command_line('outlier.algorithm=%s' % self._outlier_algorithm) if self._max_cell: self.add_command_line('max_cell=%d' % self._max_cell) if self._min_cell: self.add_command_line('min_cell=%d' % self._min_cell) if self._d_min_start: self.add_command_line('d_min_start=%f' % self._d_min_start) if self._indxr_input_lattice is not None: from xia2.Experts.SymmetryExpert import lattice_to_spacegroup_number self._symm = lattice_to_spacegroup_number( self._indxr_input_lattice) self.add_command_line('known_symmetry.space_group=%s' % self._symm) if self._indxr_input_cell is not None: self.add_command_line( 'known_symmetry.unit_cell="%s,%s,%s,%s,%s,%s"' %self._indxr_input_cell) if self._maximum_spot_error: self.add_command_line('maximum_spot_error=%.f' % self._maximum_spot_error) if self._detector_fix: self.add_command_line('detector.fix=%s' % self._detector_fix) if self._beam_fix: self.add_command_line('beam.fix=%s' % self._beam_fix) if self._phil_file is not None: self.add_command_line("%s" %self._phil_file) self._experiment_filename = os.path.join( self.get_working_directory(), '%d_experiments.json' %self.get_xpid()) self._indexed_filename = os.path.join( self.get_working_directory(), '%d_indexed.pickle' %self.get_xpid()) self.add_command_line("output.experiments=%s" %self._experiment_filename) self.add_command_line("output.reflections=%s" %self._indexed_filename) self.start() self.close_wait() self.check_for_errors() records = self.get_all_output() for i, record in enumerate(records): if 'Unit cell:' in record: self._p1_cell = map(float, record.replace('(', '').replace( ')', '').replace(',', '').split()[-6:]) if 'Final RMSDs by experiment' in record: values = records[i+6].strip().strip('|').split('|') if len(values): values = [float(v) for v in values] if values[0] == 0: self._nref = int(values[1]) self._rmsd_x = values[2] self._rmsd_y = values[3] self._rmsd_z = values[4] return
def multi_merge(self): '''Merge data from multiple runs - this is very similar to the scaling subroutine...''' self.check_hklin() self.check_hklout() if not self._scalepack: self.set_task('Scaling reflections from %s => %s' % \ (os.path.split(self.get_hklin())[-1], os.path.split(self.get_hklout())[-1])) else: self.set_task('Scaling reflections from %s => scalepack %s' % \ (os.path.split(self.get_hklin())[-1], os.path.split(self.get_hklout())[-1])) self.start() self._xmlout = os.path.join(self.get_working_directory(), '%d_aimless.xml' % self.get_xpid()) self.input('xmlout %d_aimless.xml' % self.get_xpid()) if not Flags.get_small_molecule(): self.input('bins 20') if self._new_scales_file: self.input('dump %s' % self._new_scales_file) if self._resolution: self.input('resolution %f' % self._resolution) run_number = 0 for run in self._runs: run_number += 1 if not run[5]: self.input('run %d batch %d to %d' % (run_number, run[0], run[1])) if run[6] != 0.0 and not run[5]: self.input('resolution run %d high %f' % \ (run_number, run[6])) # put in the pname, xname, dname stuff run_number = 0 for run in self._runs: run_number += 1 if run[7]: Debug.write('Run %d corresponds to sweep %s' % \ (run_number, run[7])) if run[5]: continue # we are only merging here so the scales command is # dead simple... self.input('scales constant') if self._anomalous: self.input('anomalous on') else: self.input('anomalous off') # FIXME this is probably not ready to be used yet... if self._scalepack: self.input('output polish unmerged') self.input('output unmerged') if self._scales_file: self.input('onlymerge') self.input('restore %s' % self._scales_file) self.close_wait() # check for errors try: self.check_for_errors() self.check_ccp4_errors() self.check_aimless_errors() status = 'OK' Debug.write('Aimless status: %s' % status) if 'Error' in status: raise RuntimeError, '[AIMLESS] %s' % status except RuntimeError, e: try: os.remove(self.get_hklout()) except: pass raise e
def scale(self): '''Actually perform the scaling.''' self.check_hklin() self.check_hklout() if self._chef_unmerged and self._scalepack: raise RuntimeError, 'CHEF and scalepack incompatible' if self._onlymerge: raise RuntimeError, 'use merge() method' if not self._scalepack: self.set_task('Scaling reflections from %s => %s' % \ (os.path.split(self.get_hklin())[-1], os.path.split(self.get_hklout())[-1])) else: self.set_task('Scaling reflections from %s => scalepack %s' % \ (os.path.split(self.get_hklin())[-1], os.path.split(self.get_hklout())[-1])) self._xmlout = os.path.join(self.get_working_directory(), '%d_aimless.xml' % self.get_xpid()) self.start() nproc = Flags.get_parallel() if nproc > 1: self.set_working_environment('OMP_NUM_THREADS', '%d' %nproc) self.input('refine parallel') self.input('xmlout %d_aimless.xml' % self.get_xpid()) if not Flags.get_small_molecule(): self.input('bins 20') self.input('intensities %s' %self._intensities) if self._new_scales_file: self.input('dump %s' % self._new_scales_file) run_number = 0 for run in self._runs: run_number += 1 if not run[5]: self.input('run %d batch %d to %d' % (run_number, run[0], run[1])) if run[6] != 0.0 and not run[5]: self.input('resolution run %d high %f' % \ (run_number, run[6])) run_number = 0 for run in self._runs: run_number += 1 if run[7]: Debug.write('Run %d corresponds to sweep %s' % \ (run_number, run[7])) if run[5]: continue self.input('sdcorrection same') # FIXME this is a bit of a hack - should be better determined # than this... if Flags.get_small_molecule(): #self.input('sdcorrection tie sdfac 0.707 0.3 tie sdadd 0.01 0.05') #self.input('reject all 30') self.input('sdcorrection fixsdb') if self._secondary and self._surface_tie: self.input('tie surface %.4f' % self._surface_tie) if not self._surface_link: self.input('unlink all') # assemble the scales command if self._mode == 'rotation': scale_command = 'scales rotation spacing %f' % self._spacing if self._secondary: nterm = int(self._secondary) if self._fixed_secondary_lmax: scale_command += ' secondary %d %d absorption %d %d' % \ (nterm, nterm - 1, nterm, nterm - 1) else: scale_command += ' secondary %d absorption %d' % \ (nterm, nterm) if self._bfactor: scale_command += ' bfactor on' if self._brotation: scale_command += ' brotation %f' % \ self._brotation else: scale_command += ' bfactor off' if self._tails: scale_command += ' tails' self.input(scale_command) else: scale_command = 'scales batch' if self._bfactor: scale_command += ' bfactor on' if self._brotation: scale_command += ' brotation %f' % \ self._brotation else: scale_command += ' brotation %f' % \ self._spacing else: scale_command += ' bfactor off' if self._tails: scale_command += ' tails' self.input(scale_command) # Debug.write('Scaling command: "%s"' % scale_command) # next any 'generic' parameters if self._resolution: self.input('resolution %f' % self._resolution) if self._resolution_by_run != { }: # FIXME 20/NOV/06 this needs implementing somehow... pass self.input('cycles %d' % self._cycles) if self._anomalous: self.input('anomalous on') else: self.input('anomalous off') if self._scalepack: self.input('output polish unmerged') elif self._chef_unmerged: self.input('output unmerged together') else: self.input('output unmerged') # run using previously determined scales if self._scales_file: self.input('onlymerge') self.input('restore %s' % self._scales_file) self.close_wait() # check for errors if True: # try: try: self.check_for_errors() self.check_ccp4_errors() self.check_aimless_error_negative_scale_run() self.check_aimless_errors() except Exception, e: Chatter.write( "Aimless failed, see log file for more details:\n %s" %self.get_log_file()) raise status = 'OK' Debug.write('Aimless status: %s' % status) if 'Error' in status: raise RuntimeError, '[AIMLESS] %s' % status
def _sort_together_data_ccp4(self): '''Sort together in the right order (rebatching as we go) the sweeps we want to scale together.''' max_batches = 0 for e in self._sweep_handler.get_epochs(): if Flags.get_small_molecule(): continue si = self._sweep_handler.get_sweep_information(e) pname, xname, dname = si.get_project_info() sname = si.get_sweep_name() for epoch in self._sweep_handler.get_epochs(): si = self._sweep_handler.get_sweep_information(epoch) hklin = si.get_reflections() # limit the reflections - e.g. if we are re-running the scaling step # on just a subset of the integrated data hklin = si.get_reflections() limit_batch_range = None for sweep in PhilIndex.params.xia2.settings.sweep: if sweep.id == sname and sweep.range is not None: limit_batch_range = sweep.range break if limit_batch_range is not None: Debug.write('Limiting batch range for %s: %s' %(sname, limit_batch_range)) start, end = limit_batch_range hklout = os.path.splitext(hklin)[0] + '_tmp.mtz' FileHandler.record_temporary_file(hklout) rb = self._factory.Pointless() rb.set_hklin(hklin) rb.set_hklout(hklout) rb.limit_batches(start, end) si.set_reflections(hklout) si.set_batches(limit_batch_range) # keep a count of the maximum number of batches in a block - # this will be used to make rebatch work below. hklin = si.get_reflections() md = self._factory.Mtzdump() md.set_hklin(hklin) md.dump() batches = md.get_batches() if 1 + max(batches) - min(batches) > max_batches: max_batches = max(batches) - min(batches) + 1 datasets = md.get_datasets() Debug.write('In reflection file %s found:' % hklin) for d in datasets: Debug.write('... %s' % d) dataset_info = md.get_dataset_info(datasets[0]) Debug.write('Biggest sweep has %d batches' % max_batches) max_batches = nifty_power_of_ten(max_batches) # then rebatch the files, to make sure that the batch numbers are # in the same order as the epochs of data collection. counter = 0 for epoch in self._sweep_handler.get_epochs(): si = self._sweep_handler.get_sweep_information(epoch) rb = self._factory.Rebatch() hklin = si.get_reflections() pname, xname, dname = si.get_project_info() sname = si.get_sweep_name() hklout = os.path.join(self.get_working_directory(), '%s_%s_%s_%s_integrated.mtz' % \ (pname, xname, dname, sname)) first_batch = min(si.get_batches()) si.set_batch_offset(counter * max_batches - first_batch + 1) rb.set_hklin(hklin) rb.set_first_batch(counter * max_batches + 1) rb.set_project_info(pname, xname, dname) rb.set_hklout(hklout) new_batches = rb.rebatch() # update the "input information" si.set_reflections(hklout) si.set_batches(new_batches) # update the counter & recycle counter += 1 s = self._factory.Sortmtz() hklout = os.path.join(self.get_working_directory(), '%s_%s_sorted.mtz' % \ (self._scalr_pname, self._scalr_xname)) s.set_hklout(hklout) for epoch in self._sweep_handler.get_epochs(): s.add_hklin(self._sweep_handler.get_sweep_information( epoch).get_reflections()) s.sort() # verify that the measurements are in the correct setting # choice for the spacegroup hklin = hklout hklout = hklin.replace('sorted.mtz', 'temp.mtz') if not self.get_scaler_reference_reflection_file(): p = self._factory.Pointless() FileHandler.record_log_file('%s %s pointless' % \ (self._scalr_pname, self._scalr_xname), p.get_log_file()) if len(self._sweep_handler.get_epochs()) > 1: p.set_hklin(hklin) else: # permit the use of pointless preparation... epoch = self._sweep_handler.get_epochs()[0] p.set_hklin(self._prepare_pointless_hklin( hklin, self._sweep_handler.get_sweep_information( epoch).get_integrater().get_phi_width())) if self._scalr_input_spacegroup: Debug.write('Assigning user input spacegroup: %s' % \ self._scalr_input_spacegroup) p.decide_spacegroup() spacegroup = p.get_spacegroup() reindex_operator = p.get_spacegroup_reindex_operator() Debug.write('Pointless thought %s (reindex as %s)' % \ (spacegroup, reindex_operator)) spacegroup = self._scalr_input_spacegroup reindex_operator = 'h,k,l' elif Flags.get_small_molecule() and False: p.decide_pointgroup() spacegroup = p.get_pointgroup() reindex_operator = p.get_reindex_operator() Debug.write('Pointless thought %s (reindex as %s)' % \ (spacegroup, reindex_operator)) self._scalr_likely_spacegroups = [spacegroup] else: p.decide_spacegroup() spacegroup = p.get_spacegroup() reindex_operator = p.get_spacegroup_reindex_operator() Debug.write('Pointless thought %s (reindex as %s)' % \ (spacegroup, reindex_operator)) if self._scalr_input_spacegroup: self._scalr_likely_spacegroups = [self._scalr_input_spacegroup] else: self._scalr_likely_spacegroups = p.get_likely_spacegroups() Chatter.write('Likely spacegroups:') for spag in self._scalr_likely_spacegroups: Chatter.write('%s' % spag) Chatter.write( 'Reindexing to first spacegroup setting: %s (%s)' % \ (spacegroup, clean_reindex_operator(reindex_operator))) else: md = self._factory.Mtzdump() md.set_hklin(self.get_scaler_reference_reflection_file()) md.dump() spacegroup = md.get_spacegroup() reindex_operator = 'h,k,l' self._scalr_likely_spacegroups = [spacegroup] Debug.write('Assigning spacegroup %s from reference' % \ spacegroup) # then run reindex to set the correct spacegroup ri = self._factory.Reindex() ri.set_hklin(hklin) ri.set_hklout(hklout) ri.set_spacegroup(spacegroup) ri.set_operator(reindex_operator) ri.reindex() FileHandler.record_temporary_file(hklout) # then resort the reflections (one last time!) s = self._factory.Sortmtz() temp = hklin hklin = hklout hklout = temp s.add_hklin(hklin) s.set_hklout(hklout) s.sort() # done preparing! self._prepared_reflections = s.get_hklout() return
def _scale(self): '''Actually scale all of the data together.''' from xia2.Handlers.Environment import debug_memory_usage debug_memory_usage() Journal.block( 'scaling', self.get_scaler_xcrystal().get_name(), 'XSCALE', {'scaling model':'default (all)'}) epochs = self._sweep_information.keys() epochs.sort() xscale = self.XScale() xscale.set_spacegroup_number(self._xds_spacegroup) xscale.set_cell(self._scalr_cell) Debug.write('Set CELL: %.2f %.2f %.2f %.2f %.2f %.2f' % \ tuple(self._scalr_cell)) Debug.write('Set SPACEGROUP_NUMBER: %d' % \ self._xds_spacegroup) Debug.write('Gathering measurements for scaling') for epoch in epochs: # get the prepared reflections reflections = self._sweep_information[epoch][ 'prepared_reflections'] # and the get wavelength that this belongs to dname = self._sweep_information[epoch]['dname'] sname = self._sweep_information[epoch]['sname'] # and the resolution range for the reflections intgr = self._sweep_information[epoch]['integrater'] Debug.write('Epoch: %d' % epoch) Debug.write('HKL: %s (%s/%s)' % (reflections, dname, sname)) resolution_low = intgr.get_integrater_low_resolution() resolution_high = self._scalr_resolution_limits.get((dname, sname), 0.0) resolution = (resolution_high, resolution_low) xscale.add_reflection_file(reflections, dname, resolution) # set the global properties of the sample xscale.set_crystal(self._scalr_xname) xscale.set_anomalous(self._scalr_anomalous) if Flags.get_zero_dose(): Debug.write('Switching on zero-dose extrapolation') xscale.set_zero_dose() debug_memory_usage() xscale.run() scale_factor = xscale.get_scale_factor() Debug.write('XSCALE scale factor found to be: %e' % scale_factor) # record the log file pname = self._scalr_pname xname = self._scalr_xname FileHandler.record_log_file('%s %s XSCALE' % \ (pname, xname), os.path.join(self.get_working_directory(), 'XSCALE.LP')) # check for outlier reflections and if a number are found # then iterate (that is, rerun XSCALE, rejecting these outliers) if not Flags.get_quick() and Flags.get_remove(): if len(xscale.get_remove()) > 0: xscale_remove = xscale.get_remove() current_remove = [] final_remove = [] # first ensure that there are no duplicate entries... if os.path.exists(os.path.join( self.get_working_directory(), 'REMOVE.HKL')): for line in open(os.path.join( self.get_working_directory(), 'REMOVE.HKL'), 'r').readlines(): h, k, l = map(int, line.split()[:3]) z = float(line.split()[3]) if not (h, k, l, z) in current_remove: current_remove.append((h, k, l, z)) for c in xscale_remove: if c in current_remove: continue final_remove.append(c) Debug.write( '%d alien reflections are already removed' % \ (len(xscale_remove) - len(final_remove))) else: # we want to remove all of the new dodgy reflections final_remove = xscale_remove remove_hkl = open(os.path.join( self.get_working_directory(), 'REMOVE.HKL'), 'w') z_min = Flags.get_z_min() rejected = 0 # write in the old reflections for remove in current_remove: z = remove[3] if z >= z_min: remove_hkl.write('%d %d %d %f\n' % remove) else: rejected += 1 Debug.write('Wrote %d old reflections to REMOVE.HKL' % \ (len(current_remove) - rejected)) Debug.write('Rejected %d as z < %f' % \ (rejected, z_min)) # and the new reflections rejected = 0 used = 0 for remove in final_remove: z = remove[3] if z >= z_min: used += 1 remove_hkl.write('%d %d %d %f\n' % remove) else: rejected += 1 Debug.write('Wrote %d new reflections to REMOVE.HKL' % \ (len(final_remove) - rejected)) Debug.write('Rejected %d as z < %f' % \ (rejected, z_min)) remove_hkl.close() # we want to rerun the finishing step so... # unless we have added no new reflections if used: self.set_scaler_done(False) if not self.get_scaler_done(): Chatter.write('Excluding outlier reflections Z > %.2f' % Flags.get_z_min()) if Flags.get_egg(): for record in ttt(): Chatter.write(record) return debug_memory_usage() # now get the reflection files out and merge them with aimless output_files = xscale.get_output_reflection_files() wavelength_names = output_files.keys() # these are per wavelength - also allow for user defined resolution # limits a la bug # 3183. No longer... for epoch in self._sweep_information.keys(): input = self._sweep_information[epoch] intgr = input['integrater'] rkey = input['dname'], input['sname'] if intgr.get_integrater_user_resolution(): dmin = intgr.get_integrater_high_resolution() if not self._user_resolution_limits.has_key(rkey): self._scalr_resolution_limits[rkey] = dmin self._user_resolution_limits[rkey] = dmin elif dmin < self._user_resolution_limits[rkey]: self._scalr_resolution_limits[rkey] = dmin self._user_resolution_limits[rkey] = dmin self._scalr_scaled_refl_files = { } self._scalr_statistics = { } max_batches = 0 mtz_dict = { } project_info = { } for epoch in self._sweep_information.keys(): pname = self._scalr_pname xname = self._scalr_xname dname = self._sweep_information[epoch]['dname'] reflections = os.path.split( self._sweep_information[epoch]['prepared_reflections'])[-1] project_info[reflections] = (pname, xname, dname) for epoch in self._sweep_information.keys(): self._sweep_information[epoch]['scaled_reflections'] = None debug_memory_usage() for wavelength in wavelength_names: hklin = output_files[wavelength] xsh = XDSScalerHelper() xsh.set_working_directory(self.get_working_directory()) ref = xsh.split_and_convert_xscale_output( hklin, 'SCALED_', project_info, 1.0 / scale_factor) for hklout in ref.keys(): for epoch in self._sweep_information.keys(): if os.path.split(self._sweep_information[epoch][ 'prepared_reflections'])[-1] == \ os.path.split(hklout)[-1]: if self._sweep_information[epoch][ 'scaled_reflections'] != None: raise RuntimeError, 'duplicate entries' self._sweep_information[epoch][ 'scaled_reflections'] = ref[hklout] del(xsh) debug_memory_usage() for epoch in self._sweep_information.keys(): hklin = self._sweep_information[epoch]['scaled_reflections'] dname = self._sweep_information[epoch]['dname'] sname = self._sweep_information[epoch]['sname'] hkl_copy = os.path.join(self.get_working_directory(), 'R_%s' % os.path.split(hklin)[-1]) if not os.path.exists(hkl_copy): shutil.copyfile(hklin, hkl_copy) # let's properly listen to the user's resolution limit needs... if self._user_resolution_limits.get((dname, sname), False): resolution = self._user_resolution_limits[(dname, sname)] else: resolution = self._estimate_resolution_limit(hklin) Chatter.write('Resolution for sweep %s/%s: %.2f' % \ (dname, sname, resolution)) if not (dname, sname) in self._scalr_resolution_limits: self._scalr_resolution_limits[(dname, sname)] = resolution self.set_scaler_done(False) else: if resolution < self._scalr_resolution_limits[(dname, sname)]: self._scalr_resolution_limits[(dname, sname)] = resolution self.set_scaler_done(False) debug_memory_usage() if not self.get_scaler_done(): Debug.write('Returning as scaling not finished...') return self._sort_together_data_xds() highest_resolution = min(self._scalr_resolution_limits.values()) self._scalr_highest_resolution = highest_resolution Debug.write('Scaler highest resolution set to %5.2f' % \ highest_resolution) if not self.get_scaler_done(): Debug.write('Returning as scaling not finished...') return sdadd_full = 0.0 sdb_full = 0.0 # ---------- FINAL MERGING ---------- sc = self._factory.Aimless() FileHandler.record_log_file('%s %s aimless' % (self._scalr_pname, self._scalr_xname), sc.get_log_file()) sc.set_resolution(highest_resolution) sc.set_hklin(self._prepared_reflections) sc.set_new_scales_file('%s_final.scales' % self._scalr_xname) if sdadd_full == 0.0 and sdb_full == 0.0: pass else: sc.add_sd_correction('both', 1.0, sdadd_full, sdb_full) for epoch in epochs: input = self._sweep_information[epoch] start, end = (min(input['batches']), max(input['batches'])) rkey = input['dname'], input['sname'] run_resolution_limit = self._scalr_resolution_limits[rkey] sc.add_run(start, end, exclude = False, resolution = run_resolution_limit, name = input['sname']) sc.set_hklout(os.path.join(self.get_working_directory(), '%s_%s_scaled.mtz' % \ (self._scalr_pname, self._scalr_xname))) if self.get_scaler_anomalous(): sc.set_anomalous() sc.multi_merge() FileHandler.record_xml_file('%s %s aimless xml' % (self._scalr_pname, self._scalr_xname), sc.get_xmlout()) data = sc.get_summary() loggraph = sc.parse_ccp4_loggraph() standard_deviation_info = { } for key in loggraph.keys(): if 'standard deviation v. Intensity' in key: dataset = key.split(',')[-1].strip() standard_deviation_info[dataset] = transpose_loggraph( loggraph[key]) resolution_info = { } for key in loggraph.keys(): if 'Analysis against resolution' in key: dataset = key.split(',')[-1].strip() resolution_info[dataset] = transpose_loggraph( loggraph[key]) # and also radiation damage stuff... batch_info = { } for key in loggraph.keys(): if 'Analysis against Batch' in key: dataset = key.split(',')[-1].strip() batch_info[dataset] = transpose_loggraph( loggraph[key]) # finally put all of the results "somewhere useful" self._scalr_statistics = data self._scalr_scaled_refl_files = copy.deepcopy( sc.get_scaled_reflection_files()) self._scalr_scaled_reflection_files = { } # also output the unmerged scalepack format files... sc = self._factory.Aimless() sc.set_resolution(highest_resolution) sc.set_hklin(self._prepared_reflections) sc.set_scalepack() for epoch in epochs: input = self._sweep_information[epoch] start, end = (min(input['batches']), max(input['batches'])) rkey = input['dname'], input['sname'] run_resolution_limit = self._scalr_resolution_limits[rkey] sc.add_run(start, end, exclude = False, resolution = run_resolution_limit, name = input['sname']) sc.set_hklout(os.path.join(self.get_working_directory(), '%s_%s_scaled.mtz' % \ (self._scalr_pname, self._scalr_xname))) if self.get_scaler_anomalous(): sc.set_anomalous() sc.multi_merge() self._scalr_scaled_reflection_files['sca_unmerged'] = { } self._scalr_scaled_reflection_files['mtz_unmerged'] = { } for dataset in sc.get_scaled_reflection_files().keys(): hklout = sc.get_scaled_reflection_files()[dataset] # then mark the scalepack files for copying... scalepack = os.path.join(os.path.split(hklout)[0], os.path.split(hklout)[1].replace( '_scaled', '_scaled_unmerged').replace('.mtz', '.sca')) self._scalr_scaled_reflection_files['sca_unmerged'][ dataset] = scalepack FileHandler.record_data_file(scalepack) mtz_unmerged = os.path.splitext(scalepack)[0] + '.mtz' self._scalr_scaled_reflection_files['mtz_unmerged'][dataset] = mtz_unmerged FileHandler.record_data_file(mtz_unmerged) if PhilIndex.params.xia2.settings.merging_statistics.source == 'cctbx': for key in self._scalr_scaled_refl_files: stats = self._compute_scaler_statistics( self._scalr_scaled_reflection_files['mtz_unmerged'][key]) self._scalr_statistics[ (self._scalr_pname, self._scalr_xname, key)] = stats # convert reflection files to .sca format - use mtz2various for this self._scalr_scaled_reflection_files['sca'] = { } self._scalr_scaled_reflection_files['hkl'] = { } for key in self._scalr_scaled_refl_files: f = self._scalr_scaled_refl_files[key] scaout = '%s.sca' % f[:-4] m2v = self._factory.Mtz2various() m2v.set_hklin(f) m2v.set_hklout(scaout) m2v.convert() self._scalr_scaled_reflection_files['sca'][key] = scaout FileHandler.record_data_file(scaout) if Flags.get_small_molecule(): hklout = '%s.hkl' % f[:-4] m2v = self._factory.Mtz2various() m2v.set_hklin(f) m2v.set_hklout(hklout) m2v.convert_shelx() self._scalr_scaled_reflection_files['hkl'][key] = hklout FileHandler.record_data_file(hklout) return