src.serena.analysis.scoring

File to handles teh calsses for dealing with scores

  1"""
  2File to handles teh calsses for dealing with scores
  3"""
  4
  5from dataclasses import dataclass
  6from typing import List
  7
  8from serena.analysis.judge_pool import JudgesResults
  9from serena.analysis.investigator import InvestigatorResults
 10
 11@dataclass
 12class BasicScoreResults():
 13    """
 14    Basic scores for switchyness
 15    """
 16    total_score:float = 0
 17    functional_switch_score:float = 0
 18    powerful_switch_score:float = 0
 19    on_off_switch_score:float = 0
 20    bonuses:float = 0
 21    penalties:float = 0
 22
 23@dataclass
 24class AdvancedScoreResults():
 25    """
 26    Bonuses that amplify ability to decern switchyness
 27    """
 28    lmv_bonus:float =0
 29    lmv_penalty:float = 0    
 30    comp_bonus:float = 0
 31    comp_penalty:float = 0
 32    excess_struct_penalty:float=0
 33    total_score:float = 0
 34    
 35
 36
 37class SerenaScoring():
 38    """
 39    Scoring the results from the judges decisions
 40    """
 41    def __init__(self) -> None:
 42        pass
 43
 44    def basic_score_groups(self, judge_results:JudgesResults, investigator: InvestigatorResults)->BasicScoreResults:
 45        """
 46        Perform basic scoring functions that determine switchyness of rna sequence
 47        """
 48        #inititalization data
 49        found_functional_switch: List[int] = judge_results.comp_switch_judge.switchable_groups_list 
 50        found_powerful_switch: List[int] = judge_results.comp_switch_judge.powerfull_groups_list
 51        found_on_off_switch: List[int] = judge_results.lmv_switch_judge.on_off_groups_list
 52
 53
 54        bound_range_index_plus_one:List[int] = judge_results.comp_switch_judge.switchable_groups_list
 55        is_powerful_switch:bool = judge_results.comp_switch_judge.is_powerful_switch
 56        is_functional_switch:bool = judge_results.comp_switch_judge.is_good_switch
 57        is_off_on_switch:bool = judge_results.lmv_switch_judge.is_on_off_switch
 58
 59        #SetupScores
 60        total_score:float = 0
 61        functional_switch_score:float = 0
 62        powerful_switch_score:float = 0
 63        on_off_switch_score:float = 0
 64        bonuses:float = 0
 65        penalties:float = 0
 66
 67        #main scores
 68        if is_powerful_switch is True:
 69            multiplier:int = 1
 70            message:str = 'Potential High Fold Change'
 71            #result_messages = self.log_message(message, result_messages) 
 72            powerful_switch_score = powerful_switch_score + (len(found_powerful_switch) * multiplier)
 73        
 74        if is_functional_switch is True: 
 75            multiplier:int = 2
 76            message:str = "Potential  Functional Switch"
 77            #result_messages = self.log_message(message, result_messages)
 78            functional_switch_score = functional_switch_score + (len(found_functional_switch) * multiplier)
 79        
 80        if is_off_on_switch is True:
 81            multiplier:int = 1
 82            message:str = "Potential  off/on leaning design via LMV"
 83            #result_messages = self.log_message(message, result_messages)
 84            #on_off_switch_score= on_off_switch_score + (len(found_on_off_switch) * multiplier)
 85            on_off_switch_score = on_off_switch_score + 1
 86
 87        #now do penalties for assertion of unbound
 88        if judge_results.comp_switch_judge.is_unbound_asserted is True:
 89            multiplier:int = 1
 90            penalties = penalties + (len(judge_results.comp_switch_judge.unbound_asserted_groups_list)* multiplier)
 91
 92        #now bonuses
 93        #for value in found_functional_switch:
 94        #    if value >= 0 and value <= 1 and value != -1:
 95        #        message:str = "Confirmned good. Add bonus point for point for functional being in first two groups"
 96        #        #result_messages = self.log_message(message, result_messages)
 97        #        #functional_switch_score += 1
 98        #        bonuses += 1
 99
100            #if value in found_on_off_switch:
101            #    message:str = "Add bonus for functional being in range of on/off prediction"
102            #    #result_messages = self.log_message(message, result_messages)
103            #    #functional_switch_score += 1
104            #    bonuses += .5
105
106        #for value in found_powerful_switch:
107        #    if value >= 0 and value <= 1 and value != -1:
108        #        message:str = "Confirmned good. Add bonus point for high performing being in first two groups"
109        #        #result_messages = self.log_message(message, result_messages)
110        #        #powerful_switch_score += 1
111        #        bonuses += 1
112
113            #if value in found_on_off_switch:
114            #    message:str = "Add bonus for high performing being in range of on/off prediction"
115            #    #result_messages = self.log_message(message, result_messages)
116            #    #powerful_switch_score += 1
117            #    bonuses += .5
118        
119        #only count a design sas good if functionial has at leat 1 point if not
120        #it is probbaly flase powerfull
121        #if functional_switch_score > 0:        
122        total_score = powerful_switch_score + functional_switch_score + on_off_switch_score + bonuses - penalties
123        #else:
124        #    total_score = 0
125
126        basic_score_results:BasicScoreResults = BasicScoreResults(total_score=total_score,
127                                                                  functional_switch_score=functional_switch_score,
128                                                                  powerful_switch_score=powerful_switch_score,
129                                                                  on_off_switch_score=on_off_switch_score,
130                                                                  bonuses=bonuses,
131                                                                  penalties=penalties)
132
133        return basic_score_results
134      
135    def excessive_structures_penalties(self, num_structures: int, excess_divisor:float,excess_limit:float):
136        """
137        Algorithm for determining the penalty for excessive number of secondary structures in the 
138        whole ensemble
139        """
140        #excess_divisor:float = 2000#2500
141        penalty:float = 0
142        if num_structures > excess_limit:
143            #factor:float = ((float(num_structures) - excess_limit) / excess_divisor ) * .5
144            factor:float = (float(num_structures) / excess_divisor ) * .5
145            message:str = f'Exsessive structs. Found:{num_structures} penalizing {factor} points'
146            #result_messages = self.log_message(message, result_messages)
147            sixty_range_num:float = 50000#15000
148            #penalize for too many structs
149            penalty += factor
150            if num_structures > sixty_range_num:
151                message:str = f'Significant excess structures found: found {num_structures - sixty_range_num} structures over limit of {sixty_range_num}'
152                #result_messages = self.log_message(message, result_messages)
153                message:str = f'Eterna_score should be ~60 for temp group and could be good design currently has high penalty for excess structures and now yet one more penalty'
154                #result_messages = self.log_message(message, result_messages)
155                penalty += .5
156        
157        return penalty
158    
159    def advanced_score_groups(self, judge_results:JudgesResults, investigator: InvestigatorResults):
160        """
161        Bonuses and penalties that affect the fine tunning of swithyness determinations
162        """
163        lmv_bonus:float =0
164        lmv_penalty:float = 0    
165        comp_bonus:float = 0
166        comp_penalty:float = 0
167        total_score:float = 0
168
169        comp_less_ratio: float = investigator.lmv_assertions.comp_compare_to_mfe.count('<') / investigator.num_groups
170        com_great_ratio: float = investigator.lmv_assertions.comp_compare_to_mfe.count('>')  / investigator.num_groups
171        message:str = f'ev comp great:{com_great_ratio}, ev comp less:{comp_less_ratio}'
172        #result_messages = self.log_message(message, result_messages)
173        if com_great_ratio > comp_less_ratio and com_great_ratio >= .7:
174            message:str = "EV for comparison struct is Greater MORE OFTEN than unbound mfe so add bonus"
175            #result_messages = self.log_message(message, result_messages)
176            #lmv_bonus += 1
177        elif comp_less_ratio > com_great_ratio and comp_less_ratio >= .5:
178            message:str = "EV for mfe struct is GREATER MORE OFTEN than unbound mfe so penatly"
179            #result_messages = self.log_message(message, result_messages)
180            #lmv_penalty += 1
181            if comp_less_ratio >= .8:
182                message:str = "EV for mfe is GREATER EXTRA MORE OFTEN then mfe so minus penalty point"
183                #result_messages = self.log_message(message, result_messages)
184            #    lmv_penalty += 1
185        
186        if investigator.comparison_eval_results.nuc_penatly_count > 0:
187            if investigator.comparison_eval_results.BUratio_list[0] >= .6:
188                new_penalty: float = 1#investigator.comparison_eval_results.nuc_penatly_count * 1
189                message:str = f'Bound unbound ratio higher than 75% so it will most likely just fold into what should have been a switch so minus {new_penalty} points'
190                #result_messages = self.log_message(message, result_messages)
191                comp_penalty += new_penalty
192            #elif BUratio_list[0] > .60 and BUratio_list[1] < .3:
193            #    new_penalty: float = nuc_penatly_count * 1
194            #    message:str = f'Bound unbound ratio higher than 50% and then the 2nd energy group less than 20% so it will likely be blocked from switching so minus {new_penalty} points'
195            #    result_messages = self.log_message(message, result_messages)
196            #    score = score - new_penalty            
197            else:
198                bonus: float =  1           
199                message:str = f'Bound nucs found in first energy group. Design is primed to switch so add bonus of {bonus} points'
200                #result_messages = self.log_message(message, result_messages)
201                comp_bonus += bonus
202
203        #penalize for being too strong of a switch and only forms in the 2nd
204        #bound:float = investigator.comp_nuc_counts.comparison_nuc_counts[index].bound_count
205        #unbound: float = investigator.comp_nuc_counts.comparison_nuc_counts[index].unbound_count
206        #for index, ratios in enumerate(investigator.comparison_eval_results.ratios):
207        #    if ratios.unbound_to_total_ratio <= .15 and :
208        #        comp_penalty += 1
209        #        #its probably too strong of a switch
210        is_good_actually:bool = False
211       
212        
213        #for index, ratios in enumerate(investigator.lmv_values.lmv_comps):
214        #    if ratios.lmv_rel.ev_normalized >= 40:
215        #        lmv_penalty +=1 
216        
217        if investigator.lmv_values.lmv_comps[0].lmv_mfe.ev_normalized > 13 and investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized > 13:
218            #it is a bit too unstable in the first group and will probably fall apart
219            lmv_penalty +=1
220        
221        if investigator.lmv_values.lmv_comps[0].lmv_mfe.ev_normalized < 13 and investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized < 13 and investigator.lmv_values.lmv_comps[0].lmv_mfe.ev_normalized > 5:
222            if investigator.lmv_values.lmv_comps[1].lmv_comp.ev_normalized < 20:# and investigator.lmv_values.lmv_comps[1].lmv_comp.ev_normalized < 20:
223                lmv_bonus +=1
224            else:
225                #it is probably a bit too unstable to act like a proper switch
226                lmv_penalty +=1
227        
228        #if investigator.lmv_values.lmv_comps[0].lmv_mfe.ev_normalized < 5 and investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized < 5:
229        #    #not likely to pull out of the single state as the first group is too strong for the mfe
230        #    lmv_penalty +=1
231        index_0_mfe:float = 0
232        for index, lmv_comps in enumerate(investigator.lmv_values.lmv_comps):
233            if index == 0:
234                index_0_mfe = lmv_comps.lmv_mfe.ev_normalized
235            if index_0_mfe == 1:
236                #it probably has a very low struct count as this indicates group 1 has no variation from mfe
237                if lmv_comps.lmv_mfe.ev_normalized < 3 and index > 0:
238                    lmv_penalty +=1
239                if lmv_comps.lmv_mfe.ev_normalized < 5 and index > 3:
240                    lmv_penalty +=1
241                if investigator.total_structures_ensemble > 1000:
242                    #too high of struct count for mfe to be so low so penalty I think
243                    lmv_penalty +=1
244            elif index_0_mfe > 1:
245                #it probably has a very low struct count
246                if lmv_comps.lmv_mfe.ev_normalized < 2 and index == 0:
247                    lmv_penalty +=1
248                if lmv_comps.lmv_mfe.ev_normalized < 8 and index > 0:
249                    lmv_penalty +=1
250                if lmv_comps.lmv_mfe.ev_normalized < 12 and index > 2:
251                    lmv_penalty +=1
252            #else:
253            #    if lmv_comps.lmv_comp.ev_normalized < 10 and lmv_comps.lmv_mfe.ev_normalized < 10:
254            #        lmv_penalty +=1
255        
256        for index, ratios in enumerate(investigator.comparison_eval_results.ratios):
257            if ratios.bound_ratio > .3 and ratios.bound_ratio < 1:
258                comp_penalty +=1
259            #if ratios.bound_to_both_ratio < 0:
260                #comp_penalty +=1
261        #for index, ratios in enumerate(investigator.comparison_eval_results.ratios):
262            if ratios.last_bound_ratio > 5.0 or ratios.last_unbound_ratio > 5.0:
263                if investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized > 15 and investigator.lmv_values.lmv_comps[index].lmv_comp.ev_normalized > 25:
264                    comp_penalty +=1   
265                elif investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized < 15 and investigator.lmv_values.lmv_comps[index].lmv_comp.ev_normalized < 25:
266                    is_good_actually = True
267        #for index, ratios in enumerate(investigator.comparison_eval_results.ratios):
268            if ratios.both_nuc_total >= .9:
269                comp_penalty +=1 
270                
271        #not sure if I want to use... i was ify about before and it seams not fully baked in implementatiuon. 
272        # need to make a ticket for this funciton
273        #if is_good_switch is True and bound_to_both_ratio >= 0.08:
274        #    message:str = "Low number of both and mfe nucs in relation to bound. Add bonus point"
275        #    result_messages = self.log_message(message, result_messages)
276        #    score= score + 1
277        excess_limit:float = 35000#this is based on new data 7500
278        excess_divisor:float = 2000#2500
279        excess_struct_penalty:float = self.excessive_structures_penalties(num_structures=investigator.total_structures_ensemble,
280                                                                    excess_limit=excess_limit,
281                                                                    excess_divisor=excess_divisor)
282        if excess_struct_penalty > 5 and is_good_actually is True:
283            #disregard the penatly
284            total_score = lmv_bonus - lmv_penalty + comp_bonus - comp_penalty - (excess_struct_penalty/2)
285        else:            
286            total_score = lmv_bonus - lmv_penalty + comp_bonus - comp_penalty - excess_struct_penalty
287            
288        advanced_score_response: AdvancedScoreResults = AdvancedScoreResults(lmv_bonus=lmv_bonus,
289                                                                             lmv_penalty=lmv_penalty,
290                                                                             comp_bonus=comp_bonus,
291                                                                             comp_penalty=comp_penalty,
292                                                                             excess_struct_penalty=excess_struct_penalty,
293                                                                             total_score=total_score)
294        return advanced_score_response
295
296    
@dataclass
class BasicScoreResults:
12@dataclass
13class BasicScoreResults():
14    """
15    Basic scores for switchyness
16    """
17    total_score:float = 0
18    functional_switch_score:float = 0
19    powerful_switch_score:float = 0
20    on_off_switch_score:float = 0
21    bonuses:float = 0
22    penalties:float = 0

Basic scores for switchyness

BasicScoreResults( total_score: float = 0, functional_switch_score: float = 0, powerful_switch_score: float = 0, on_off_switch_score: float = 0, bonuses: float = 0, penalties: float = 0)
total_score: float = 0
functional_switch_score: float = 0
powerful_switch_score: float = 0
on_off_switch_score: float = 0
bonuses: float = 0
penalties: float = 0
@dataclass
class AdvancedScoreResults:
24@dataclass
25class AdvancedScoreResults():
26    """
27    Bonuses that amplify ability to decern switchyness
28    """
29    lmv_bonus:float =0
30    lmv_penalty:float = 0    
31    comp_bonus:float = 0
32    comp_penalty:float = 0
33    excess_struct_penalty:float=0
34    total_score:float = 0

Bonuses that amplify ability to decern switchyness

AdvancedScoreResults( lmv_bonus: float = 0, lmv_penalty: float = 0, comp_bonus: float = 0, comp_penalty: float = 0, excess_struct_penalty: float = 0, total_score: float = 0)
lmv_bonus: float = 0
lmv_penalty: float = 0
comp_bonus: float = 0
comp_penalty: float = 0
excess_struct_penalty: float = 0
total_score: float = 0
class SerenaScoring:
 38class SerenaScoring():
 39    """
 40    Scoring the results from the judges decisions
 41    """
 42    def __init__(self) -> None:
 43        pass
 44
 45    def basic_score_groups(self, judge_results:JudgesResults, investigator: InvestigatorResults)->BasicScoreResults:
 46        """
 47        Perform basic scoring functions that determine switchyness of rna sequence
 48        """
 49        #inititalization data
 50        found_functional_switch: List[int] = judge_results.comp_switch_judge.switchable_groups_list 
 51        found_powerful_switch: List[int] = judge_results.comp_switch_judge.powerfull_groups_list
 52        found_on_off_switch: List[int] = judge_results.lmv_switch_judge.on_off_groups_list
 53
 54
 55        bound_range_index_plus_one:List[int] = judge_results.comp_switch_judge.switchable_groups_list
 56        is_powerful_switch:bool = judge_results.comp_switch_judge.is_powerful_switch
 57        is_functional_switch:bool = judge_results.comp_switch_judge.is_good_switch
 58        is_off_on_switch:bool = judge_results.lmv_switch_judge.is_on_off_switch
 59
 60        #SetupScores
 61        total_score:float = 0
 62        functional_switch_score:float = 0
 63        powerful_switch_score:float = 0
 64        on_off_switch_score:float = 0
 65        bonuses:float = 0
 66        penalties:float = 0
 67
 68        #main scores
 69        if is_powerful_switch is True:
 70            multiplier:int = 1
 71            message:str = 'Potential High Fold Change'
 72            #result_messages = self.log_message(message, result_messages) 
 73            powerful_switch_score = powerful_switch_score + (len(found_powerful_switch) * multiplier)
 74        
 75        if is_functional_switch is True: 
 76            multiplier:int = 2
 77            message:str = "Potential  Functional Switch"
 78            #result_messages = self.log_message(message, result_messages)
 79            functional_switch_score = functional_switch_score + (len(found_functional_switch) * multiplier)
 80        
 81        if is_off_on_switch is True:
 82            multiplier:int = 1
 83            message:str = "Potential  off/on leaning design via LMV"
 84            #result_messages = self.log_message(message, result_messages)
 85            #on_off_switch_score= on_off_switch_score + (len(found_on_off_switch) * multiplier)
 86            on_off_switch_score = on_off_switch_score + 1
 87
 88        #now do penalties for assertion of unbound
 89        if judge_results.comp_switch_judge.is_unbound_asserted is True:
 90            multiplier:int = 1
 91            penalties = penalties + (len(judge_results.comp_switch_judge.unbound_asserted_groups_list)* multiplier)
 92
 93        #now bonuses
 94        #for value in found_functional_switch:
 95        #    if value >= 0 and value <= 1 and value != -1:
 96        #        message:str = "Confirmned good. Add bonus point for point for functional being in first two groups"
 97        #        #result_messages = self.log_message(message, result_messages)
 98        #        #functional_switch_score += 1
 99        #        bonuses += 1
100
101            #if value in found_on_off_switch:
102            #    message:str = "Add bonus for functional being in range of on/off prediction"
103            #    #result_messages = self.log_message(message, result_messages)
104            #    #functional_switch_score += 1
105            #    bonuses += .5
106
107        #for value in found_powerful_switch:
108        #    if value >= 0 and value <= 1 and value != -1:
109        #        message:str = "Confirmned good. Add bonus point for high performing being in first two groups"
110        #        #result_messages = self.log_message(message, result_messages)
111        #        #powerful_switch_score += 1
112        #        bonuses += 1
113
114            #if value in found_on_off_switch:
115            #    message:str = "Add bonus for high performing being in range of on/off prediction"
116            #    #result_messages = self.log_message(message, result_messages)
117            #    #powerful_switch_score += 1
118            #    bonuses += .5
119        
120        #only count a design sas good if functionial has at leat 1 point if not
121        #it is probbaly flase powerfull
122        #if functional_switch_score > 0:        
123        total_score = powerful_switch_score + functional_switch_score + on_off_switch_score + bonuses - penalties
124        #else:
125        #    total_score = 0
126
127        basic_score_results:BasicScoreResults = BasicScoreResults(total_score=total_score,
128                                                                  functional_switch_score=functional_switch_score,
129                                                                  powerful_switch_score=powerful_switch_score,
130                                                                  on_off_switch_score=on_off_switch_score,
131                                                                  bonuses=bonuses,
132                                                                  penalties=penalties)
133
134        return basic_score_results
135      
136    def excessive_structures_penalties(self, num_structures: int, excess_divisor:float,excess_limit:float):
137        """
138        Algorithm for determining the penalty for excessive number of secondary structures in the 
139        whole ensemble
140        """
141        #excess_divisor:float = 2000#2500
142        penalty:float = 0
143        if num_structures > excess_limit:
144            #factor:float = ((float(num_structures) - excess_limit) / excess_divisor ) * .5
145            factor:float = (float(num_structures) / excess_divisor ) * .5
146            message:str = f'Exsessive structs. Found:{num_structures} penalizing {factor} points'
147            #result_messages = self.log_message(message, result_messages)
148            sixty_range_num:float = 50000#15000
149            #penalize for too many structs
150            penalty += factor
151            if num_structures > sixty_range_num:
152                message:str = f'Significant excess structures found: found {num_structures - sixty_range_num} structures over limit of {sixty_range_num}'
153                #result_messages = self.log_message(message, result_messages)
154                message:str = f'Eterna_score should be ~60 for temp group and could be good design currently has high penalty for excess structures and now yet one more penalty'
155                #result_messages = self.log_message(message, result_messages)
156                penalty += .5
157        
158        return penalty
159    
160    def advanced_score_groups(self, judge_results:JudgesResults, investigator: InvestigatorResults):
161        """
162        Bonuses and penalties that affect the fine tunning of swithyness determinations
163        """
164        lmv_bonus:float =0
165        lmv_penalty:float = 0    
166        comp_bonus:float = 0
167        comp_penalty:float = 0
168        total_score:float = 0
169
170        comp_less_ratio: float = investigator.lmv_assertions.comp_compare_to_mfe.count('<') / investigator.num_groups
171        com_great_ratio: float = investigator.lmv_assertions.comp_compare_to_mfe.count('>')  / investigator.num_groups
172        message:str = f'ev comp great:{com_great_ratio}, ev comp less:{comp_less_ratio}'
173        #result_messages = self.log_message(message, result_messages)
174        if com_great_ratio > comp_less_ratio and com_great_ratio >= .7:
175            message:str = "EV for comparison struct is Greater MORE OFTEN than unbound mfe so add bonus"
176            #result_messages = self.log_message(message, result_messages)
177            #lmv_bonus += 1
178        elif comp_less_ratio > com_great_ratio and comp_less_ratio >= .5:
179            message:str = "EV for mfe struct is GREATER MORE OFTEN than unbound mfe so penatly"
180            #result_messages = self.log_message(message, result_messages)
181            #lmv_penalty += 1
182            if comp_less_ratio >= .8:
183                message:str = "EV for mfe is GREATER EXTRA MORE OFTEN then mfe so minus penalty point"
184                #result_messages = self.log_message(message, result_messages)
185            #    lmv_penalty += 1
186        
187        if investigator.comparison_eval_results.nuc_penatly_count > 0:
188            if investigator.comparison_eval_results.BUratio_list[0] >= .6:
189                new_penalty: float = 1#investigator.comparison_eval_results.nuc_penatly_count * 1
190                message:str = f'Bound unbound ratio higher than 75% so it will most likely just fold into what should have been a switch so minus {new_penalty} points'
191                #result_messages = self.log_message(message, result_messages)
192                comp_penalty += new_penalty
193            #elif BUratio_list[0] > .60 and BUratio_list[1] < .3:
194            #    new_penalty: float = nuc_penatly_count * 1
195            #    message:str = f'Bound unbound ratio higher than 50% and then the 2nd energy group less than 20% so it will likely be blocked from switching so minus {new_penalty} points'
196            #    result_messages = self.log_message(message, result_messages)
197            #    score = score - new_penalty            
198            else:
199                bonus: float =  1           
200                message:str = f'Bound nucs found in first energy group. Design is primed to switch so add bonus of {bonus} points'
201                #result_messages = self.log_message(message, result_messages)
202                comp_bonus += bonus
203
204        #penalize for being too strong of a switch and only forms in the 2nd
205        #bound:float = investigator.comp_nuc_counts.comparison_nuc_counts[index].bound_count
206        #unbound: float = investigator.comp_nuc_counts.comparison_nuc_counts[index].unbound_count
207        #for index, ratios in enumerate(investigator.comparison_eval_results.ratios):
208        #    if ratios.unbound_to_total_ratio <= .15 and :
209        #        comp_penalty += 1
210        #        #its probably too strong of a switch
211        is_good_actually:bool = False
212       
213        
214        #for index, ratios in enumerate(investigator.lmv_values.lmv_comps):
215        #    if ratios.lmv_rel.ev_normalized >= 40:
216        #        lmv_penalty +=1 
217        
218        if investigator.lmv_values.lmv_comps[0].lmv_mfe.ev_normalized > 13 and investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized > 13:
219            #it is a bit too unstable in the first group and will probably fall apart
220            lmv_penalty +=1
221        
222        if investigator.lmv_values.lmv_comps[0].lmv_mfe.ev_normalized < 13 and investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized < 13 and investigator.lmv_values.lmv_comps[0].lmv_mfe.ev_normalized > 5:
223            if investigator.lmv_values.lmv_comps[1].lmv_comp.ev_normalized < 20:# and investigator.lmv_values.lmv_comps[1].lmv_comp.ev_normalized < 20:
224                lmv_bonus +=1
225            else:
226                #it is probably a bit too unstable to act like a proper switch
227                lmv_penalty +=1
228        
229        #if investigator.lmv_values.lmv_comps[0].lmv_mfe.ev_normalized < 5 and investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized < 5:
230        #    #not likely to pull out of the single state as the first group is too strong for the mfe
231        #    lmv_penalty +=1
232        index_0_mfe:float = 0
233        for index, lmv_comps in enumerate(investigator.lmv_values.lmv_comps):
234            if index == 0:
235                index_0_mfe = lmv_comps.lmv_mfe.ev_normalized
236            if index_0_mfe == 1:
237                #it probably has a very low struct count as this indicates group 1 has no variation from mfe
238                if lmv_comps.lmv_mfe.ev_normalized < 3 and index > 0:
239                    lmv_penalty +=1
240                if lmv_comps.lmv_mfe.ev_normalized < 5 and index > 3:
241                    lmv_penalty +=1
242                if investigator.total_structures_ensemble > 1000:
243                    #too high of struct count for mfe to be so low so penalty I think
244                    lmv_penalty +=1
245            elif index_0_mfe > 1:
246                #it probably has a very low struct count
247                if lmv_comps.lmv_mfe.ev_normalized < 2 and index == 0:
248                    lmv_penalty +=1
249                if lmv_comps.lmv_mfe.ev_normalized < 8 and index > 0:
250                    lmv_penalty +=1
251                if lmv_comps.lmv_mfe.ev_normalized < 12 and index > 2:
252                    lmv_penalty +=1
253            #else:
254            #    if lmv_comps.lmv_comp.ev_normalized < 10 and lmv_comps.lmv_mfe.ev_normalized < 10:
255            #        lmv_penalty +=1
256        
257        for index, ratios in enumerate(investigator.comparison_eval_results.ratios):
258            if ratios.bound_ratio > .3 and ratios.bound_ratio < 1:
259                comp_penalty +=1
260            #if ratios.bound_to_both_ratio < 0:
261                #comp_penalty +=1
262        #for index, ratios in enumerate(investigator.comparison_eval_results.ratios):
263            if ratios.last_bound_ratio > 5.0 or ratios.last_unbound_ratio > 5.0:
264                if investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized > 15 and investigator.lmv_values.lmv_comps[index].lmv_comp.ev_normalized > 25:
265                    comp_penalty +=1   
266                elif investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized < 15 and investigator.lmv_values.lmv_comps[index].lmv_comp.ev_normalized < 25:
267                    is_good_actually = True
268        #for index, ratios in enumerate(investigator.comparison_eval_results.ratios):
269            if ratios.both_nuc_total >= .9:
270                comp_penalty +=1 
271                
272        #not sure if I want to use... i was ify about before and it seams not fully baked in implementatiuon. 
273        # need to make a ticket for this funciton
274        #if is_good_switch is True and bound_to_both_ratio >= 0.08:
275        #    message:str = "Low number of both and mfe nucs in relation to bound. Add bonus point"
276        #    result_messages = self.log_message(message, result_messages)
277        #    score= score + 1
278        excess_limit:float = 35000#this is based on new data 7500
279        excess_divisor:float = 2000#2500
280        excess_struct_penalty:float = self.excessive_structures_penalties(num_structures=investigator.total_structures_ensemble,
281                                                                    excess_limit=excess_limit,
282                                                                    excess_divisor=excess_divisor)
283        if excess_struct_penalty > 5 and is_good_actually is True:
284            #disregard the penatly
285            total_score = lmv_bonus - lmv_penalty + comp_bonus - comp_penalty - (excess_struct_penalty/2)
286        else:            
287            total_score = lmv_bonus - lmv_penalty + comp_bonus - comp_penalty - excess_struct_penalty
288            
289        advanced_score_response: AdvancedScoreResults = AdvancedScoreResults(lmv_bonus=lmv_bonus,
290                                                                             lmv_penalty=lmv_penalty,
291                                                                             comp_bonus=comp_bonus,
292                                                                             comp_penalty=comp_penalty,
293                                                                             excess_struct_penalty=excess_struct_penalty,
294                                                                             total_score=total_score)
295        return advanced_score_response

Scoring the results from the judges decisions

def basic_score_groups( self, judge_results: serena.analysis.judge_pool.JudgesResults, investigator: serena.analysis.investigator.InvestigatorResults) -> src.serena.analysis.scoring.BasicScoreResults:
 45    def basic_score_groups(self, judge_results:JudgesResults, investigator: InvestigatorResults)->BasicScoreResults:
 46        """
 47        Perform basic scoring functions that determine switchyness of rna sequence
 48        """
 49        #inititalization data
 50        found_functional_switch: List[int] = judge_results.comp_switch_judge.switchable_groups_list 
 51        found_powerful_switch: List[int] = judge_results.comp_switch_judge.powerfull_groups_list
 52        found_on_off_switch: List[int] = judge_results.lmv_switch_judge.on_off_groups_list
 53
 54
 55        bound_range_index_plus_one:List[int] = judge_results.comp_switch_judge.switchable_groups_list
 56        is_powerful_switch:bool = judge_results.comp_switch_judge.is_powerful_switch
 57        is_functional_switch:bool = judge_results.comp_switch_judge.is_good_switch
 58        is_off_on_switch:bool = judge_results.lmv_switch_judge.is_on_off_switch
 59
 60        #SetupScores
 61        total_score:float = 0
 62        functional_switch_score:float = 0
 63        powerful_switch_score:float = 0
 64        on_off_switch_score:float = 0
 65        bonuses:float = 0
 66        penalties:float = 0
 67
 68        #main scores
 69        if is_powerful_switch is True:
 70            multiplier:int = 1
 71            message:str = 'Potential High Fold Change'
 72            #result_messages = self.log_message(message, result_messages) 
 73            powerful_switch_score = powerful_switch_score + (len(found_powerful_switch) * multiplier)
 74        
 75        if is_functional_switch is True: 
 76            multiplier:int = 2
 77            message:str = "Potential  Functional Switch"
 78            #result_messages = self.log_message(message, result_messages)
 79            functional_switch_score = functional_switch_score + (len(found_functional_switch) * multiplier)
 80        
 81        if is_off_on_switch is True:
 82            multiplier:int = 1
 83            message:str = "Potential  off/on leaning design via LMV"
 84            #result_messages = self.log_message(message, result_messages)
 85            #on_off_switch_score= on_off_switch_score + (len(found_on_off_switch) * multiplier)
 86            on_off_switch_score = on_off_switch_score + 1
 87
 88        #now do penalties for assertion of unbound
 89        if judge_results.comp_switch_judge.is_unbound_asserted is True:
 90            multiplier:int = 1
 91            penalties = penalties + (len(judge_results.comp_switch_judge.unbound_asserted_groups_list)* multiplier)
 92
 93        #now bonuses
 94        #for value in found_functional_switch:
 95        #    if value >= 0 and value <= 1 and value != -1:
 96        #        message:str = "Confirmned good. Add bonus point for point for functional being in first two groups"
 97        #        #result_messages = self.log_message(message, result_messages)
 98        #        #functional_switch_score += 1
 99        #        bonuses += 1
100
101            #if value in found_on_off_switch:
102            #    message:str = "Add bonus for functional being in range of on/off prediction"
103            #    #result_messages = self.log_message(message, result_messages)
104            #    #functional_switch_score += 1
105            #    bonuses += .5
106
107        #for value in found_powerful_switch:
108        #    if value >= 0 and value <= 1 and value != -1:
109        #        message:str = "Confirmned good. Add bonus point for high performing being in first two groups"
110        #        #result_messages = self.log_message(message, result_messages)
111        #        #powerful_switch_score += 1
112        #        bonuses += 1
113
114            #if value in found_on_off_switch:
115            #    message:str = "Add bonus for high performing being in range of on/off prediction"
116            #    #result_messages = self.log_message(message, result_messages)
117            #    #powerful_switch_score += 1
118            #    bonuses += .5
119        
120        #only count a design sas good if functionial has at leat 1 point if not
121        #it is probbaly flase powerfull
122        #if functional_switch_score > 0:        
123        total_score = powerful_switch_score + functional_switch_score + on_off_switch_score + bonuses - penalties
124        #else:
125        #    total_score = 0
126
127        basic_score_results:BasicScoreResults = BasicScoreResults(total_score=total_score,
128                                                                  functional_switch_score=functional_switch_score,
129                                                                  powerful_switch_score=powerful_switch_score,
130                                                                  on_off_switch_score=on_off_switch_score,
131                                                                  bonuses=bonuses,
132                                                                  penalties=penalties)
133
134        return basic_score_results

Perform basic scoring functions that determine switchyness of rna sequence

def excessive_structures_penalties( self, num_structures: int, excess_divisor: float, excess_limit: float):
136    def excessive_structures_penalties(self, num_structures: int, excess_divisor:float,excess_limit:float):
137        """
138        Algorithm for determining the penalty for excessive number of secondary structures in the 
139        whole ensemble
140        """
141        #excess_divisor:float = 2000#2500
142        penalty:float = 0
143        if num_structures > excess_limit:
144            #factor:float = ((float(num_structures) - excess_limit) / excess_divisor ) * .5
145            factor:float = (float(num_structures) / excess_divisor ) * .5
146            message:str = f'Exsessive structs. Found:{num_structures} penalizing {factor} points'
147            #result_messages = self.log_message(message, result_messages)
148            sixty_range_num:float = 50000#15000
149            #penalize for too many structs
150            penalty += factor
151            if num_structures > sixty_range_num:
152                message:str = f'Significant excess structures found: found {num_structures - sixty_range_num} structures over limit of {sixty_range_num}'
153                #result_messages = self.log_message(message, result_messages)
154                message:str = f'Eterna_score should be ~60 for temp group and could be good design currently has high penalty for excess structures and now yet one more penalty'
155                #result_messages = self.log_message(message, result_messages)
156                penalty += .5
157        
158        return penalty

Algorithm for determining the penalty for excessive number of secondary structures in the whole ensemble

def advanced_score_groups( self, judge_results: serena.analysis.judge_pool.JudgesResults, investigator: serena.analysis.investigator.InvestigatorResults):
160    def advanced_score_groups(self, judge_results:JudgesResults, investigator: InvestigatorResults):
161        """
162        Bonuses and penalties that affect the fine tunning of swithyness determinations
163        """
164        lmv_bonus:float =0
165        lmv_penalty:float = 0    
166        comp_bonus:float = 0
167        comp_penalty:float = 0
168        total_score:float = 0
169
170        comp_less_ratio: float = investigator.lmv_assertions.comp_compare_to_mfe.count('<') / investigator.num_groups
171        com_great_ratio: float = investigator.lmv_assertions.comp_compare_to_mfe.count('>')  / investigator.num_groups
172        message:str = f'ev comp great:{com_great_ratio}, ev comp less:{comp_less_ratio}'
173        #result_messages = self.log_message(message, result_messages)
174        if com_great_ratio > comp_less_ratio and com_great_ratio >= .7:
175            message:str = "EV for comparison struct is Greater MORE OFTEN than unbound mfe so add bonus"
176            #result_messages = self.log_message(message, result_messages)
177            #lmv_bonus += 1
178        elif comp_less_ratio > com_great_ratio and comp_less_ratio >= .5:
179            message:str = "EV for mfe struct is GREATER MORE OFTEN than unbound mfe so penatly"
180            #result_messages = self.log_message(message, result_messages)
181            #lmv_penalty += 1
182            if comp_less_ratio >= .8:
183                message:str = "EV for mfe is GREATER EXTRA MORE OFTEN then mfe so minus penalty point"
184                #result_messages = self.log_message(message, result_messages)
185            #    lmv_penalty += 1
186        
187        if investigator.comparison_eval_results.nuc_penatly_count > 0:
188            if investigator.comparison_eval_results.BUratio_list[0] >= .6:
189                new_penalty: float = 1#investigator.comparison_eval_results.nuc_penatly_count * 1
190                message:str = f'Bound unbound ratio higher than 75% so it will most likely just fold into what should have been a switch so minus {new_penalty} points'
191                #result_messages = self.log_message(message, result_messages)
192                comp_penalty += new_penalty
193            #elif BUratio_list[0] > .60 and BUratio_list[1] < .3:
194            #    new_penalty: float = nuc_penatly_count * 1
195            #    message:str = f'Bound unbound ratio higher than 50% and then the 2nd energy group less than 20% so it will likely be blocked from switching so minus {new_penalty} points'
196            #    result_messages = self.log_message(message, result_messages)
197            #    score = score - new_penalty            
198            else:
199                bonus: float =  1           
200                message:str = f'Bound nucs found in first energy group. Design is primed to switch so add bonus of {bonus} points'
201                #result_messages = self.log_message(message, result_messages)
202                comp_bonus += bonus
203
204        #penalize for being too strong of a switch and only forms in the 2nd
205        #bound:float = investigator.comp_nuc_counts.comparison_nuc_counts[index].bound_count
206        #unbound: float = investigator.comp_nuc_counts.comparison_nuc_counts[index].unbound_count
207        #for index, ratios in enumerate(investigator.comparison_eval_results.ratios):
208        #    if ratios.unbound_to_total_ratio <= .15 and :
209        #        comp_penalty += 1
210        #        #its probably too strong of a switch
211        is_good_actually:bool = False
212       
213        
214        #for index, ratios in enumerate(investigator.lmv_values.lmv_comps):
215        #    if ratios.lmv_rel.ev_normalized >= 40:
216        #        lmv_penalty +=1 
217        
218        if investigator.lmv_values.lmv_comps[0].lmv_mfe.ev_normalized > 13 and investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized > 13:
219            #it is a bit too unstable in the first group and will probably fall apart
220            lmv_penalty +=1
221        
222        if investigator.lmv_values.lmv_comps[0].lmv_mfe.ev_normalized < 13 and investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized < 13 and investigator.lmv_values.lmv_comps[0].lmv_mfe.ev_normalized > 5:
223            if investigator.lmv_values.lmv_comps[1].lmv_comp.ev_normalized < 20:# and investigator.lmv_values.lmv_comps[1].lmv_comp.ev_normalized < 20:
224                lmv_bonus +=1
225            else:
226                #it is probably a bit too unstable to act like a proper switch
227                lmv_penalty +=1
228        
229        #if investigator.lmv_values.lmv_comps[0].lmv_mfe.ev_normalized < 5 and investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized < 5:
230        #    #not likely to pull out of the single state as the first group is too strong for the mfe
231        #    lmv_penalty +=1
232        index_0_mfe:float = 0
233        for index, lmv_comps in enumerate(investigator.lmv_values.lmv_comps):
234            if index == 0:
235                index_0_mfe = lmv_comps.lmv_mfe.ev_normalized
236            if index_0_mfe == 1:
237                #it probably has a very low struct count as this indicates group 1 has no variation from mfe
238                if lmv_comps.lmv_mfe.ev_normalized < 3 and index > 0:
239                    lmv_penalty +=1
240                if lmv_comps.lmv_mfe.ev_normalized < 5 and index > 3:
241                    lmv_penalty +=1
242                if investigator.total_structures_ensemble > 1000:
243                    #too high of struct count for mfe to be so low so penalty I think
244                    lmv_penalty +=1
245            elif index_0_mfe > 1:
246                #it probably has a very low struct count
247                if lmv_comps.lmv_mfe.ev_normalized < 2 and index == 0:
248                    lmv_penalty +=1
249                if lmv_comps.lmv_mfe.ev_normalized < 8 and index > 0:
250                    lmv_penalty +=1
251                if lmv_comps.lmv_mfe.ev_normalized < 12 and index > 2:
252                    lmv_penalty +=1
253            #else:
254            #    if lmv_comps.lmv_comp.ev_normalized < 10 and lmv_comps.lmv_mfe.ev_normalized < 10:
255            #        lmv_penalty +=1
256        
257        for index, ratios in enumerate(investigator.comparison_eval_results.ratios):
258            if ratios.bound_ratio > .3 and ratios.bound_ratio < 1:
259                comp_penalty +=1
260            #if ratios.bound_to_both_ratio < 0:
261                #comp_penalty +=1
262        #for index, ratios in enumerate(investigator.comparison_eval_results.ratios):
263            if ratios.last_bound_ratio > 5.0 or ratios.last_unbound_ratio > 5.0:
264                if investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized > 15 and investigator.lmv_values.lmv_comps[index].lmv_comp.ev_normalized > 25:
265                    comp_penalty +=1   
266                elif investigator.lmv_values.lmv_comps[0].lmv_comp.ev_normalized < 15 and investigator.lmv_values.lmv_comps[index].lmv_comp.ev_normalized < 25:
267                    is_good_actually = True
268        #for index, ratios in enumerate(investigator.comparison_eval_results.ratios):
269            if ratios.both_nuc_total >= .9:
270                comp_penalty +=1 
271                
272        #not sure if I want to use... i was ify about before and it seams not fully baked in implementatiuon. 
273        # need to make a ticket for this funciton
274        #if is_good_switch is True and bound_to_both_ratio >= 0.08:
275        #    message:str = "Low number of both and mfe nucs in relation to bound. Add bonus point"
276        #    result_messages = self.log_message(message, result_messages)
277        #    score= score + 1
278        excess_limit:float = 35000#this is based on new data 7500
279        excess_divisor:float = 2000#2500
280        excess_struct_penalty:float = self.excessive_structures_penalties(num_structures=investigator.total_structures_ensemble,
281                                                                    excess_limit=excess_limit,
282                                                                    excess_divisor=excess_divisor)
283        if excess_struct_penalty > 5 and is_good_actually is True:
284            #disregard the penatly
285            total_score = lmv_bonus - lmv_penalty + comp_bonus - comp_penalty - (excess_struct_penalty/2)
286        else:            
287            total_score = lmv_bonus - lmv_penalty + comp_bonus - comp_penalty - excess_struct_penalty
288            
289        advanced_score_response: AdvancedScoreResults = AdvancedScoreResults(lmv_bonus=lmv_bonus,
290                                                                             lmv_penalty=lmv_penalty,
291                                                                             comp_bonus=comp_bonus,
292                                                                             comp_penalty=comp_penalty,
293                                                                             excess_struct_penalty=excess_struct_penalty,
294                                                                             total_score=total_score)
295        return advanced_score_response

Bonuses and penalties that affect the fine tunning of swithyness determinations