refactor foldx pipeline to include:

* command-line args
* creating necessary dirs automagically
* code cleanup, syntax errors, etc etc
This commit is contained in:
Tanushree Tunstall 2020-06-30 17:14:30 +01:00
parent e8a66a7a94
commit 973a1a33da
12 changed files with 700 additions and 56 deletions

View file

@ -14,8 +14,6 @@ import numpy as np
from mcsm import *
#==============================
#%% global variables for defs
#==============================
#%%
@ -194,9 +192,9 @@ def format_mcsm_output(mcsm_outputcsv):
#############
# format colnames: all lowercase, remove spaces and use '_' to join
print('Assigning meaningful colnames i.e without spaces and hyphen and reflecting units'
, '\n===================================================================')
, '\n=======================================================')
my_colnames_dict = {'Predicted Affinity Change': 'PredAffLog' # relevant info from this col will be extracted and the column discarded
, 'Mutation information': 'mutation_information' # {wild_type}<position>{mutant_type}
, 'Mutation information': 'mutationinformation' # {wild_type}<position>{mutant_type}
, 'Wild-type': 'wild_type' # one letter amino acid code
, 'Position': 'position' # number
, 'Mutant-type': 'mutant_type' # one letter amino acid code
@ -206,41 +204,41 @@ def format_mcsm_output(mcsm_outputcsv):
, 'DUET stability change': 'duet_stability_change'} # in kcal/mol
mcsm_data.rename(columns = my_colnames_dict, inplace = True)
#%%===========================================================================
#%%=====================================================================
#################################
# populate mutation_information
# populate mutationinformation
# col which is currently blank
#################################
# populate mutation_information column:mcsm style muts {WT}<POS>{MUT}
print('Populating column : mutation_information which is currently empty\n', mcsm_data['mutation_information'])
mcsm_data['mutation_information'] = mcsm_data['wild_type'] + mcsm_data['position'].astype(str) + mcsm_data['mutant_type']
print('checking after populating:\n', mcsm_data['mutation_information']
, '\n===================================================================')
# populate mutationinformation column:mcsm style muts {WT}<POS>{MUT}
print('Populating column : mutationinformation which is currently empty\n', mcsm_data['mutationinformation'])
mcsm_data['mutationinformation'] = mcsm_data['wild_type'] + mcsm_data['position'].astype(str) + mcsm_data['mutant_type']
print('checking after populating:\n', mcsm_data['mutationinformation']
, '\n=======================================================')
# Remove spaces b/w pasted columns
print('removing white space within column: \mutation_information')
mcsm_data['mutation_information'] = mcsm_data['mutation_information'].str.replace(' ', '')
print('Correctly formatted column: mutation_information\n', mcsm_data['mutation_information']
, '\n===================================================================')
#%%===========================================================================
print('removing white space within column: \mutationinformation')
mcsm_data['mutationinformation'] = mcsm_data['mutationinformation'].str.replace(' ', '')
print('Correctly formatted column: mutationinformation\n', mcsm_data['mutationinformation']
, '\n=======================================================')
#%%=====================================================================
#############
# sanity check: drop dupliate muts
#############
# shouldn't exist as this should be eliminated at the time of running mcsm
print('Sanity check:'
, '\nChecking duplicate mutations')
if mcsm_data['mutation_information'].duplicated().sum() == 0:
if mcsm_data['mutationinformation'].duplicated().sum() == 0:
print('PASS: No duplicate mutations detected (as expected)'
, '\nDim of data:', mcsm_data.shape
, '\n===============================================================')
, '\n===================================================')
else:
print('WARNING: Duplicate mutations detected'
, '\nDim of df with duplicates:', mcsm_data.shape
, 'Removing duplicate entries')
mcsm_data = mcsm_data.drop_duplicates(['mutation_information'])
mcsm_data = mcsm_data.drop_duplicates(['mutationinformation'])
print('Dim of data after removing duplicate muts:', mcsm_data.shape
, '\n===============================================================')
#%%===========================================================================
, '\n===========================================================')
#%%=====================================================================
#############
# Create col: duet_outcome
#############
@ -259,8 +257,8 @@ def format_mcsm_output(mcsm_outputcsv):
# print('FAIL: DUET outcome assigned incorrectly'
# , '\nExpected no. of stabilising mutations:', DUET_pos
# , '\nGot no. of stabilising mutations', mcsm_data['duet_outcome'].value_counts()['Stabilising']
# , '\n===============================================================')
#%%===========================================================================
# , '\n======================================================')
#%%=====================================================================
#############
# Extract numeric
# part of ligand_distance col
@ -271,7 +269,7 @@ def format_mcsm_output(mcsm_outputcsv):
print('extracting numeric part of col: ligand_distance')
mcsm_data['ligand_distance'] = mcsm_data['ligand_distance'].str.extract('(\d+\.?\d*)')
print('Ligand Distance:',mcsm_data['ligand_distance'])
#%%===========================================================================
#%%=====================================================================
#############
# Create 2 columns:
# ligand_affinity_change and ligand_outcome
@ -282,7 +280,7 @@ def format_mcsm_output(mcsm_outputcsv):
# categorocal part: '\b(\w+ing)\b'
print('Extracting numerical and categorical parts from the col: PredAffLog')
print('to create two columns: ligand_affinity_change and ligand_outcome'
, '\n===================================================================')
, '\n=======================================================')
# 1) Extracting the predicted affinity change (numerical part)
mcsm_data['ligand_affinity_change'] = mcsm_data['PredAffLog'].str.extract('(-?\d+\.?\d*)', expand = True)
@ -308,24 +306,24 @@ def format_mcsm_output(mcsm_outputcsv):
if check.all():
print('PASS: spelling change successfull'
, '\nNo. of predicted affinity changes:\n', british_spl
, '\n===============================================================')
, '\n===================================================')
else:
sys.exit('FAIL: spelling change unsucessfull'
, '\nExpected:\n', american_spl
, '\nGot:\n', british_spl
, '\n===============================================================')
#%%===========================================================================
, '\n===================================================')
#%%=====================================================================
#############
# ensuring corrrect dtype for numeric columns
#############
# check dtype in cols
print('Checking dtypes in all columns:\n', mcsm_data.dtypes
, '\n===================================================================')
, '\n=======================================================')
print('Converting the following cols to numeric:'
, '\nligand_distance'
, '\nduet_stability_change'
, '\nligand_affinity_change'
, '\n===================================================================')
, '\n=======================================================')
# using apply method to change stabilty and affinity values to numeric
numeric_cols = ['duet_stability_change', 'ligand_affinity_change', 'ligand_distance']
@ -336,12 +334,12 @@ def format_mcsm_output(mcsm_outputcsv):
if cols_check.all():
print('PASS: dtypes for selected cols:', numeric_cols
, '\nchanged to numeric'
, '\n===============================================================')
, '\n===================================================')
else:
sys.exit('FAIL:dtype change to numeric for selected cols unsuccessful'
, '\n===============================================================')
, '\n===================================================')
print(mcsm_data.dtypes)
#%%===========================================================================
#%%=====================================================================
#############
# scale duet values
#############
@ -357,7 +355,7 @@ def format_mcsm_output(mcsm_outputcsv):
, '\n---------------------------------------------------------------'
, '\nScaled duet scores:\n', mcsm_data['duet_scaled'])
#%%===========================================================================
#%%=====================================================================
#############
# scale affinity values
#############
@ -373,7 +371,7 @@ def format_mcsm_output(mcsm_outputcsv):
, '\n---------------------------------------------------------------'
, '\nScaled affinity scores:\n', mcsm_data['affinity_scaled'])
#%%===========================================================================
#%%=====================================================================
#############
# adding column: wild_position
# useful for plots and db
@ -385,33 +383,33 @@ def format_mcsm_output(mcsm_outputcsv):
print('removing white space within column: wild_position')
mcsm_data['wild_position'] = mcsm_data['wild_position'].str.replace(' ', '')
print('Correctly formatted column: wild_position\n', mcsm_data['wild_position'].head()
, '\n===================================================================')
, '\n=========================================================')
#%%===========================================================================
#%%=====================================================================
#############
# ensuring corrrect dtype in non-numeric cols
#############
#) char cols
char_cols = ['PredAffLog', 'mutation_information', 'wild_type', 'mutant_type', 'chain', 'ligand_id', 'duet_outcome', 'ligand_outcome', 'wild_position']
char_cols = ['PredAffLog', 'mutationinformation', 'wild_type', 'mutant_type', 'chain', 'ligand_id', 'duet_outcome', 'ligand_outcome', 'wild_position']
#mcsm_data[char_cols] = mcsm_data[char_cols].astype(str)
cols_check_char = mcsm_data.select_dtypes(include = 'object').columns.isin(char_cols)
if cols_check_char.all():
print('PASS: dtypes for char cols:', char_cols, 'are indeed string'
, '\n===============================================================')
, '\n===================================================')
else:
sys.exit('FAIL:dtype change to numeric for selected cols unsuccessful'
, '\n===============================================================')
, '\n===================================================')
#mcsm_data['ligand_distance', 'ligand_affinity_change'].apply(is_numeric_dtype(mcsm_data['ligand_distance', 'ligand_affinity_change']))
print(mcsm_data.dtypes)
#%%=============================================================================
#%%=====================================================================
# Removing PredAff log column as it is not needed?
print('Removing col: PredAffLog since relevant info has been extracted from it')
mcsm_dataf = mcsm_data.drop(columns = ['PredAffLog'])
#%%===========================================================================
#%%=====================================================================
#############
# sanity check before writing file
#############
@ -421,14 +419,14 @@ def format_mcsm_output(mcsm_outputcsv):
if len(mcsm_dataf.columns) == expected_cols:
print('PASS: formatting successful'
, '\nformatted df has expected no. of cols:', expected_cols
, '\n---------------------------------------------------------------'
, '\n---------------------------------------------------'
, '\ncolnames:', mcsm_dataf.columns
, '\n----------------------------------------------------------------'
, '\n---------------------------------------------------'
, '\ndtypes in cols:', mcsm_dataf.dtypes
, '\n----------------------------------------------------------------'
, '\n---------------------------------------------------'
, '\norig data shape:', dforig_shape
, '\nformatted df shape:', mcsm_dataf.shape
, '\n===============================================================')
, '\n===================================================')
else:
sys.exit('FAIL: something went wrong in formatting df'
, '\nLen of orig df:', dforig_len
@ -438,7 +436,7 @@ def format_mcsm_output(mcsm_outputcsv):
, '\nCheck formatting:'
, '\ncheck hardcoded value:', expected_ncols_toadd
, '\nis', expected_ncols_toadd, 'the no. of expected cols to add?'
, '\n===============================================================')
, '\n===================================================')
return mcsm_dataf