Project: s41467-024-52580-3 | Function: predict (python)

system: You are an expert Python programmer implementing algorithms from scientific papers.
Complete the masked function based on the algorithm description.
Follow Python best practices and maintain consistent code style.
Return **only** the complete Python function code.

user: Complete this Python function:

**DESCRIPTION:** Ensemble prediction algorithm combining multiple sub-models (SVR, RF, LR) trained on different data subsets to predict missense mutation impacts on phase separation with robust generalization through leave-one-source-out cross-validation

**KEY TERMS:** {
  "svr_model": "Support Vector Regression sub-models for Impact Prediction",
  "rf_model": "Random Forest sub-models for ensemble prediction",
  "lr_model": "Logistic Regression for Strengthen/Weaken prediction",
  "input_matrix": "39-dimensional feature matrix from build_feature_df",
  "ip_scores": "Impact Prediction task scores",
  "sp_scores": "Strengthen/Weaken Prediction task scores",
  "rank_scores": "percentile rankings across background distribution"
}

**CONTEXT CODE:** print('--------preparing models--------')
from modules import *
from ml_feature_construction import *
import bisect 
submodel_path = 'data/models/submodels/'
class lr_merge_model:
    def __init__(self):   
        self.lr_model1 = joblib.load(os.path.join(submodel_path,'lr_sub_1.model'))
        self.lr_model2 = joblib.load(os.path.join(submodel_path,'lr_sub_2.model'))
        self.lr_model3 = joblib.load(os.path.join(submodel_path,'lr_sub_3.model'))
        self.lr_model4 = joblib.load(os.path.join(submodel_path,'lr_sub_4.model'))
        self.lr_model5 = joblib.load(os.path.join(submodel_path,'lr_sub_5.model'))
        self.lr_model6 = joblib.load(os.path.join(submodel_path,'lr_sub_6.model'))
        self.lr_model7 = joblib.load(os.path.join(submodel_path,'lr_sub_7.model'))
        self.lr_model8 = joblib.load(os.path.join(submodel_path,'lr_sub_8.model'))
        self.lr_model9 = joblib.load(os.path.join(submodel_path,'lr_sub_9.model'))
        self.lr_model10 = joblib.load(os.path.join(submodel_path,'lr_sub_10.model'))
    

    def predict(self,input_matrix):
        p1 = self.lr_model1.predict_proba(input_matrix)[:,1]
        p2 = self.lr_model2.predict_proba(input_matrix)[:,1]
        p3 = self.lr_model3.predict_proba(input_matrix)[:,1]
        p4 = self.lr_model4.predict_proba(input_matrix)[:,1]
        p5 = self.lr_model5.predict_proba(input_matrix)[:,1]
        p6 = self.lr_model6.predict_proba(input_matrix)[:,1]
        p7 = self.lr_model7.predict_proba(input_matrix)[:,1]
        p8 = self.lr_model8.predict_proba(input_matrix)[:,1]
        p9 = self.lr_model9.predict_proba(input_matrix)[:,1]
        p10 = self.lr_model10.predict_proba(input_matrix)[:,1]
        return (p1+p2+p3+p4+p5+p6+p7+p8+p9+p10)/10


    
class rf_merge_model:
    def __init__(self):   
        self.rf_model1 = joblib.load(os.path.join(submodel_path,'rf_sub_1.model'))
        self.rf_model2 = joblib.load(os.path.join(submodel_path,'rf_sub_2.model'))
        self.rf_model3 = joblib.load(os.path.join(submodel_path,'rf_sub_3.model'))
        self.rf_model4 = joblib.load(os.path.join(submodel_path,'rf_sub_4.model'))
        self.rf_model5 = joblib.load(os.path.join(submodel_path,'rf_sub_5.model'))
        self.rf_model6 = joblib.load(os.path.join(submodel_path,'rf_sub_6.model'))
        self.rf_model7 = joblib.load(os.path.join(submodel_path,'rf_sub_7.model'))
        self.rf_model8 = joblib.load(os.path.join(submodel_path,'rf_sub_8.model'))
        self.rf_model9 = joblib.load(os.path.join(submodel_path,'rf_sub_9.model'))
        self.rf_model10 = joblib.load(os.path.join(submodel_path,'rf_sub_10.model'))
    

    def predict(self,input_matrix):
        p1 = self.rf_model1.predict_proba(input_matrix)[:,1]
        p2 = self.rf_model2.predict_proba(input_matrix)[:,1]
        p3 = self.rf_model3.predict_proba(input_matrix)[:,1]
        p4 = self.rf_model4.predict_proba(input_matrix)[:,1]
        p5 = self.rf_model5.predict_proba(input_matrix)[:,1]
        p6 = self.rf_model6.predict_proba(input_matrix)[:,1]
        p7 = self.rf_model7.predict_proba(input_matrix)[:,1]
        p8 = self.rf_model8.predict_proba(input_matrix)[:,1]
        p9 = self.rf_model9.predict_proba(input_matrix)[:,1]
        p10 = self.rf_model10.predict_proba(input_matrix)[:,1]
        return (p1+p2+p3+p4+p5+p6+p7+p8+p9+p10)/10
    

class svr_merge_model:
    def __init__(self):   
        self.svr_model1 = joblib.load(os.path.join(submodel_path,'svr_sub_1.model'))
        self.svr_model2 = joblib.load(os.path.join(submodel_path,'svr_sub_2.model'))
        self.svr_model3 = joblib.load(os.path.join(submodel_path,'svr_sub_3.model'))
        self.svr_model4 = joblib.load(os.path.join(submodel_path,'svr_sub_4.model'))
        self.svr_model5 = joblib.load(os.path.join(submodel_path,'svr_sub_5.model'))
        self.svr_model6 = joblib.load(os.path.join(submodel_path,'svr_sub_6.model'))
        self.svr_model7 = joblib.load(os.path.join(submodel_path,'svr_sub_7.model'))
        self.svr_model8 = joblib.load(os.path.join(submodel_path,'svr_sub_8.model'))
        self.svr_model9 = joblib.load(os.path.join(submodel_path,'svr_sub_9.model'))
        self.svr_model10 = joblib.load(os.path.join(submodel_path,'svr_sub_10.model'))
    

    def predict(self,input_matrix):
        p1 = self.svr_model1.predict(input_matrix)
        p2 = self.svr_model2.predict(input_matrix)
        p3 = self.svr_model3.predict(input_matrix)
        p4 = self.svr_model4.predict(input_matrix)
        p5 = self.svr_model5.predict(input_matrix)
        p6 = self.svr_model6.predict(input_matrix)
        p7 = self.svr_model7.predict(input_matrix)
        p8 = self.svr_model8.predict(input_matrix)
        p9 = self.svr_model9.predict(input_matrix)
        p10 = self.svr_model10.predict(input_matrix)
        return (p1+p2+p3+p4+p5+p6+p7+p8+p9+p10)/10


def point_mutation(seq,point,before,after):
    if seq[point-1] != before:
        return False
    else:
        return seq[:point-1]+after+seq[point:]

def convert2Predictable(dat,wt_seq,gene_name):
    mt_aas = dat['mt_aa'].values
    wt_aas = dat['wt_aa'].values
    positions = dat['position'].values
    mt_seqs = []
    size = len(mt_aas)
    for pos,wt_aa,mt_aa in zip(positions,wt_aas,mt_aas):
        mt_seq = point_mutation(wt_seq, int(pos), wt_aa, mt_aa)
        mt_seqs.append(mt_seq)
        
    dat['MT_AA'] = mt_aas # 根据新的buildfeature文件重命名
    dat['WT_AA'] = wt_aas 
    dat['Seq'] = mt_seqs
    dat['wt_seq'] = [wt_seq]*size
    dat['MuPosition'] = dat['position'].apply(lambda x:str(x))
    dat['gene_name'] = [gene_name]*size
    return dat

def predict(dat,wt_seq,gene_name):
    dat1 = convert2Predictable(dat,wt_seq,gene_name)
    dat1 = build_feature_df(dat1)
    dat_numeric = dat1._get_numeric_data()
    dat2predict_model1 = dat_numeric


Complete the function implementation replacing "raise NotImplementedError".