BioMedGPT-Mol / evaluation /evaluate.py
leofansq's picture
update for evaluation
3824ea0 verified
import os
import json
class Evaluator():
def __init__(self, dataset, result_dir, raw_dir=""):
self.dataset = dataset
self.result_dir = result_dir
if self.dataset == "openmolinst":
self.raw_dir = raw_dir
def _load_json(self, file_path):
with open(file_path, 'r') as f:
contents = json.load(f)
return contents
def _dump_json(self, content, file_path):
with open(file_path, 'w') as f:
json.dump(content, f, indent=4, ensure_ascii=False)
def _get_pred_gold_smolinstruct(self, json_file):
logs = self._load_json(json_file)
preds, gts = list(), list()
for log in logs:
preds.append([log["extracted_answer"]])
gts.append([log["extracted_gt"]])
return preds, gts
def _get_pred_gold_openmolinst(self, csv_file, json_file):
gts = pd.read_csv(csv_file)
preds = list()
logs = self._load_json(json_file)
for log in logs:
preds.append(log["extracted_answer"])
return preds, gts
def _get_pred_gold_mumoinstruct(self, json_file):
logs = self._load_json(json_file)
input_smiles, input_props, output_smiles, output_props = dict(), dict(), dict(), dict()
for log in logs:
task = log['metadata']['subtask']
pred_smi = [log["extracted_answer"]] if isinstance(log["extracted_answer"], str) \
else log["extracted_answer"]
if task in list(input_smiles.keys()):
input_smiles[task].append(log['metadata']['source_smiles'])
input_props[task].append(log['metadata']['source_props'])
output_smiles[task].append(pred_smi)
else:
input_smiles[task] = [(log['metadata']['source_smiles'])]
input_props[task] = [(log['metadata']['source_props'])]
output_smiles[task] = [pred_smi]
for task in input_smiles.keys():
output_props[task] = generate_props(output_smiles[task])
return input_smiles, input_props, output_smiles, output_props
def eval(self, json_file, task=None):
if self.dataset == "smolinstruct":
pred_list, gold_list = self._get_pred_gold_smolinstruct(json_file=json_file)
if task in ('forward_synthesis', 'description_guided_generation', 'name_conversion-i2s'):
r = calculate_smiles_metrics(pred_list, gold_list)
elif task in ('retrosynthesis',):
r = calculate_smiles_metrics(pred_list, gold_list, metrics=('exact_match', 'fingerprint', 'multiple_match'))
elif task in ('molecule_captioning',):
r = calculate_text_metrics(pred_list, gold_list)
elif task in ('name_conversion-i2f', 'name_conversion-s2f'):
r = calculate_formula_metrics(pred_list, gold_list, metrics=('element_match',))
elif task in ('name_conversion-s2i',):
r = calculate_formula_metrics(pred_list, gold_list, metrics=('split_match',))
elif task in ('property_prediction-esol', 'property_prediction-lipo'):
r = calculate_number_metrics(pred_list, gold_list)
elif task in ('property_prediction-bbbp', 'property_prediction-clintox', 'property_prediction-hiv', 'property_prediction-sider'):
r = calculate_boolean_metrics(pred_list, gold_list)
else:
raise ValueError(task)
print (r)
return r
elif self.dataset == "openmolinst":
preds, golds = self._get_pred_gold_openmolinst(csv_file=os.path.join(self.raw_dir, "openmolinst_"+task+".csv"),
json_file=json_file)
if task == "moledit_add_component":
r = eval_moledit_add_component(data=golds, target=preds)
elif task == "moledit_delete_component":
r = eval_moledit_delete_component(data=golds, target=preds)
elif task == "moledit_sub_component":
r = eval_moledit_sub_component(data=golds, target=preds)
elif task == "molopt_logP":
r = eval_molopt_logP(data=golds, target=preds)
elif task == "molopt_MR":
r = eval_molopt_MR(data=golds, target=preds)
elif task == "molopt_QED":
r = eval_molopt_QED(data=golds, target=preds)
else:
raise ValueError(task)
print (r)
return r
elif self.dataset == "mumoinstruct":
input_smiles, input_props, output_smiles, output_props = self._get_pred_gold_mumoinstruct(json_file)
results = dict()
for task in input_smiles.keys():
print (f"\n###### {task} ######")
r, _ = compute_metrics(input_smiles=input_smiles[task], \
input_props=input_props[task], \
output_smiles=output_smiles[task], \
output_props_df=output_props[task], \
task=task, \
normalize=None)
print (r)
results[task] = r
return results
def evaluate_smolinstruct(self):
result_files = os.listdir(self.result_dir)
results = dict()
for file_name in result_files:
if "smolinstruct" not in file_name:
continue
task = file_name[:-5].replace("smolinstruct_", "")
print (f"\n###### {task} ######")
results[task] = self.eval(json_file=os.path.join(self.result_dir, file_name), task=task)
self._dump_json(results, os.path.join(self.result_dir, "metrics.json"))
def evaluate_openmolinst(self):
result_files = os.listdir(self.result_dir)
results = dict()
for file_name in result_files:
if "openmolinst" not in file_name:
continue
task = file_name[:-5].replace("openmolinst_", "")
print (f"\n###### {task} ######")
results[task] = self.eval(json_file=os.path.join(self.result_dir, file_name), task=task)
self._dump_json(results, os.path.join(self.result_dir, "metrics.json"))
def evaluate_mumoinstruct(self):
result_files = os.listdir(self.result_dir)
for file_name in result_files:
if "mumoinstruct" not in file_name:
continue
results = self.eval(json_file=os.path.join(self.result_dir, file_name))
self._dump_json(results, os.path.join(self.result_dir, "metrics.json"))
def run(self):
if self.dataset == "smolinstruct":
self.evaluate_smolinstruct()
elif self.dataset == "openmolinst":
self.evaluate_openmolinst()
elif self.dataset == "mumoinstruct":
self.evaluate_mumoinstruct()
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description="")
parser.add_argument("--dataset_name", type=str, help="name of the dataset")
parser.add_argument("--result_dir", type=str, help="path to result files")
parser.add_argument("--raw_dir", type=str, default="evaluation/datasets/openmolinst_raw", help="path to raw files (for OpenMolInst)")
args = parser.parse_args()
if args.dataset_name == "smolinstruct":
from utils.smolinstruct_metrics import calculate_smiles_metrics, calculate_formula_metrics, calculate_text_metrics, calculate_number_metrics, calculate_boolean_metrics
workflow = Evaluator(dataset=args.dataset_name,
result_dir=args.result_dir)
workflow.run()
elif args.dataset_name == "openmolinst":
from utils.openmolinst_metrics import eval_moledit_add_component, eval_moledit_delete_component, eval_moledit_sub_component, eval_molopt_logP, eval_molopt_MR, eval_molopt_QED
import pandas as pd
workflow = Evaluator(dataset=args.dataset_name,
result_dir=args.result_dir,
raw_dir=args.raw_dir)
workflow.run()
elif args.dataset_name == "mumoinstruct":
from utils.mumoinstruct_metrics import generate_props, compute_metrics
workflow = Evaluator(dataset=args.dataset_name,
result_dir=args.result_dir)
workflow.run()