#!/usr/bin/python import os,sys,string from process import process import common par=common.parameter class ref(process): name="macromolecular reciprocal space refinement" short_name="model refinement" supported_progs=["refmac"] supported_params = {} supported_params['target'] = par( desc='Experiment/refinement target', typ=str, cap=True ) supported_params['cycles'] = par( desc='Number of model refinement cycles', typ=(int,bool) ) supported_params['beta'] = par( desc='Bias parameter ("phcomb" only)', typ=float ) supported_params['phcomb'] = par( desc='Refine with restrains to an inputted F and phase', typ=bool ) supported_params['low_res_par'] = par( desc='Refine using low resolution specific parameters', typ=bool ) supported_params['comb_with_typ'] = par( desc='Combine phases with the specified mapcoef type (only if "phcomb")', typ=str ) supported_params['catch_output'] = par( desc='Catch program output continously', typ=bool ) supported_params['no_substr'] = par( desc='Refine input partial model excluding substructure atoms', typ=bool ) def TreatInOutPar(self, set_all_par=False): if not self.GetProg(supported=True): self.AddProg('refmac') if self.GetVirtPar('phcomb') and not self.GetVirtPar('comb_with_typ'): self.SetVirtPar('comb_with_typ', 'densmod') # determine the resolution of the relevant dataset against which we'll refine... obj,N=self.inp.GetTargetObjects(self.GetParam('target'),no_model=True,no_warn=True) if obj is None: # if no success then we try to assume Rice (this is useful eg in emulate mode when not all exists) obj,N=self.inp.GetTargetObjects('RICE',no_model=True,inten=None) if not obj: common.Error('The input objects for target Rice of {0} could not be retrieved'.format(self.name)) ref_data = obj['f'] if 'f' in obj and obj['f'] else obj['f+'] resol=ref_data.GetResolution(pro=self,accept_none=True) if (self.GetVirtPar('low_res_par') is not False and resol and resol>3.0): self.SetVirtPar('low_res_par') # changing the default number of cycles here in case of a separate refinement step # (setting cycles to False restores the program default) if self.IsTrueOrNoneParam('cycles') and (not self.parent_process or self.parent_process.nick=='crank'): self.SetVirtPar('cycles', 15) # disabling hydrogens by default for low res if self.GetParam('low_res_par') and self.GetProg('refmac') and not self.GetProg('refmac').IsKey('make'): self.GetProg('refmac').SetKey('make',('hydrogens','no')) # setting default solvent params - testing only! #if self.GetProg(supported=True).nick=='refmac' and not self.GetProg(supported=True).IsKey('solvent'): # self.GetProg(supported=True).SetKey('solvent',('yes','VDWProb','1.4','IONProb','0.8','RSHRink','0.8')) if self.GetParam('catch_output') is False: self.Info('Continous log output disabled.') if self.GetParam('no_substr') is None and self.inp.Get(has_atomtypes=True) and self.GetCrankParent(): # if this refinement is the last crank subprocess, we do not want substr. atoms by default (finalizing) if self.inp.Get(has_atomtypes=True).GetAtomType() in ('S','SE') and self.GetParam('target') in ('MLHL','RICE') and \ self is self.GetCrankParent().processes[-1]: self.SetParam('no_substr') elif not self.parent_process or self.parent_process.nick=='crank' or self.GetParam('catch_output'): self.GetProg(supported=True).interact_output=True process.TreatInOutPar(self,set_all_par) def RunPreprocess(self,*args,**kwargs): process.RunPreprocess(self,*args,**kwargs) modpart=self.inp.Get('model',typ='partial',filetype='pdb') if not self.GetParam('no_substr'): # merge partial model and substructure model into one if both are supplied for the same crystal if modpart and modpart is self.inp.Get('model',typ=('partial+substr','partial'),filetype='pdb'): modsubst=self.inp.Get('model',typ='substr',xname=modpart.xname,filetype='pdb') if not modsubst and (modpart.xname=='native' or 'native' in modpart.custom) and self.GetParam('target')=='SAD': modsubst=self.inp.Get('model',typ='substr',filetype='pdb') if modsubst: pdbmerge=self.AddProg('pdbmerge',propagate_inp=False,propagate_out=False) pdbmerge.inp.Set([modpart,modsubst]) pdbmerge.SetKey('nomerge') pdbmerge.Run() self.inp.Add(pdbmerge.out.Get('model')) self.programs.remove(pdbmerge) elif not modpart or modpart is not self.inp.Get('model',filetype='pdb'): # make sure partial model will be used (without substructure) if not modpart and self.inp.Get('model',typ='partial+substr',filetype='pdb'): sepsub=self.AddProcess('sepsubstrprot',propagate_inp=False,propagate_out=False) sepsub.inp.Set(self.inp.Get('model',typ='partial+substr',filetype='pdb')) sepsub.Run() modpart=sepsub.out.Get('model',typ='partial') if modpart: self.inp.AddCopy(modpart) # a hack to prevent refmac from choking by some chain ID # refmac chokes by _ and \ , maybe more will be needed to add here... bad_ids = ('\\', '_', '\x7f', '\x80','\x81','\x82','\x83','\x84', '"', '\'', '#') mod=self.inp.Get('model',filetype='pdb') if mod: pdbcur=self.AddProg('pdbcur') pdbcur.SetKey('summarise') pdbcur.inp.Set(mod) pdbcur.Run() chain_ids = pdbcur.GetStat('chain_ids') for bad_id in set(bad_ids).intersection(chain_ids): for new_id in string.printable: if new_id not in chain_ids and new_id not in bad_ids and new_id not in pdbcur.bad_chain_ids: pdbcur.SetKey('renchain', ("\""+bad_id+"\"", "\""+new_id+"\"") ) chain_ids.append(new_id) break if pdbcur.IsKey('renchain'): pdbcur.Run() mod=self.inp.Add(pdbcur.out.Get('model')) if set(pdbcur.bad_chain_ids).intersection(chain_ids).intersection(bad_ids): # rename substr. chains if ids that pdbcur does not accept are present pdbset=self.AddProg('pdbset') pdbset.inp.Set(mod) for bad_id in set(pdbcur.bad_chain_ids).intersection(chain_ids).intersection(bad_ids): new_id = next(nid for nid in string.printable if nid not in chain_ids and nid not in bad_ids and nid not in pdbcur.bad_chain_ids and nid not in pdbset.bad_chain_ids) pdbset.SetKey('chain',(bad_id,new_id)) chain_ids.append(new_id) pdbset.Run() self.inp.Add(pdbset.out.Get('model')) self.programs.remove(pdbset) self.programs.remove(pdbcur) # low res par if self.GetVirtPar('low_res_par') and self.GetProg().nick=='refmac': refmac=self.GetProg() self.save_refmac=refmac.BackupAnyPars() if not refmac.IsKey('RIDG') or (refmac.GetKey('RIDG') and not 'DIST' in refmac.GetKey('RIDG',as_list=True)): refmac.SetKey('RIDG',['DIST','SIGM','0.1']) #if not refmac.IsKey('MAPC') or not 'SHAR' in refmac.GetKey('MAPC'): # if (self.parent_process.nick!='dmfull' or self.parent_process.GetParam('dmcyc')==self.parent_process.cyc) \ # and self.parent_process.nick!='refatompick': # #self.GetProg().SetKey('MAPC',['SHAR',gcx.GetStat('wilson_B')/2]) # refmac.SetKey('MAPC', ['SHAR','ALPH','0.2']) # Refmac NCSR LOCAL (as of 5.8.0155) crashes if non-numerical insertion codes are used (generated by Buccaneer if there are many chains)... #if not refmac.IsKey('NCSR'): # mon_obj=self.inp.Get(has_monomers_asym=True) # mon_obj.GetSequenceString() # if not mon_obj: # matthews=self.AddProcess('matthews', propagate_out=False) # matthews.Run() # mon_asym=matthews.GetProg().GetStat('monomers_asym') # self.processes.remove(matthews) # if (mon_obj and (mon_obj.monomers_asym>1 or mon_obj.seq_monomers>1)) or (not mon_obj and mon_asym>1): # refmac.SetKey('NCSR', 'LOCAL') def RunPostprocess(self,restore=True,*args,**kwargs): refmac=self.GetProg() if hasattr(self,'save_refmac'): refmac.RestoreAnyPars(self.save_refmac) self.R, self.Rfree = refmac.GetStat('rfact')[-1], (refmac.GetStat('rfree', accept_none=True) or [None])[-1] self.fom=refmac.GetStat('fom') self.i2_R, self.i2_Rfree = self.R, self.Rfree if self.parent_process.nick != 'dmfull': self.Info('{0} after refinement is {1}'.format(refmac.stat['rfact'].name, self.R)) if self.rv_report: self.rv_report.Text("Result:") self.rv_report.Text(' '+'Final R factor is {0}'.format(self.R)) rfree=refmac.GetStat('rfree',accept_none=True) if rfree: self.Info('{0} after refinement is {1}'.format(refmac.stat['rfree'].name, rfree[-1])) if self.rv_report: self.rv_report.Text(' Final Rfree factor is {0}'.format(rfree[-1])) # make sure that there is an output substructure - this may be removed later if not needed if self.out.Get('model',typ='partial+substr') and not self.out.Get('model',typ='substr'): separate_models=self.AddProcess('sepsubstrprot') separate_models.inp.Set(self.out.Get('model',typ='partial+substr')) # filter on input substr. chains, to make sure that SE/S built by Buccaneer rebuilding is not included in substr. substr=self.inp.Get('model',typ='substr',has_atomtypes=True) if substr and substr.GetAtomType in ('S','SE'): separate_models.inp.Add(self.inp.Get('model',typ='substr')) separate_models.Run() self.processes.remove(separate_models) if self.rv_report: self.rv_plotref = self.rv_report.Plot( 'R factor vs refinement cycle', "Cycle", "R factors", intx=True ) Rs = refmac.GetStat('rfact') cyc = [i for i in range(len(Rs))] self.rv_R = self.rv_plotref.PlotLine(["x",cyc],["R",Rs]) if rfree: self.rv_R = self.rv_plotref.PlotLine(["x",cyc],["Rfree",rfree]) if not self.parent_process or not self.parent_process.ccp4i2: out_pdb = self.out.Get('model',typ=('partial','partial+substr')).GetFileName() out_mtz = self.out.Get('mapcoef',typ='combined').GetFileName() out_map = self.out.Get('mapcoef',typ='weighted',filetype='map',conv_opts=['no_rewrite']).GetFileName('map') out_dmap = self.out.Get('mapcoef',typ='diff',filetype='map',conv_opts=['no_rewrite']).GetFileName('map') self.rv_report.Text("
Output:") self.rv_files = self.rv_report.DataFile(out_pdb, "xyz", "Refined model and map") self.rv_files.DataFile(out_mtz, "hkl:map") self.rv_files.DataFile(out_map, "hkl:ccp4_map") self.rv_files.DataFile(out_dmap, "hkl:ccp4_dmap", flush=True) process.RunPostprocess(self,restore,*args,**kwargs) def UpdateInfo(self,line,popen): # copies over the log (to be interpreted as loggraph) if self.opened_loggraph: self.LGInfo(line)