class nmref(object): def __init__(self, start_pdb, target_pr, ntotal, nmodes, max_rmsd, backbone_scale, prefix): self.counter = 0 self.nmode_init = ntotal self.nmodes = nmodes self.topn = 10 self.Niter = 0 self.modes = flex.int(range(self.nmode_init)) + 7 self.cutoff = 10 self.weighted = True ##### for histogram ## r, self.expt = self.readPr(target_pr) self.expt2 = flex.pow(self.expt, 2.0) #print list(self.expt) start_name = start_pdb self.pdb = PDB(start_name) self.natom = self.pdb.natm self.scale_factor = backbone_scale self.pdb.Hessian = self.pdb.Hessian(self.cutoff, self.nmode_init, self.scale_factor) self.root = prefix self.dMax = max(r) self.n_slot = r.size() self.scale = 0 self.drmsd = max_rmsd self.Rmax2 = self.natom * (self.drmsd)**2.0 self.step_size = sqrt(self.Rmax2 / self.nmodes) * 2.0 self.new_indx = flex.int(range(self.natom)) self.stop = False self.minscore = 1e20 self.minDev = 0 #minimum deviations of refined structures, compared to refined structure from the previous step self.optNum = 20 #number of iterations between geometry optimization self.iterate() def iterate(self): self.n1 = self.nmodes if (self.Niter > 0): # need to build PDB object from the last PDB file iter_name = self.root + str(self.Niter) + ".pdb" self.pdb = PDB(iter_name) self.pdb.Hessian = self.pdb.Hessian(self.cutoff, self.nmode_init, self.scale_factor) # Generate random normal modes self.modes = flex.int(range(self.nmodes - 1)) + 7 self.modes.append( int(random.random() * (self.nmode_init - self.nmodes)) + 7 + self.nmodes) self.scale = 0 candidates = [] score = [] for kk in range(self.topn * 10): if (kk == 0): vec = flex.random_double(self.nmodes) * 0 else: vec = (flex.random_double(self.nmodes) - 0.5) * 2 * self.step_size result = self.target(vec) insert = 0 for ii in range(len(score)): if (score[ii] > result): score.insert(ii, result) candidates.insert(ii, vec) insert = 1 break if (insert == 0): score.append(result) candidates.append(vec) for kk in range(self.topn): self.starting_simplex = [] cand = candidates[kk] for ii in range(self.n1): self.starting_simplex.append( flex.double(self.orth(ii, self.n1)) * self.step_size + cand) self.starting_simplex.append(cand) self.optimizer = simplex.simplex_opt(dimension=self.n1, matrix=self.starting_simplex, evaluator=self, tolerance=1e-8) self.x = self.optimizer.get_solution() candidates[kk] = self.x.deep_copy() score[kk] = self.optimizer.get_score() minscore = min(score[0:self.topn]) if ((self.Niter % self.optNum) > 1): self.stopCheck(minscore) self.updateScore(minscore) minvec = candidates[score.index(minscore)] new_coord = flex.vec3_double(self.pdb.NMPerturb(self.modes, minvec)) self.Niter = self.Niter + 1 iter_name = self.root + str(self.Niter) + ".pdb" self.pdb.writePDB(new_coord, iter_name) if (self.Niter % self.optNum == 0): geo_opt(iter_name, iter_name) if (not self.stop): # if(self.Niter < 100): self.iterate() def readPr(self, filename): r = flex.double() pr = flex.double() file = open(filename, 'r') total = 0.0 for line in file: keys = line.split() r.append(float(keys[0])) pr.append(float(keys[1])) total += float(keys[1]) return r, pr / total def updateScore(self, minscore): if ((self.Niter % self.optNum) == 0): self.minscore = minscore elif (minscore < self.minscore): self.minDev += (self.minscore - minscore) self.minscore = minscore def stopCheck(self, minscore): print self.minscore, minscore, self.minDev, self.counter if (self.minscore < minscore): self.stop = True # if(minscore < (self.minDev*5.0)): if (self.minscore - minscore < (self.minDev * 0.01)): self.stop = True def orth(self, indx, n): vec = [0] * n vec[indx] = 1 return vec def target(self, vector): self.counter += 1 result = 0 length = flex.sum(flex.pow(vector, 2)) if (length > self.Rmax2): result = 100000000000000 else: new_coord = self.pdb.NMPerturb(self.modes, vector) self.pdb.model.updateDistArray(flex.vec3_double(new_coord)) dist_array = self.pdb.model.getDistArray() new_pr = self.pdb.model.Histogram(dist_array, self.dMax, self.n_slot) if (self.weighted): if (self.scale == 0): self.scale = float(flex.mean( flex.abs(self.expt - new_pr))) / float( flex.mean(self.expt)) self.scale2 = self.scale * self.scale result = flex.pow((self.expt - new_pr), 2.0) result = flex.sum( flex.exp(-self.scale2 * self.expt2 / (result + 10 - 12)) * result) else: result = flex.sum(flex.pow((self.expt - new_pr), 2.0)) result = result * 100 return result
class nmref(object): def __init__(self, start_pdb, target_I, ntotal, nmodes, max_rmsd, backbone_scale, prefix, weight='i', method='rtb', log='tmp.log'): self.counter = 0 self.nmode_init = ntotal self.method = method self.nmodes = nmodes self.topn = 10 self.Niter = 0 self.modes = flex.int(range(self.nmode_init)) + 7 self.cutoff = 8 self.weighted = True self.log = open(log, 'w') self.chi = open(prefix + '.chi', 'w') pdb_inp = pdb.input(file_name=start_pdb) crystal_symmetry = pdb_inp.xray_structure_simple().\ cubic_unit_cell_around_centered_scatterers( buffer_size = 10).crystal_symmetry() self.pdb_processor = process_pdb_file_srv( crystal_symmetry=crystal_symmetry) self.expt = saxs_read_write.read_standard_ascii_qis(target_I) self.q = self.expt.q self.expt_I = self.expt.i self.expt_s = self.expt.s if (self.q.size() > 100): self.q = self.interpolation(self.q, n_pts=30) self.expt_I = flex.linear_interpolation(self.expt.q, self.expt.i, self.q) self.expt_s = flex.linear_interpolation(self.expt.q, self.expt.s, self.q) #if( weight=='i'): self.expt_s = self.expt_I for aa, bb, cc in zip(self.q, self.expt_I, self.expt_s): print aa, bb, cc start_name = start_pdb self.pdb = PDB(start_name, method=self.method) self.she_engine = she.she(start_name, self.q) self.natom = self.pdb.natm self.scale_factor = backbone_scale self.pdb.Hessian(self.cutoff, self.nmode_init, self.scale_factor) self.root = prefix self.scale = 0 self.drmsd = max_rmsd if (self.method == 'rtb'): self.drmsd = self.drmsd * 2 self.Rmax2 = self.natom * (self.drmsd)**2.0 self.step_size = sqrt(self.Rmax2 / self.nmodes) * 6.0 self.new_indx = flex.int(range(self.natom)) self.stop = False self.minscore = 1e20 self.minDev = 0 #minimum deviations of refined structures, compared to refined structure from the previous step self.optNum = 1 #number of iterations between geometry optimization ### set running env for pulchra ### import libtbx.env_config env = libtbx.env_config.unpickle() self.pulchra = env.build_path + '/pulchra/exe/pulchra' self.iterate() self.log.close() self.chi.close() def interpolation(self, q_array, qmax=0.3, n_pts=100): qmin = q_array[0] #qmax = q_array[-1] qmax = min(q_array[-1], qmax) q_array = flex.double( range(n_pts)) / float(n_pts) * (qmax - qmin) + qmin return q_array def iterate(self): self.n1 = self.nmodes if (self.Niter > 0): # need to build PDB object from the last PDB file iter_name = self.root + str(self.Niter) + ".pdb" self.pdb = PDB(iter_name, method=self.method) self.pdb.Hessian(self.cutoff, self.nmode_init, self.scale_factor) # Generate random normal modes self.modes = flex.int(range(self.nmodes - 1)) + 7 self.modes.append( int(random.random() * (self.nmode_init - self.nmodes)) + 7 + self.nmodes) self.scale = 0 candidates = [] score = [] for kk in range(self.topn * 10): if (kk == 0): vec = flex.random_double(self.nmodes) * 0 else: vec = (flex.random_double(self.nmodes) - 0.5) * 2 * self.step_size result = self.target(vec) insert = 0 for ii in range(len(score)): if (score[ii] > result): score.insert(ii, result) candidates.insert(ii, vec) insert = 1 break if (insert == 0): score.append(result) candidates.append(vec) for kk in range(self.topn): self.starting_simplex = [] cand = candidates[kk] for ii in range(self.n1): self.starting_simplex.append( flex.double(self.orth(ii, self.n1)) * self.step_size + cand) self.starting_simplex.append(cand) self.optimizer = simplex.simplex_opt(dimension=self.n1, matrix=self.starting_simplex, evaluator=self, monitor_cycle=5, tolerance=1e-2) self.x = self.optimizer.get_solution() candidates[kk] = self.x.deep_copy() score[kk] = self.optimizer.get_score() minscore = min(score[0:self.topn]) print self.Niter, minscore, self.counter print >> self.chi, self.Niter, minscore if ((self.Niter % self.optNum) > 1): self.stopCheck(minscore) self.updateScore(minscore) minvec = candidates[score.index(minscore)] new_coord = self.pdb.NMPerturb(self.modes, minvec) print list(minvec) self.Niter = self.Niter + 1 iter_base = self.root + str(self.Niter) iter_name = iter_base + ".pdb" self.pdb.writePDB(new_coord, iter_name) if (self.Niter % self.optNum == 0): print self.pulchra run_command(command=self.pulchra + ' ' + iter_name) run_command(command='mv ' + iter_base + '.rebuilt.pdb ' + iter_name) #processed_pdb, pdb_inp = self.pdb_processor.process_pdb_files( pdb_file_names=[iter_name] ) #new_coord = geo_opt(processed_pdb, self.log) #self.pdb.writePDB(new_coord,iter_name) # if(not self.stop): if (self.Niter < 40): self.iterate() def readPr(self, filename): r = flex.double() pr = flex.double() file = open(filename, 'r') total = 0.0 for line in file: keys = line.split() r.append(float(keys[0])) pr.append(float(keys[1])) total += float(keys[1]) return r, pr / total def updateScore(self, minscore): if ((self.Niter % self.optNum) == 0): self.minscore = minscore elif (minscore < self.minscore): self.minDev = self.minscore - minscore self.minscore = minscore def stopCheck(self, minscore): print self.minscore, minscore, self.minDev if (self.minscore < minscore): self.stop = True # if(minscore < (self.minDev*5.0)): if (self.minscore - minscore < (self.minDev * 0.01)): self.stop = True def orth(self, indx, n): vec = [0] * n vec[indx] = 1 return vec def target(self, vector): self.counter += 1 result = 0 length = flex.sum_sq(vector) if (length > self.Rmax2): result = 1e30 else: new_coord = self.pdb.NMPerturb(self.modes, vector) self.she_engine.engine.update_coord(new_coord, self.new_indx) new_I = self.she_engine.engine.I() var = self.expt_s s, o = she.linear_fit(new_I[:5], self.expt_I[:5], var[:5]) result = flex.sum( flex.pow2((self.expt_I - (s * new_I + o)) / self.expt_s)) # result = flex.sum_sq( (self.expt_I-new_I) /self.expt_s ) #print self.pdb.r, result return result
class nmref(object): def __init__(self, start_pdb, target_I, ntotal, nmodes, max_rmsd, backbone_scale, prefix, weight='i', method='rtb', log='tmp.log'): self.counter = 0 self.nmode_init = ntotal self.nmodes = 3 #nmodes self.method = method self.topn = 3 self.Niter = 0 self.modes = flex.int(range(self.nmode_init)) + 7 self.cutoff = 12 self.weighted = True self.log = open(log, 'w') pdb_inp = pdb.input(file_name=start_pdb) crystal_symmetry = pdb_inp.xray_structure_simple().\ cubic_unit_cell_around_centered_scatterers( buffer_size = 10).crystal_symmetry() # uc=cctbx.uctbx.unit_cell("300,300,300,90,90,90") # crystal_symmetry=cctbx.crystal.symmetry(uc, 'P1') self.pdb_processor = process_pdb_file_srv( crystal_symmetry=crystal_symmetry) self.expt = saxs_read_write.read_standard_ascii_qis(target_I) self.q = self.expt.q self.expt_I = self.expt.i self.expt_s = self.expt.s if (self.q.size() > 50): self.q = self.interpolation(self.q, n_pts=50) self.expt_I = flex.linear_interpolation(self.expt.q, self.expt.i, self.q) self.expt_s = flex.linear_interpolation(self.expt.q, self.expt.s, self.q) if (weight == 'i'): self.expt_s = self.expt_I self.time_nm = 0 self.time_she = 0 start_name = start_pdb self.pdb = PDB(start_name, method=self.method) self.she_engine = she.she(start_name, self.q) self.natom = self.pdb.natm self.scale_factor = backbone_scale time1 = time.time() self.nmode = self.pdb.Hessian(self.cutoff, self.nmode_init, self.scale_factor) self.time_nm += (time.time() - time1) self.root = prefix self.drmsd = max_rmsd self.Rmax2 = self.natom * (self.drmsd)**2.0 self.step_size = sqrt(self.Rmax2 / self.nmodes) * 5.0 self.new_indx = flex.int(range(self.natom)) self.stop = False self.minscore = 1e20 self.minDev = 0 #minimum deviations of refined structures, compared to refined structure from the previous step self.optNum = 10 #number of iterations between geometry optimization self.iterate() self.log.close() print "time used for NM : %d" % self.time_nm print "time used for she: %d" % self.time_she def interpolation(self, q_array, n_pts=100): qmin = q_array[0] qmax = q_array[-1] q_array = flex.double( range(n_pts)) / float(n_pts) * (qmax - qmin) + qmin return q_array def iterate(self): if (self.Niter > 0): # need to build PDB object from the last PDB file iter_name = self.root + str(self.Niter) + ".pdb" t1 = time.time() self.pdb = PDB(iter_name, method=self.method) self.nmode = self.pdb.Hessian(self.cutoff, self.nmode_init, self.scale_factor) - 1 self.time_nm += (time.time() - t1) self.n1 = self.nmodes + 1 score = [] candidates = [] for kk in range(self.nmode_init - self.nmodes): self.modes = flex.int(range(self.nmodes)) + 7 self.modes.append(kk + 7 + self.nmodes) self.starting_simplex = [] cand = flex.double(self.n1, 0) for ii in range(self.n1): self.starting_simplex.append( flex.double(self.orth(ii, self.n1)) * self.step_size + cand) self.starting_simplex.append(cand) self.optimizer = simplex.simplex_opt(dimension=self.n1, matrix=self.starting_simplex, evaluator=self, monitor_cycle=4, tolerance=1e-1) self.x = self.optimizer.get_solution() candidates.append(self.x.deep_copy()) score.append(self.optimizer.get_score()) minscore = min(score[0:self.topn]) print self.Niter, minscore, self.counter if ((self.Niter % self.optNum) > 1): self.stopCheck(minscore) self.updateScore(minscore) minvec = candidates[score.index(minscore)] new_coord = flex.vec3_double(self.pdb.NMPerturb(self.modes, minvec)) self.Niter = self.Niter + 1 iter_name = self.root + str(self.Niter) + ".pdb" self.pdb.writePDB(new_coord, iter_name) if (self.Niter % self.optNum == 0): processed_pdb, pdb_inp = self.pdb_processor.process_pdb_files( pdb_file_names=[iter_name]) new_coord = geo_opt(processed_pdb, self.log) self.pdb.writePDB(new_coord, iter_name) if (not self.stop): # if(self.Niter < 50): self.iterate() def updateScore(self, minscore): if ((self.Niter % self.optNum) == 0): self.minscore = minscore elif (minscore < self.minscore): self.minDev = self.minscore - minscore self.minscore = minscore def stopCheck(self, minscore): print self.minscore, minscore, self.minDev if (self.minscore < minscore): self.stop = True # if(minscore < (self.minDev*5.0)): if (self.minscore - minscore < (self.minDev * 0.01)): self.stop = True def orth(self, indx, n): vec = [0] * n vec[indx] = 1 return vec def target(self, vector): self.counter += 1 result = 0 length = flex.sum(flex.pow(vector, 2)) if (length > self.Rmax2): result = 1e30 else: new_coord = self.pdb.NMPerturb(self.modes, vector) t1 = time.time() self.she_engine.engine.update_coord(flex.vec3_double(new_coord), self.new_indx) new_I = self.she_engine.engine.I() self.time_she += (time.time() - t1) var = self.expt_s s, o = she.linear_fit(new_I, self.expt_I, var) result = flex.sum( flex.pow2((self.expt_I - (s * new_I + o)) / self.expt_s)) return result