CoolFace
Modelpublic

OneScience-Group/TemStaPro-main

sourceHugging Facemitupdated 15d agoView on Hugging Face
0likes19downloads
temstapro309 linesDownload Raw Back to scripts
1#!/usr/bin/env python32 3# Program that makes thermostability predictions4 5from optparse import OptionParser6from datetime import datetime7import sys8import os9import numpy10from torch.utils.data import DataLoader11from torch.utils.data import TensorDataset12import torch13 14PARAMETERS = {15	"PT_MODEL_PATH": "Rostlab/prot_t5_xl_half_uniref50-enc",16	"DATASET": "major",17	"EMB_TYPE": "mean",18	"CLASSIFIER_TYPE": "imbal",19	"THRESHOLDS": {20		":(40-65]:": ["40", "45", "50", "55", "60", "65"],21		":(40-80]:": ["40", "45", "50", "55", "60", "65", "70", "75", "80"],22	},23	"SEEDS": ["1", "2", "3", "4", "5"],24	"INPUT_SIZE": 1024,25	"HIDDEN_LAYER_SIZES": [256, 128],26	"DEVICE": torch.device("cuda:0" if torch.cuda.is_available() else "cpu"),27	"THRESHOLDS_RANGE": ":(40-65]:",28	"TEMPERATURE_RANGES": {29		":(40-65]:": ["<40", "[40-45)", "[45-50)", "[50-55)", "[55-60)", 30			"[60-65)", "65<="],31		":(40-80]:": ["<40", "[40-45)", "[45-50)", "[50-55)", "[55-60)", 32			"[60-65)", "[65-70)", "[70-75)", "[75-80)", "80<="],33	},34	"THERMOPHILICITY_LABELS": {35		"mesophilic": ["<40", "[40-45)", "<45"],36		"thermophilic": ["[45-50)", "[50-55)", "[55-60)", "[60-65)", 37			"65<=", "[65-70)", "[70-75)", "<75"],38		"hyperthermophilic": ["[75-80)", "80<="]39	},40	"PRINT_THERMOPHILICITY": {41		":(40-65]:": False,42		":(40-80]:": True43	}44}45 46SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))47PROJECT_DIR = os.path.dirname(SCRIPT_DIR)48 49parser = OptionParser()50 51parser.add_option("--input-fasta", "-f", dest="fasta",52	default=None, help="path to the input FASTA file.")53 54parser.add_option("--embeddings-dir", "-e", dest="emb_dir",55	default=None, help="path to the directory to which embeddings "+\56	"files will be saved (cache).")57 58parser.add_option("--PT-directory", "-d", dest="pt_dir",59	default=None, help="path to the directory of ProtTrans model.")60 61parser.add_option("--temstapro-directory", "-t", dest="tsp_dir",62	default=PROJECT_DIR, help="path to the directory of TemStaPro program "+\63	"with its dependencies.")64 65parser.add_option("--more-thresholds", dest="more_thresholds",66	action="store_true", help="option for the mode that outputs "+\67	"additional predictions for upper temperature thresholds and the "+\68	"thremophilicity label")69 70parser.add_option("--mean-output", dest="mean_out",71	default=None, help="path to the output TSV file with mean predictions. "+\72	"Predictions made from the mean embeddings are always printed to STDOUT."+\73	" If this option is given, the output is directed to the given file")74 75parser.add_option("--per-res-output", dest="per_res_out",76	default=None, help="path to the output TSV file with per-residue "+\77	"predictions.")78 79parser.add_option("--per-segment-output", dest="per_segment_out",80	default=None, help="path to the output TSV file with per-residue "+\81	"predictions made for each segment of the sequence.")82 83parser.add_option("--segment-size", dest="segment_size",84	default=41, help="option to set the window size for average smoothening "+\85	"of per residue embeddings ('per-segment-output' option). Default: 41.")86 87parser.add_option("--window-size-predictions", "-w", 88	dest="window_size_predictions",89	default=81, help="option to set the window size for average smoothening "+\90	"of per residue predictions for plotting (option for 'per-res-output' "+\91	"and 'per-segment-output'). Default: 81.")92 93parser.add_option("--per-residue-plot-dir", "-p", dest="plot_dir",94	default=None, help="path to the directory to which inferences "+\95	"plots will be saved (option for 'per-res-output' and "+\96	"'per-res-segment-output' modes. Default: './'.")97 98parser.add_option("--curve-smoothening", "-c", dest="curve_smoothening",99	default=False, action="store_true", 100	help="option for 'per-segment-output' run mode, which adjusts the "+\101	"plot by making an additional smoothening of the curve.")102 103parser.add_option("--portion-size", dest="portion_size",104	default=1000, 105	help="option to set the portions', into which to divide the input "+\106	"of sequences, maximum size. If no division is needed, set the "+\107	"option to 0. Default: 1000.")108 109parser.add_option("--version", "-v", dest="version",110	default=False, action="store_true",111	help="print version of the program and exit.")112 113(options, args) = parser.parse_args()114 115if(options.version):116	print(f"TemStaPro 0.2.{int(os.popen('git rev-list --count HEAD').read().strip())-61}")117	exit()118 119options.window_size_predictions = int(options.window_size_predictions)120options.segment_size = int(options.segment_size)121if(options.more_thresholds): PARAMETERS['THRESHOLDS_RANGE'] = ":(40-80]:"122 123try:124	assert (options.fasta != None), f"{sys.argv[0]}: a FASTA file is required."125except AssertionError as message:126	print(message, file=sys.stderr)127	exit()128 129try:130	assert (options.pt_dir != None), (131		f"{sys.argv[0]}: a path to the ProtTrans model location is required."132	)133except AssertionError as message:134	print(message, file=sys.stderr)135	exit()136 137temstapro_dir = os.path.abspath(options.tsp_dir)138PARAMETERS["CLASSIFIERS_DIR"] = os.path.join(temstapro_dir, "weight")139 140# Importing local modules141 142sys.path.append(os.path.join(temstapro_dir, "scripts"))143sys.path.append(os.path.join(temstapro_dir, "model"))144 145import prottrans_models146import data_process147import model_flow148import results149 150# Standardization of the FASTA file151(sequences, orig_headers, orig_seqs) = prottrans_models.process_FASTA(options.fasta)152 153# Loading the ProtTrans model154print("%s: beginning to load the model " % datetime.now(), file=sys.stderr)155 156pt_model, tokenizer = prottrans_models.load_model_and_tokenizer(options.pt_dir, 157	PARAMETERS["PT_MODEL_PATH"])158 159print("%s: finished loading the model" % datetime.now(), file=sys.stderr)160 161# Dividing sequences into portions162options.portion_size = int(options.portion_size)163if(options.portion_size == 0): options.portion_size = len(sequences)164 165per_res_mode = (options.per_res_out or options.per_segment_out)166 167for i in range(0, len(list(sequences.keys())), options.portion_size):168	portion_keys = list(sequences.keys())[i:i+options.portion_size]169	170	sequences_portion = {}171	for key in portion_keys:172		sequences_portion[key] = sequences[key]173 174	# Check which sequences do not have embeddings generated175	if(options.emb_dir and os.path.exists(options.emb_dir)):176		seqs_wo_emb_portion = data_process.get_sequences_without_embeddings(177			sequences_portion, options.emb_dir, per_res=per_res_mode)178	else:179		seqs_wo_emb_portion = sequences_portion180 181	embeddings = {}182	per_res_dataset = {}183	per_res_sequences_portion = {}184 185	if(len(seqs_wo_emb_portion)):186		gen_emb_start = datetime.now()187		print(f"{datetime.now()}: beginning to generate embeddings", file=sys.stderr)188 189		# Generating embeddings190		embeddings = prottrans_models.get_embeddings(pt_model, tokenizer, 191			seqs_wo_emb_portion, 192			per_residue=per_res_mode, 193			per_protein=True)194 195		gen_emb_end = datetime.now()196		197		# If cache given, save embeddings198		if(options.emb_dir and os.path.exists(options.emb_dir)):199			if(per_res_mode):200				prottrans_models.save_embeddings(seqs_wo_emb_portion, embeddings,201					options.emb_dir, "per_res")202			prottrans_models.save_embeddings(seqs_wo_emb_portion, embeddings, 203				options.emb_dir, "mean")204		elif(options.emb_dir and not os.path.exists(options.emb_dir)):205			print("The given directory (option -e) does not exist, "+\206				"embeddings' PT files will not be saved.", file=sys.stderr)207 208		try:209			prottrans_models.print_embeddings_generation_stats(i, 210				options.portion_size, embeddings, seqs_wo_emb_portion, 211				gen_emb_start, gen_emb_end)212		except ZeroDivisionError:213			print(f"{sys.argv[0]}: no embeddings were generated.", file=sys.stderr)214			sys.exit(1)215 216	# Collecting the required type of embeddings217	dataset = data_process.collect_mean_embeddings(sequences_portion, 218		embeddings=embeddings, emb_dir=options.emb_dir, 219		input_size=PARAMETERS["INPUT_SIZE"])220 221	if(options.per_res_out):222		per_res_dataset = data_process.collect_per_res_embeddings(sequences_portion, 223			orig_seqs, embeddings=embeddings, emb_dir=options.emb_dir, 224			input_size=PARAMETERS["INPUT_SIZE"])225		per_res_sequences_portion = per_res_dataset["z_test"]226	elif(options.per_segment_out):227		per_res_dataset = data_process.collect_per_res_embeddings(sequences_portion, 228			orig_seqs, embeddings=embeddings,229			emb_dir=options.emb_dir, input_size=PARAMETERS["INPUT_SIZE"], smoothen=True, 230			window_size=options.segment_size)231		per_res_sequences_portion = per_res_dataset["z_test"]232 233	test_loader, per_res_test_loader = model_flow.prepare_data_loaders([234		dataset, per_res_dataset], 'test')235 236	print("%s: beginning to make inferences" % datetime.now(), 237		file=sys.stderr)238 239	averaged_inferences, binary_inferences, labels, clashes = model_flow.make_inferences(240		sequences_portion, per_res_sequences_portion, test_loader, 241		per_res_test_loader, PARAMETERS, PARAMETERS["THRESHOLDS_RANGE"])242 243	print("%s: finished making inferences" % datetime.now(), file=sys.stderr)244			245	# Processing results246	for j, loader in enumerate([test_loader, per_res_test_loader]):247		if(loader is None): break248		for seq in averaged_inferences[j].keys():249			labels[j][seq].append(results.get_temperature_label(250				averaged_inferences[j][seq], 251				PARAMETERS["TEMPERATURE_RANGES"][PARAMETERS["THRESHOLDS_RANGE"]], left_hand=True))252			labels[j][seq].append(results.get_temperature_label(253				averaged_inferences[j][seq],254				PARAMETERS["TEMPERATURE_RANGES"][PARAMETERS["THRESHOLDS_RANGE"]], left_hand=False))255			clashes[j][seq].append(results.detect_clash(averaged_inferences[j][seq],256				left_hand=True))257 258	# Processing printing of mean predictions259	if(options.mean_out):260		os.system(f"mkdir -p {os.path.dirname(options.mean_out)}")261		f_mean = open(options.mean_out, "w") if i == 0 else open(options.mean_out, "a")262	else:263		f_mean = sys.stdout264 265	if(i == 0): results.print_inferences_header(f_mean, 266		PARAMETERS["THRESHOLDS"][PARAMETERS["THRESHOLDS_RANGE"]], 267		PARAMETERS["PRINT_THERMOPHILICITY"][PARAMETERS["THRESHOLDS_RANGE"]])268 269	results.print_inferences(averaged_inferences[0], binary_inferences[0],270		orig_headers, labels[0], clashes[0], 271		PARAMETERS["THERMOPHILICITY_LABELS"], f_mean, orig_seqs,272		"mean", PARAMETERS["PRINT_THERMOPHILICITY"][PARAMETERS["THRESHOLDS_RANGE"]])273 274	# Printing per-residue inferences275	if(options.per_res_out):276		os.system(f"mkdir -p {os.path.dirname(options.per_res_out)}")277		f_per_res = open(options.per_res_out, "w") if i == 0 else open(options.per_res_out, "a")278		if(i == 0): results.print_inferences_header(f_per_res, 279			PARAMETERS["THRESHOLDS"][PARAMETERS["THRESHOLDS_RANGE"]], 280			PARAMETERS["PRINT_THERMOPHILICITY"][PARAMETERS["THRESHOLDS_RANGE"]])281 282		results.print_inferences(averaged_inferences[1], binary_inferences[1], 283			orig_headers, labels[1],284			clashes[1], PARAMETERS["THERMOPHILICITY_LABELS"],285			f_per_res, per_res_sequences_portion, "per-res", 286			PARAMETERS["PRINT_THERMOPHILICITY"][PARAMETERS["THRESHOLDS_RANGE"]])287	elif(options.per_segment_out):288		os.system(f"mkdir -p {os.path.dirname(options.per_segment_out)}")289		f_per_res = open(options.per_segment_out, "w") if i == 0 else open(options.per_segment_out, "a")290		if(i == 0): results.print_inferences_header(f_per_res, 291			PARAMETERS["THRESHOLDS"][PARAMETERS["THRESHOLDS_RANGE"]],292			PARAMETERS["PRINT_THERMOPHILICITY"][PARAMETERS["THRESHOLDS_RANGE"]])293 294		results.print_inferences(averaged_inferences[1], binary_inferences[1], 295			orig_headers, labels[1],296			clashes[1], PARAMETERS["THERMOPHILICITY_LABELS"], f_per_res, 297			per_res_sequences_portion, "per-segment",298			PARAMETERS["PRINT_THERMOPHILICITY"][PARAMETERS["THRESHOLDS_RANGE"]])299 300	# Plotting inferences301	if(options.plot_dir):302		os.system(f"mkdir -p {options.plot_dir}")303		results.plot_inferences(304			options.per_res_out, options.per_segment_out,305			averaged_inferences[1],306			PARAMETERS["THRESHOLDS"][PARAMETERS["THRESHOLDS_RANGE"]], options.plot_dir,307			options.window_size_predictions, options.segment_size, 308			options.curve_smoothening)309