Example #1
0
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
Example #2
0
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
Example #3
0
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