<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 1. Import Python Packages
To install the kernel used by NERSC-metatlas users, copy the following text to $HOME/.ipython/kernels/mass_spec_cori/kernel.json
{
 "argv"
Step1:  2. Set atlas, project and output directories from your nersc home directory
Create a project folder name for this analysis by replacing the PROJECTDIRECTORY string text in red below.  Make sure to update the rest of the direcory to point to your home directory.  The pwd block will print out the directory where this jupyter notebook is stored.
Create a subdirectory name for the output, each run through you may want to create a new output folder.
When you run the block the folders will be created in your home directory.  If the directory already exists, the block will just set the path for use with future code blocks.
Step2:  3. Select groups and get QC files
Step3:  4. Get template QC atlas from database
Available templates in Database
Step4:  4b. Uncomment the block below to adjust RT window
Step5:  5. Create metatlas dataset from QC files and QC atlas
Step6:  5b Optional
Step7:  6. Summarize RT peak across files and make data frame
Step8:  7. Create Compound atlas RTs plot and choose file for prediction
Step9:  8. Create RT adjustment model - Linear & Polynomial Regression
Step10:  8. Plot actual vs predict RT values and fit a  median coeff+intercept line
Step11:  9. Choose your model
Step12:  10. Save RT model (optional)
Step13:  11. Auto RT adjust Template atlases
Available templates in Database
Step14:  OPTIONAL BLOCK FOR RT PREDICTION OF CUSTOM ATLAS
<ASSISTANT_TASK:>
Python Code:
from IPython.core.display import Markdown, display, clear_output, HTML
display(HTML("<style>.container { width:100% !important; }</style>"))
%matplotlib notebook
%matplotlib inline
%env HDF5_USE_FILE_LOCKING=FALSE
import sys, os
#### add a path to your private code if not using production code ####
#print ('point path to metatlas repo')
sys.path.insert(0,"/global/homes/v/vrsingan/repos/metatlas") #where your private code is
######################################################################
from metatlas.plots import dill2plots as dp
from metatlas.io import metatlas_get_data_helper_fun as ma_data
from metatlas.plots import chromatograms_mp_plots as cp
from metatlas.plots import chromplotplus as cpp
from metatlas.datastructures import metatlas_objects as metob
import time
import numpy as np
import multiprocessing as mp
import pandas as pd
import operator
import matplotlib.pyplot as plt
pd.set_option('display.max_rows', 5000)
pd.set_option('display.max_columns', 500)
pd.set_option('display.max_colwidth', 100)
def printmd(string):
    display(Markdown(string))
Explanation: 1. Import Python Packages
To install the kernel used by NERSC-metatlas users, copy the following text to $HOME/.ipython/kernels/mass_spec_cori/kernel.json
{
 "argv": [
  "/global/common/software/m2650/python-cori/bin/python",
  "-m",
  "IPython.kernel",
  "-f",
  "{connection_file}"
 ],
 "env": {
    "PATH": "/global/common/software/m2650/python-cori/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
 },
 "display_name": "mass_spec_cori",
 "language": "python"
}
End of explanation
project_directory='/global/homes/FIRST-INITIAL-OF-USERNAME/USERNAME/PROJECTDIRECTORY/'  # <- edit this line, do not copy the path directly from NERSC (ex. the u1, or u2 directories)
output_subfolder='HILIC_POS_20190830/'  # <- edit this as 'chromatography_polarity_yyyymmdd/'
output_dir = os.path.join(project_directory,output_subfolder)
output_data_qc = os.path.join(output_dir,'data_QC')
if not os.path.exists(project_directory):
    os.makedirs(project_directory)
if not os.path.exists(output_dir):
    os.makedirs(output_dir)
if not os.path.exists(output_data_qc):
    os.makedirs(output_data_qc)
Explanation: 2. Set atlas, project and output directories from your nersc home directory
Create a project folder name for this analysis by replacing the PROJECTDIRECTORY string text in red below.  Make sure to update the rest of the direcory to point to your home directory.  The pwd block will print out the directory where this jupyter notebook is stored.
Create a subdirectory name for the output, each run through you may want to create a new output folder.
When you run the block the folders will be created in your home directory.  If the directory already exists, the block will just set the path for use with future code blocks.
End of explanation
groups = dp.select_groups_for_analysis(name = '%20201106%505892%HILIC%KLv1%',
                                       most_recent = True,
                                       remove_empty = True,
                                       include_list = ['QC'], exclude_list = ['NEG'])  #['QC','Blank']
groups = sorted(groups, key=operator.attrgetter('name'))
file_df = pd.DataFrame(columns=['file','time','group'])
for g in groups:
    for f in g.items:
        if hasattr(f, 'acquisition_time'):
            file_df = file_df.append({'file':f, 'time':f.acquisition_time,'group':g}, ignore_index=True)
        else:
            file_df = file_df.append({'file':f, 'time':0,'group':g}, ignore_index=True)
file_df = file_df.sort_values(by=['time'])
for file_data in file_df.iterrows():
    print(file_data[1].file.name)
Explanation: 3. Select groups and get QC files
End of explanation
# DO NOT EDIT THIS BLOCK
pos_templates = ['HILICz150_ANT20190824_TPL_EMA_Unlab_POS',
'HILICz150_ANT20190824_TPL_QCv3_Unlab_POS',
'HILICz150_ANT20190824_TPL_ISv5_Unlab_POS',
'HILICz150_ANT20190824_TPL_ISv5_13C15N_POS',
'HILICz150_ANT20190824_TPL_IS_LabUnlab2_POS']
neg_templates = ['HILICz150_ANT20190824_TPL_EMA_Unlab_NEG',
'HILICz150_ANT20190824_TPL_QCv3_Unlab_NEG',
'HILICz150_ANT20190824_TPL_ISv5_Unlab_NEG',
'HILICz150_ANT20190824_TPL_ISv5_13C15N_NEG',
'HILICz150_ANT20190824_TPL_IS_LabUnlab2_NEG']
#Atlas File Name 
QC_template_filename = pos_templates[1]
atlases = metob.retrieve('Atlas',name=QC_template_filename,
                         username='vrsingan')
names = []
for i,a in enumerate(atlases):
    print(i,a.name,pd.to_datetime(a.last_modified,unit='s'),len(a.compound_identifications))
# #Alternatively use this block to create QC atlas from spreadsheet
# import datetime
#dp = reload(dp)
# QC_template_filename = " " #<- Give the template filename to be used for storing in Database
#myAtlas = dp.make_atlas_from_spreadsheet('/global/project/projectdirs/metatlas/projects/1_TemplateAtlases/TemplateAtlas_HILICz150mm_Annotation20190824_QCv3_Unlabeled_Positive.csv',
#                                       QC_template_filename,
#                                        filetype='csv',
#                                        sheetname='',
#                                        polarity = 'positive',
#                                        store=True,
#                                       mz_tolerance = 20)
#atlases = dp.get_metatlas_atlas(name=QC_template_filename,do_print = True,most_recent=True)
myAtlas = atlases[-1]
atlas_df = ma_data.make_atlas_df(myAtlas)
atlas_df['label'] = [cid.name for cid in myAtlas.compound_identifications]
print(myAtlas.name)
print(myAtlas.username)
Explanation: 4. Get template QC atlas from database
Available templates in Database:
Index  Atlas_name(POS)\
0   HILICz150_ANT20190824_TPL_EMA_Unlab_POS\
1   HILICz150_ANT20190824_TPL_QCv3_Unlab_POS\
2   HILICz150_ANT20190824_TPL_ISv5_Unlab_POS\
3   HILICz150_ANT20190824_TPL_ISv5_13C15N_POS\
4   HILICz150_ANT20190824_TPL_IS_LabUnlab2_POS
Index  Atlas_name(NEG)\
0   HILICz150_ANT20190824_TPL_EMA_Unlab_NEG\
1   HILICz150_ANT20190824_TPL_QCv3_Unlab_NEG\
2   HILICz150_ANT20190824_TPL_ISv5_Unlab_NEG\
3   HILICz150_ANT20190824_TPL_ISv5_13C15N_NEG\
4   HILICz150_ANT20190824_TPL_IS_LabUnlab2_NEG
End of explanation
# rt_allowance = 1.5
# atlas_df['rt_min'] = atlas_df['rt_peak'].apply(lambda rt: rt-rt_allowance)
# atlas_df['rt_max'] = atlas_df['rt_peak'].apply(lambda rt: rt+rt_allowance)
# for compound in range(len(myAtlas.compound_identifications)):
#     rt_peak = myAtlas.compound_identifications[compound].rt_references[0].rt_peak
#     myAtlas.compound_identifications[compound].rt_references[0].rt_min = rt_peak - rt_allowance
#     myAtlas.compound_identifications[compound].rt_references[0].rt_max = rt_peak + rt_allowance
Explanation: 4b. Uncomment the block below to adjust RT window
End of explanation
all_files = []
for file_data in file_df.iterrows():
    all_files.append((file_data[1].file,file_data[1].group,atlas_df,myAtlas))
pool = mp.Pool(processes=min(4, len(all_files)))
t0 = time.time()
metatlas_dataset = pool.map(ma_data.get_data_for_atlas_df_and_file, all_files)
pool.close()
pool.terminate()
#If you're code crashes here, make sure to terminate any processes left open.
print(time.time() - t0)
Explanation: 5. Create metatlas dataset from QC files and QC atlas
End of explanation
# dp = reload(dp)
# num_data_points_passing = 3
# peak_height_passing = 1e4
# atlas_df_passing = dp.filter_atlas(atlas_df=atlas_df, input_dataset=metatlas_dataset, num_data_points_passing = num_data_points_passing, peak_height_passing = peak_height_passing)
# print("# Compounds in Atlas: "+str(len(atlas_df)))
# print("# Compounds passing filter: "+str(len(atlas_df_passing)))
# atlas_passing = myAtlas.name+'_filteredby-datapnts'+str(num_data_points_passing)+'-pkht'+str(peak_height_passing)
# myAtlas_passing = dp.make_atlas_from_spreadsheet(atlas_df_passing,
#                           atlas_passing,
#                           filetype='dataframe',
#                           sheetname='',
#                           polarity = 'positive',
#                           store=True,
#                           mz_tolerance = 20)
# atlases = dp.get_metatlas_atlas(name=atlas_passing,do_print = True, most_recent=True)
# myAtlas = atlases[-1]
# atlas_df = ma_data.make_atlas_df(myAtlas)
# atlas_df['label'] = [cid.name for cid in myAtlas.compound_identifications]
# print(myAtlas.name)
# print(myAtlas.username)
# metob.to_dataframe([myAtlas])# 
# all_files = []
# for file_data in file_df.iterrows():
#     all_files.append((file_data[1].file,file_data[1].group,atlas_df,myAtlas))
# pool = mp.Pool(processes=min(4, len(all_files)))
# t0 = time.time()
# metatlas_dataset = pool.map(ma_data.get_data_for_atlas_df_and_file, all_files)
# pool.close()
# pool.terminate()
# #If you're code crashes here, make sure to terminate any processes left open.
# print(time.time() - t0)
Explanation: 5b Optional: Filter atlas for compounds with no or low signals
Uncomment the below 3 blocks to filter the atlas.
Please ensure that correct polarity is used for the atlases.
End of explanation
from importlib import reload
dp=reload(dp)
rts_df = dp.make_output_dataframe(input_dataset = metatlas_dataset, fieldname='rt_peak', use_labels=True, output_loc = output_data_qc, summarize=True)
rts_df.to_csv(os.path.join(output_data_qc,"QC_Measured_RTs.csv"))
rts_df
Explanation: 6. Summarize RT peak across files and make data frame
End of explanation
import itertools
import math
from __future__ import division
from matplotlib import gridspec
import matplotlib.ticker as mticker
rts_df['atlas RT peak'] = [compound['identification'].rt_references[0].rt_peak for compound in metatlas_dataset[0]]
# number of columns in rts_df that are not values from a specific input file
num_not_files = len(rts_df.columns) - len(metatlas_dataset)
rts_df_plot = rts_df.sort_values(by='standard deviation', ascending=False, na_position='last') \
    .drop(['#NaNs'], axis=1) \
    .dropna(axis=0, how='all', subset=rts_df.columns[:-num_not_files])
fontsize = 2
pad = 0.1
cols = 8
rows = int(math.ceil((rts_df.shape[0]+1)/8))
fig = plt.figure()
gs = gridspec.GridSpec(rows, cols, figure=fig, wspace=0.2, hspace=0.4)
for i, (index, row) in enumerate(rts_df_plot.iterrows()):
    ax = fig.add_subplot(gs[i])
    ax.tick_params(direction='in', length=1, pad=pad, width=0.1, labelsize=fontsize)
    ax.scatter(range(rts_df_plot.shape[1]-num_not_files),row[:-num_not_files], s=0.2)
    ticks_loc = np.arange(0,len(rts_df_plot.columns)-num_not_files , 1.0)
    ax.axhline(y=row['atlas RT peak'], color='r', linestyle='-', linewidth=0.2)
    ax.set_xlim(-0.5,len(rts_df_plot.columns)-num_not_files+0.5)
    ax.xaxis.set_major_locator(mticker.FixedLocator(ticks_loc))
    range_columns = list(rts_df_plot.columns[:-num_not_files])+['atlas RT peak']
    ax.set_ylim(np.nanmin(row.loc[range_columns])-0.12,
                np.nanmax(row.loc[range_columns])+0.12)
    [s.set_linewidth(0.1) for s in ax.spines.values()]
    # truncate name so it fits above a single subplot
    ax.set_title(row.name[:33], pad=pad, fontsize=fontsize)
    ax.set_xlabel('Files', labelpad=pad, fontsize=fontsize)
    ax.set_ylabel('Actual RTs', labelpad=pad, fontsize=fontsize)
plt.savefig(os.path.join(output_data_qc, 'Compound_Atlas_RTs.pdf'), bbox_inches="tight")
for i,a in enumerate(rts_df.columns):
    print(i, a)
selected_column=9
Explanation: 7. Create Compound atlas RTs plot and choose file for prediction
End of explanation
from sklearn.linear_model import LinearRegression, RANSACRegressor
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_absolute_error as mae
actual_rts, pred_rts, polyfit_rts = [],[],[]
current_actual_df = rts_df.loc[:,rts_df.columns[selected_column]]
bad_qc_compounds = np.where(~np.isnan(current_actual_df))
current_actual_df = current_actual_df.iloc[bad_qc_compounds]
current_pred_df = atlas_df.iloc[bad_qc_compounds][['rt_peak']]
actual_rts.append(current_actual_df.values.tolist())
pred_rts.append(current_pred_df.values.tolist())
ransac = RANSACRegressor(random_state=42)
rt_model_linear = ransac.fit(current_pred_df, current_actual_df)
coef_linear = rt_model_linear.estimator_.coef_[0]
intercept_linear = rt_model_linear.estimator_.intercept_
poly_reg = PolynomialFeatures(degree=2)
X_poly = poly_reg.fit_transform(current_pred_df)
rt_model_poly = LinearRegression().fit(X_poly, current_actual_df)
coef_poly = rt_model_poly.coef_
intercept_poly = rt_model_poly.intercept_
for i in range(rts_df.shape[1]-5):
    current_actual_df = rts_df.loc[:,rts_df.columns[i]]
    bad_qc_compounds = np.where(~np.isnan(current_actual_df))
    current_actual_df = current_actual_df.iloc[bad_qc_compounds]
    current_pred_df = atlas_df.iloc[bad_qc_compounds][['rt_peak']]
    actual_rts.append(current_actual_df.values.tolist())
    pred_rts.append(current_pred_df.values.tolist())
Explanation: 8. Create RT adjustment model - Linear & Polynomial Regression
End of explanation
#User can change to use particular qc file
import itertools
import math
from __future__ import division
from matplotlib import gridspec
x = list(itertools.chain(*pred_rts))
y = list(itertools.chain(*actual_rts))
rows = int(math.ceil((rts_df.shape[1]+1)/5))
cols = 5
fig = plt.figure(constrained_layout=False)
gs = gridspec.GridSpec(rows, cols, figure=fig)
plt.rc('font', size=6)
plt.rc('axes', labelsize=6)
plt.rc('xtick', labelsize=3)
plt.rc('ytick', labelsize=3)
for i in range(rts_df.shape[1]-5):
    x = list(itertools.chain(*pred_rts[i]))
    y = actual_rts[i]
    
    ax = fig.add_subplot(gs[i])
    ax.scatter(x, y, s=2)
    ax.plot(np.linspace(0, max(x),100), coef_linear*np.linspace(0,max(x),100)+intercept_linear, linewidth=0.5,color='red')
    ax.plot(np.linspace(0, max(x),100), (coef_poly[1]*np.linspace(0,max(x),100))+(coef_poly[2]*(np.linspace(0,max(x),100)**2))+intercept_poly, linewidth=0.5,color='green')
    ax.set_title("File: "+str(i))
    ax.set_xlabel('predicted RTs')
    ax.set_ylabel('actual RTs')
    
fig_legend = "FileIndex       FileName"
for i in range(rts_df.shape[1]-5):
    fig_legend = fig_legend+"\n"+str(i)+"        "+rts_df.columns[i]
fig.tight_layout(pad=0.5)
plt.text(0,-0.03*rts_df.shape[1], fig_legend, transform=plt.gcf().transFigure)
plt.savefig(os.path.join(output_data_qc, 'Actual_vs_Predicted_RTs.pdf'), bbox_inches="tight")
Explanation: 8. Plot actual vs predict RT values and fit a  median coeff+intercept line
End of explanation
qc_df = rts_df[[rts_df.columns[selected_column]]]
qc_df = qc_df.copy()
print("Linear Parameters :", coef_linear, intercept_linear)
print("Polynomial Parameters :", coef_poly,intercept_poly)
qc_df.columns = ['RT Measured']
atlas_df.index = qc_df.index
qc_df['RT Reference'] = atlas_df['rt_peak']
qc_df['RT Linear Pred'] = qc_df['RT Reference'].apply(lambda rt: coef_linear*rt+intercept_linear)
qc_df['RT Polynomial Pred'] = qc_df['RT Reference'].apply(lambda rt: (coef_poly[1]*rt)+(coef_poly[2]*(rt**2))+intercept_poly) 
qc_df['RT Diff Linear'] = qc_df['RT Measured'] - qc_df['RT Linear Pred']
qc_df['RT Diff Polynomial'] = qc_df['RT Measured'] - qc_df['RT Polynomial Pred']
qc_df.to_csv(os.path.join(output_data_qc, "RT_Predicted_Model_Comparison.csv"))
qc_df
# CHOOSE YOUR MODEL HERE (linear / polynomial).
#model = 'linear' 
model = 'polynomial'  
Explanation: 9. Choose your model
End of explanation
# Save model
    
with open(os.path.join(output_data_qc,'rt_model.txt'), 'w') as f:
    if model == 'linear':
        f.write('coef = {}\nintercept = {}\nqc_actual_rts = {}\nqc_predicted_rts = {}'.format(coef_linear, 
                                                                intercept_linear, 
                                                                ', '.join([g.name for g in groups]),
                                                                myAtlas.name))
        f.write('\n'+repr(rt_model_linear.set_params()))
        
    else:
        f.write('coef = {}\nintercept = {}\nqc_actual_rts = {}\nqc_predicted_rts = {}'.format(coef_poly, 
                                                                intercept_poly, 
                                                                ', '.join([g.name for g in groups]),
                                                                myAtlas.name))
        f.write('\n'+repr(rt_model_poly.set_params()))
    
    
Explanation: 10. Save RT model (optional)
End of explanation
pos_atlas_indices = [0,1,2,3,4]
neg_atlas_indices = [0,1,2,3,4]
free_text = '' # this will be appended to the end of the csv filename exported
save_to_db = False
for ix in pos_atlas_indices:
    atlases = metob.retrieve('Atlas',name=pos_templates[ix], username='vrsingan')
    prd_atlas_name = pos_templates[ix].replace('TPL', 'PRD')
    if free_text != '':
        prd_atlas_name = prd_atlas_name+"_"+free_text
    prd_atlas_filename = prd_atlas_name+'.csv'
    myAtlas = atlases[-1]
    PRD_atlas_df = ma_data.make_atlas_df(myAtlas)
    PRD_atlas_df['label'] = [cid.name for cid in myAtlas.compound_identifications]
    if model == 'linear':
        PRD_atlas_df['rt_peak'] = PRD_atlas_df['rt_peak'].apply(lambda rt: coef_linear*rt+intercept_linear)
    else:
        PRD_atlas_df['rt_peak'] = PRD_atlas_df['rt_peak'].apply(lambda rt: (coef_poly[1]*rt)+(coef_poly[2]*(rt**2))+intercept_poly)
    PRD_atlas_df['rt_min'] = PRD_atlas_df['rt_peak'].apply(lambda rt: rt-.5)
    PRD_atlas_df['rt_max'] = PRD_atlas_df['rt_peak'].apply(lambda rt: rt+.5)
    
    PRD_atlas_df.to_csv(os.path.join(output_data_qc,prd_atlas_filename), index=False)
    
    if save_to_db:
            dp.make_atlas_from_spreadsheet(PRD_atlas_df,
                          prd_atlas_name,
                          filetype='dataframe',
                          sheetname='',
                          polarity = 'positive',
                          store=True,
                          mz_tolerance = 12)
    print(prd_atlas_name+" Created!")
for ix in neg_atlas_indices:
    atlases = metob.retrieve('Atlas',name=neg_templates[ix], username='vrsingan')
    prd_atlas_name = neg_templates[ix].replace('TPL', 'PRD')
    if free_text != '':
        prd_atlas_name = prd_atlas_name+"_"+free_text
    prd_atlas_filename = prd_atlas_name+'.csv'
    myAtlas = atlases[-1]
    PRD_atlas_df = ma_data.make_atlas_df(myAtlas)
    PRD_atlas_df['label'] = [cid.name for cid in myAtlas.compound_identifications]
    if model == 'linear':
        PRD_atlas_df['rt_peak'] = PRD_atlas_df['rt_peak'].apply(lambda rt: coef_linear*rt+intercept_linear)
    else:
        PRD_atlas_df['rt_peak'] = PRD_atlas_df['rt_peak'].apply(lambda rt: (coef_poly[1]*rt)+(coef_poly[2]*(rt**2))+intercept_poly)
    PRD_atlas_df['rt_min'] = PRD_atlas_df['rt_peak'].apply(lambda rt: rt-.5)
    PRD_atlas_df['rt_max'] = PRD_atlas_df['rt_peak'].apply(lambda rt: rt+.5)
    
    PRD_atlas_df.to_csv(os.path.join(output_data_qc,prd_atlas_filename), index=False)
    
    if save_to_db:
            dp.make_atlas_from_spreadsheet(PRD_atlas_df,
                          prd_atlas_name,
                          filetype='dataframe',
                          sheetname='',
                          polarity = 'negative',
                          store=True,
                          mz_tolerance = 12)
    
    print(prd_atlas_name+" Created!")
Explanation: 11. Auto RT adjust Template atlases
Available templates in Database:
Index  Atlas_name(POS)\
0   HILICz150_ANT20190824_TPL_EMA_Unlab_POS\
1   HILICz150_ANT20190824_TPL_QCv3_Unlab_POS\
2   HILICz150_ANT20190824_TPL_ISv5_Unlab_POS\
3   HILICz150_ANT20190824_TPL_ISv5_13C15N_POS\
4   HILICz150_ANT20190824_TPL_IS_LabUnlab2_POS
Index  Atlas_name(NEG)\
0   HILICz150_ANT20190824_TPL_EMA_Unlab_NEG\
1   HILICz150_ANT20190824_TPL_QCv3_Unlab_NEG\
2   HILICz150_ANT20190824_TPL_ISv5_Unlab_NEG\
3   HILICz150_ANT20190824_TPL_ISv5_13C15N_NEG\
4   HILICz150_ANT20190824_TPL_IS_LabUnlab2_NEG
End of explanation
## Optional for custom template predictions
# atlas_name = '' #atlas name
# save_to_db = False
# atlases = metob.retrieve('Atlas',name=atlas_name, username='*')
# myAtlas = atlases[-1]
# PRD_atlas_df = ma_data.make_atlas_df(myAtlas)
# PRD_atlas_df['label'] = [cid.name for cid in myAtlas.compound_identifications]
# if model == 'linear':
#     PRD_atlas_df['rt_peak'] = PRD_atlas_df['rt_peak'].apply(lambda rt: coef_linear*rt+intercept_linear)
# else:
#     PRD_atlas_df['rt_peak'] = PRD_atlas_df['rt_peak'].apply(lambda rt: (coef_poly[1]*rt)+(coef_poly[2]*(rt**2))+intercept_poly)
# PRD_atlas_df['rt_min'] = PRD_atlas_df['rt_peak'].apply(lambda rt: rt-.5)
# PRD_atlas_df['rt_max'] = PRD_atlas_df['rt_peak'].apply(lambda rt: rt+.5)
    
# PRD_atlas_df.to_csv(os.path.join(output_data_qc, name=atlas_name.replace('TPL','PRD'), index=False)
    
# if save_to_db:
#     dp.make_atlas_from_spreadsheet(PRD_atlas_df,
#                     PRD_atlas_name,
#                     filetype='dataframe',
#                     sheetname='',
#                     polarity = 'positive', # NOTE - Please make sure you are choosing the correct polarity
#                     store=True,
#                     mz_tolerance = 12)
Explanation: OPTIONAL BLOCK FOR RT PREDICTION OF CUSTOM ATLAS
End of explanation
<END_TASK>