def __init__( self, scorefxn, steps, temp, cooling_rate ): ''' ''' assert isScoreFxn( scorefxn ) self._log = "" self._scorefxn = scorefxn self._steps = steps # MC steps per annealing cycle self._temperature = temp # declare objects self.__fragidx_pose = FragIdxPose() self._initialization = "random" self._cooling_rate = cooling_rate self._anneal_temp = 0.0 # recover_low ( quench ) self._quench = False self._lowest_score_pose = FragIdxPose() self._record_trajectory = False
def __init__(self, score_table, wts, null_frag_score, pose={}): """ 1. Score methods: function call operations > Given a pose, return the total_score > Given a frag_idx, return the score relatively to the rest of the residues in the pose (update the pose?) 2. Evaluation method: return stats for evaluation/debug purposes > Per-residue stats: decomposite scores for each residue level > Summarize score: overall results for a pose """ assert isScoreTable(score_table) assert isWeights(wts) self._score_table = score_table self._wts = wts self._null_frag_score = null_frag_score # Private Member self.__pose = FragIdxPose() # selected_frags_dict
class SimulatedAnnealing: ''' 1. easy to dump the object as a resulting model, and the trajectory? 2. linear cooling rate ''' def __init__( self, scorefxn, steps, temp, cooling_rate ): ''' ''' assert isScoreFxn( scorefxn ) self._log = "" self._scorefxn = scorefxn self._steps = steps # MC steps per annealing cycle self._temperature = temp # declare objects self.__fragidx_pose = FragIdxPose() self._initialization = "random" self._cooling_rate = cooling_rate self._anneal_temp = 0.0 # recover_low ( quench ) self._quench = False self._lowest_score_pose = FragIdxPose() self._record_trajectory = False def set_annealing_temperature( self ): ''' ''' self._anneal_temp = round( self._temperature*self._cooling_rate, 1 ) self._temperature -= self._anneal_temp def run( self, runid ): ''' run id is a identification for a model to dump ''' self.__fragidx_pose.clear() self.__fragidx_pose.initialization( self._scorefxn.get_density_score_dict(), self._initialization ) # default initialize by random #print self.__fragidx_pose.show_state( "initialization" ) mc = MonteCarlo( self._scorefxn, self._temperature ) mc.apply( self.__fragidx_pose, self._steps ) # to prevent a silly bug that at the very first state SCORE==0, such that you wouldn't lower than that during high temperatures sampling self._lowest_score_pose = self.__fragidx_pose.clone() tracker = TrajectoryTracker( runid ) tag = "model_" + str( runid ) while self._temperature >=0 : # it would never reach this criteria if self._quench: self.recover_low() # retrieve the lowest-score pose from previous runs mc.apply( self.__fragidx_pose, self._steps ) residual_pose = self._scorefxn.residualize_pose() # residual_pose will be filled with #print residual_pose.show_state( tag + "_" + str( self._temperature ) ) self.set_annealing_temperature() # update self._temperature if self._temperature == mc.get_temperature(): break mc.set_temperature( self._temperature ) if self._record_trajectory: tracker.save( self._temperature, self.__fragidx_pose ) tracker.save( self._temperature, self._scorefxn.residualize_pose() ) tracker.dump_pickle( tag ) residual_pose.show_state( tag + "_final", True ) # True for verbose showing all residues states def set_to_quench( self ): self._quench = True def record_trajectory( self ): self._record_trajectory = True def recover_low( self ): # recover_low ''' last accept score pose, and lowest score pose; the MC.recover_low has this is because it uses Metropolis to thermally accept pose ''' # this is for the first around # need to think about a better way to initiate it if not self._lowest_score_pose._initialized: self._lowest_score_pose._initialized = self.__fragidx_pose # .total_score() method will re-evaluate pose whenever it is called if self.__fragidx_pose.total_score() > self._lowest_score_pose.total_score(): stdout.write("recover previous found lowest-score pose with score: %s\n" % self._lowest_score_pose.total_score() ) self.__fragidx_pose = self._lowest_score_pose.clone() else: stdout.write("found a newer lowest-score pose\n") self._lowest_score_pose = self.__fragidx_pose.clone() def dump( self, id ): return def quench( self ): return
class ScoreFunction: """ The ScoreFucntion object must initialize by having object ScoreTable read in as Dictionary. > 130909: should I move pose storage out of the class? """ def __init__(self, score_table, wts, null_frag_score, pose={}): """ 1. Score methods: function call operations > Given a pose, return the total_score > Given a frag_idx, return the score relatively to the rest of the residues in the pose (update the pose?) 2. Evaluation method: return stats for evaluation/debug purposes > Per-residue stats: decomposite scores for each residue level > Summarize score: overall results for a pose """ assert isScoreTable(score_table) assert isWeights(wts) self._score_table = score_table self._wts = wts self._null_frag_score = null_frag_score # Private Member self.__pose = FragIdxPose() # selected_frags_dict def __call__(self, input): """ Two operations: 1. scorefxn( pose ): # ** noteworthy: the pose object here is Pose > assign Residue object for each position, and > return a total score of it 2. scorefxn( frag_idx ): > return frag score for the frag_idx to a pose """ assert isPose(input) or isFragIdx(input) if isPose(input): # a residual pose """ 1. update the residue of the verbose_pose to be composed of Residue objects 2. return a total score """ residual_pose = input self.update_pose(residual_pose) # the frag_idx in the input has been update to self.__pose # use the new ScoreTable to rescore it residual_pose output_pose = Pose() for frag_idx in self.__pose: output_pose.update_residue(self.score_evaluator(frag_idx, True)) return output_pose elif isFragIdx(input): """ return a residue score """ return self.score_evaluator(input) def residualize_pose(self): """ Pose() has methods to evaluate the state """ residual_pose = Pose() for frag_idx in self.__pose: residual_pose.update_residue(self.score_evaluator(frag_idx, True)) return residual_pose def get_density_score_dict(self): return self._score_table.get_density_score_dict() def get_candidate_frags(self, pos): """ return candidate fragid objects from a position as a list """ return self._score_table.get_candidate_frags(pos) def clone(self): """ would it work? don't know yet """ return copy.deepcopy(self) def update_score_table(self, new_score_table): assert isScoreTable(new_score_table) self._score_table = new_score_table def update_pose(self, pose): """ simply assign the coming pose to the in-object pose """ assert isFragIdxPose(pose) or isPose(pose) if isFragIdxPose(pose): self.__pose = pose elif isPose(pose): for residue in pose: pos = residue._frag_id._pos # print pos, residue._score frag_idx = self._score_table.frag_to_index(residue._frag_id()) self.__pose.update_residue(pos, frag_idx) def set_weights(self, new_wts): """ This is in particular useful when you want to interactive use this class to rescore by changing the weights """ assert isWeights(new_wts) self._wts = new_wts def set_null_frag_score(self, new_null_frag_score): """ This is being used whenever low acceptance rate of MonteCarlo object - lower the null_frag_score """ assert new_null_frag_score self._null_frag_score = new_null_frag_score #### the main method to score #### def score_evaluator(self, candidate_frag_idx, verbose=False): """ Given a candidate_frag_idx, return a frag_score of the fragment to the selected ones, 1. null_frag - return null_frag_score 2. frag - return frag_score """ assert isFragIdxPose( self.__pose ) # is a Pose instance, and has been initialized; this is because when instance ScoreFunction class, you don't have to give it a Pose class # skip null fragment: this is for when calculating total_score if isNullFrag(candidate_frag_idx): if verbose: candidate_frag_id = FragID(self._score_table.index_to_frag(candidate_frag_idx)) # make FragID object return Residue(candidate_frag_id, self._null_frag_score) else: return self._null_frag_score density_score, all_overlap_score, all_closab_score, all_clash_score = (0.0,) * 4 # one-body score: try: density_score = self._score_table.density_score_lookup(candidate_frag_idx) density_score *= self._wts._density_score_wt rmsd = self._score_table.rmsd_lookup(candidate_frag_idx) except KeyError: stderr.write("Error: %s does not have density score\n" % candidate_frag_idx) exit() # two-body score: the candidate_frag to the rest selected ones """ for each candidate placement, calculate frag_score against all selected frags """ for selected_frag_idx in self.__pose: # pose as an iterator of positions if selected_frag_idx == candidate_frag_idx: continue # no two-body score to itself if isNullFrag(selected_frag_idx): continue # you don't need to compare to null fragment # overlap using table to do a fast lookup if self._score_table.overlapping_check_table_lookup(candidate_frag_idx, selected_frag_idx): # The reason why you don't need to look up clash score for overlapping fragments is because it has been considered while calculating overlap_score try: overlap_score = self._score_table.overlap_score_lookup(candidate_frag_idx, selected_frag_idx) overlap_score *= self._wts._overlap_score_wt all_overlap_score += overlap_score except KeyError: stderr.write( "WARNING: %s %s don't have overlap score\n" % ( self._score_table.index_to_frag(candidate_frag_idx), self._score_table.index_to_frag(selected_frag_id), ) ) continue else: try: closab_score = self._score_table.closab_score_lookup(candidate_frag_idx, selected_frag_idx) closab_score *= self._wts._closab_score_wt all_closab_score += closab_score clash_score = self._score_table.clash_score_lookup(candidate_frag_idx, selected_frag_idx) clash_score *= self._wts._clash_score_wt all_clash_score += clash_score except KeyError: stderr.write( "WARNING: %s %s don't have nonoverlap score\n" % ( self._score_table.index_to_frag(candidate_frag_idx), self._score_table.index_to_frag(selected_frag_id), ) ) continue #### end of calculating "the candidate_frag" to the selected ones #### frag_score = density_score + all_overlap_score + all_closab_score + all_clash_score if verbose: """ This is to be used at the very end of stage of simulation to dump residual decomposed scores; preferably will only be called in scorefxn.show_state() """ candidate_frag_id = FragID(self._score_table.index_to_frag(candidate_frag_idx)) # make FragID object residue = Residue( candidate_frag_id, frag_score, density_score, all_overlap_score, all_closab_score, all_clash_score, rmsd ) # missing Boltzmann return residue else: return frag_score