#loadconc.py - possibly these classes will be added to ajustador/loader.py when ready
# -*- coding:utf-8 -*-
from __future__ import print_function, division
import numpy as np
from ajustador import xml,nrd_fitness
import glob
import os
import operator
msec_per_sec=1000
nM_per_uM=1000
nM_per_mM=1e6
class trace(object):
def __init__(self, molname, x, y,stim_time):
molname_parts=molname.split()
self.molname=molname_parts[0]
if len(molname_parts)>1:
self.units=molname_parts[1]
if len(molname_parts)>2:
#strip out any trailing non-numeric characteris
self.scale=int(''.join([c for c in molname_parts[2] if c.isdigit()]))
else:
self.scale=1
else:
self.units='nM'
self.scale=1
if self.units.startswith('m') or self.units.startswith('(m'):
yvalue=y*nM_per_mM
elif self.units.startswith('u') or self.units.startswith('(u'):
yvalue=y*nM_per_uM
else:
#assume nM (or percent if fret)
yvalue=y
self.wave=np.rec.fromarrays((x, yvalue), names='x,y')
#calculate features: baseline, peaktime, peak value
start_index,basal=nrd_fitness.basal(x,yvalue,stim_time)
pt,peak=nrd_fitness.peak(x,yvalue,start_index)
self.features={'basal':basal, 'stim_pt': start_index,'peaktime':pt,'peakval': peak}
class CSV_conc(object):
"""Load a series of concentration measurements from a CSV file
Each CSV file contains data for one or more molecules:
Time time_units, mol_name1 (nM), [mol_name2]
read time_units (sec,msec,min allowed) and convert to msec
"""
def __init__(self, fname,rootname,stim_time,features=[]):
import pandas as pd
model_num=xml.modelname_to_param(fname,rootname)
self.name=os.path.basename(fname)[0:os.path.basename(fname).rfind('.')]
self.injection=model_num
self.features=features
csv = pd.read_csv(fname, index_col=0)
x_head=csv.index.name.split()
if len(x_head)>1:
time_units=x_head[-1]
if time_units.startswith('sec') or time_units.startswith('(sec'):
time_factor=msec_per_sec
elif time_units.startswith('min') or time_units.startswith('(min'):
time_factor=msec_per_sec*60 #sec_per_min
else:
time_factor=1
print('x column header: {}, time_units: {}, conversion factor: {}'.format(x_head,time_units,time_factor))
else:
time_factor=1
x = csv.index.values*time_factor #time values
#may want to read units of y value, e.g. allow uM or mM and convert to nM
self.waves = {col.split()[0]:trace(col, x, csv[col].values,stim_time) for col in csv.columns}
class CSV_conc_set(object):
#set of files, each one a CSV_conc object, differing in stim protocol
def __init__(self,rootname,stim_time=0,features=[]):
self.stim_time=stim_time*msec_per_sec
self.features=features
if os.path.isdir(rootname): #if directory, look for all csv files
dirname = rootname
filenames=glob.glob(rootname+'/*.csv')
self.name=rootname
else:
if rootname.endswith('.csv'):
#case with single filename specified
filenames=[rootname]
else:
#case with a set of filenames specified, with common "prefix" + variable "suffix"
filenames=glob.glob(rootname+'*.csv')
dirname = os.path.dirname(rootname)
self.name=os.path.basename(rootname)
print('CSV_conc_set:',self.name, 'dir',dirname,'files',filenames,'stim_start (ms)', self.stim_time)
if len(filenames)==0:
print('**************** CSV_conc_set: NO FILES FOUND **************************')
csv_list=[CSV_conc(fn,rootname,self.stim_time,features) for fn in filenames]
csv_list.sort(key=operator.attrgetter('injection'))
self.data=csv_list