Project: s41467-024-46089-y | Function: compute_gene_weight (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:** Calculates functional similarity weights for genes using Z-score normalization of cosine similarities

**KEY TERMS:** {
  "mat": "gene embedding matrix",
  "sim_pairwise": "pairwise cosine similarities",
  "sim_sum": "average similarity per gene",
  "sim_mean": "background similarity mean",
  "sim_std": "background similarity standard deviation",
  "gene_weight": "Z-score normalized weights"
}

**CONTEXT CODE:**             cpd_sig_cl = cpd_sig_cl_df[cl]
            if len(cpd_sig_cl) == 0 or len(tgtcl_idx[cl]) == 0:
                continue

            tgt_idx = {}
            scnt = 0
            test_input_idx_l = []
            test_input_idx_r = []
            for tidx in tgtcl_idx[cl]:
                tgt_idx[pert_sig.loc[tidx, 'Name']] = []
            for cidx in cpd_sig_cl.index:
                for tidx in tgtcl_idx[cl]:
                    test_input_idx_l.append(cidx)
                    test_input_idx_r.append(tidx)
                    tgt_idx[pert_sig.loc[tidx, 'Name']].append(scnt)
                    scnt += 1

            test_input_l = sigvec_all[test_input_idx_l]
            test_input_r = sigvec_all[test_input_idx_r]
            scores_0 = classifier_0.predict([test_input_l, test_input_r])
            scores_0 = 1 / (1 + np.exp(-scores_0))
            scores_1 = classifier_1.predict([test_input_l, test_input_r])
            scores_1 = 1 / (1 + np.exp(-scores_1))
            scores_2 = classifier_2.predict([test_input_l, test_input_r])
            scores_2 = 1 / (1 + np.exp(-scores_2))
            scores = (scores_0 + scores_1 + scores_2) / 3
            genes = []
            max_scores = []
            for k in tgt_idx:
                genes.append(k)
                max_scores.append(np.max(scores[tgt_idx[k]]))
            max_scores = np.array(max_scores)
            genes = np.array(genes)
            sortidx = np.argsort(-max_scores)
            topgenes = genes[sortidx]
            rankedscores = max_scores[sortidx]
            fw = open(outdir + cpd + cl + '_' + perttype + '.txt', 'w')
            fw.write('gene\trank\tscore\n')
            for i in range(len(topgenes)):
                fw.write(topgenes[i].split('@')[0] + '\t' + str(i+1) + '\t' + str(rankedscores[i]) + '\n')
            fw.close()

def compute_list_emb(glist):
    '''Compute the vector representation (embedding) for an input gene list
       input: list of gene IDs
       return: a 512d vector reprsentation
    '''
    # MASKED: Computes FRoGS vector representation for gene lists by combining GO and RNA-seq embeddings with functional similarity weighting implementation
    raise NotImplementedError("This function is masked for testing purposes.")

def compute_gene_weight(mat, sim_mean, sim_std):
    # MASKED: Calculates functional similarity weights for genes using Z-score normalization of cosine similarities implementation
    raise NotImplementedError("This function is masked for testing purposes.")

args = parse_args()
cpdlist_file, sig_file, perttype, emb_go, emb_archs4, outdir = args.cpdlist_file, args.sig_file, args.perttype, args.emb_go, args.emb_archs4, args.outdir

with open(emb_archs4, mode='r') as infile:
    reader = csv.reader(infile)
    archs4_emb = {rows[0]:np.array(rows[1:], dtype=np.float32) for rows in reader}

with open(emb_go, mode='r') as infile:
    reader = csv.reader(infile)
    go_emb = {rows[0]:np.array(rows[1:], dtype=np.float32) for rows in reader}

mean_std_dict_go, mean_std_dict_archs4 = gene_sim_mean_std()

#read gene signature file
id2sig = {}
t_sig=pd.read_csv(sig_file)
pert_sig = []
tasks = []
cnt = 0
targetsymbols = set()
all_cl = set()
#parse compound gene signature
for idx in t_sig.index:
    des = t_sig.loc[idx, 'term_name']
    ty = t_sig.loc[idx, 'term_name'].split(':')[0]
    if ty != 'Cpd':
        continue
    name = t_sig.loc[idx, 'term_name'].split(':')[1].split(':')[0] + '@'
    cl = t_sig.loc[idx, 'term_name'].split('@')[1].split('@')[0]
    dir = t_sig.loc[idx, 'term_name'].split('(')[1].split(')')[0]
    S_hit = set(t_sig.loc[idx, 'gids'].split(","))
    l1k = t_sig.loc[idx, 'term_id']

    pert_sig.append([l1k, name, cl, dir, des, ty, S_hit])
    id2sig[l1k] = S_hit
    tasks.append((l1k, S_hit))
    all_cl.add(cl)

id_map=pd.read_csv('../data/term2gene_id.csv')
term2geneid = {}
for idx in id_map.index:
    term2geneid[id_map.loc[idx, 'term_name']] = str(id_map.loc[idx, 'gene_id'])

#parse target gene signature
for idx in t_sig.index:
    des = t_sig.loc[idx, 'term_name']
    ty = t_sig.loc[idx, 'term_name'].split(':')[0]
    if ty not in ['shRNA', 'cDNA']:
        continue
    if t_sig.loc[idx, 'term_name'] in term2geneid:
        name = term2geneid[t_sig.loc[idx, 'term_name']] + '@'
    else:
        continue
    cl = t_sig.loc[idx, 'term_name'].split('@')[1].split('@')[0]
    if cl not in all_cl:
        continue
    dir = t_sig.loc[idx, 'term_name'].split('(')[1].split(')')[0]
    S_hit = set(t_sig.loc[idx, 'gids'].split(","))
    l1k = t_sig.loc[idx, 'term_id']
    pert_sig.append([l1k, name, cl, dir, des, ty, S_hit])
    id2sig[l1k] = S_hit
    tasks.append((l1k, S_hit))

pert_sig=pd.DataFrame(pert_sig, columns=['l1k', 'Name', 'CellLine', 'Direction', 'Description', 'Perturbagen', 'Signature'])
print('Number of perturbagen signatures:', len(pert_sig))
print('Numer of cell lines:', len(all_cl))

print("Compute embeddings of gene signatures...")
sig2vec_dic = {}
rslt=parallel.map(get_vec, tasks, n_CPU=10, progress=False)
for dic in rslt:
    for k in dic:
        sig2vec_dic[k] = dic[k]
sigvec_all = []
for idx in pert_sig.index:
    sigvec_all.append(sig2vec_dic[pert_sig.loc[idx, 'l1k']])
sigvec_all = np.array(sigvec_all)

fp_dim = 512
classifier_0= get_model(fp_dim)
optimizer = keras.optimizers.Adam()
classifier_0.compile(
    optimizer=optimizer,
    loss=[losses.BinaryCrossentropy(from_logits=True)]
)
classifier_0.load_weights('../saved_model/FEGS_Broad_' + perttype + '_0/ckpt')

classifier_1= get_model(fp_dim)
optimizer = keras.optimizers.Adam()
classifier_1.compile(
    optimizer=optimizer,
    loss=[losses.BinaryCrossentropy(from_logits=True)]
)
classifier_1.load_weights('../saved_model/FEGS_Broad_' + perttype + '_1/ckpt')

classifier_2= get_model(fp_dim)


Complete the function implementation replacing "raise NotImplementedError".