vary.py
import numpy as np
import sys as sy
import os
class Vary:
def __init__(self, sim, paramFile, fileHandle=None, varyTogether=False):
#For logging
self.sim = sim
self.log = self.sim.log
self.paramFile = paramFile
self.fileHandle = fileHandle
self.varyTogether = varyTogether
#Status bar length
self.barLen = 100
#Load parameters to vary
self.log.log("Loading parameters to vary from %s" % (os.path.join(os.path.dirname(sy.argv[0]), 'config', 'paramsToVary.txt')))
self.tels, self.cams, self.chs, self.opts, self.params, self.mins, self.maxs, self.stps = np.loadtxt(self.paramFile, delimiter='|', dtype=np.str, unpack=True)
self.tels = [tel.strip('\t ') for tel in self.tels]
self.cams = [cam.strip('\t ') for cam in self.cams]
self.chs = [ch.strip('\t ') for ch in self.chs]
self.opts = [opt.strip('\t ') for opt in self.opts]
self.params = [param.strip('\t ') for param in self.params]
#Check for consistency of number of parameters varied
if len(self.tels) == len(self.params) and len(self.params) == len(self.mins) and len(self.mins) == len(self.maxs) and len(self.maxs) == len(self.stps):
self.numParams = len(self.params)
else:
raise Exception('FATAL: Number of telescopes, parameters, mins, maxes, and steps must match for parameters to be varied. Problem with parameter vary file "BoloCalc/config/paramsToVary.txt"\n')
#Construct arrays of parameters
paramArr = [np.arange(float(self.mins[i]), float(self.maxs[i])+float(self.stps[i]), float(self.stps[i])).tolist() for i in range(len(self.params))]
self.numParams = len(paramArr)
self.log.log("Processing %d parameters" % (self.numParams))
#Length of each parameter array
lenArr = [len(paramArr[i]) for i in range(len(paramArr))]
#Store the telescope, camera, channels, and optic name information for each parameter
telsArr = [[self.tels[i] for j in range(len(paramArr[i]))] for i in range(len(paramArr))]
camsArr = [[self.cams[i] for j in range(len(paramArr[i]))] for i in range(len(paramArr))]
chsArr = [[self.chs[i] for j in range(len(paramArr[i]))] for i in range(len(paramArr))]
optsArr = [[self.opts[i] for j in range(len(paramArr[i]))] for i in range(len(paramArr))]
if varyTogether:
#Vary the parameters together. All arrays need to be the same length
if not len(np.shape(np.array(paramArr))) == 2: raise Exception('FATAL: When all parameters are varied together, all parameter arrays must have the same length. Array length is set by np.arange(min, max+step, step)')
self.numEntries = lenArr[0]
self.log.log("Processing %d combinations of parameters" % (self.numEntries))
self.telArr = np.array(telsArr)
self.camArr = np.array(camsArr)
self.chArr = np.array(chsArr)
self.optArr = np.array(optsArr)
self.setArr = np.array(paramArr)
else:
self.numEntries = np.prod(lenArr)
self.log.log("Processing %d combinations of parameters" % (self.numEntries))
#In order to loop over all possible combinations of the parameters, the arrays need to be rebuilt
telArr = []
camArr = []
chArr = []
optArr = []
setArr = []
#Construct one array for each parameter
for i in range(self.numParams):
#For storing names
telArrArr = []
camArrArr = []
chArrArr = []
optArrArr = []
#For storing values
setArrArr = []
#Number of values to be calculated for this parameter
if i < self.numParams-1:
for j in range(lenArr[i]):
telArrArr = telArrArr + [telsArr[i][j]]*np.prod(lenArr[i+1:])
camArrArr = camArrArr + [camsArr[i][j]]*np.prod(lenArr[i+1:])
chArrArr = chArrArr + [chsArr[i][j]]*np.prod(lenArr[i+1:])
optArrArr = optArrArr + [optsArr[i][j]]*np.prod(lenArr[i+1:])
setArrArr = setArrArr + [paramArr[i][j]]*np.prod(lenArr[i+1:])
else:
telArrArr = telArrArr + telsArr[i]
camArrArr = camArrArr + camsArr[i]
chArrArr = chArrArr + chsArr[i]
optArrArr = optArrArr + optsArr[i]
setArrArr = setArrArr + paramArr[i]
if i > 0:
telArr.append(telArrArr*np.prod(lenArr[:i]))
camArr.append(camArrArr*np.prod(lenArr[:i]))
chArr.append( chArrArr*np.prod( lenArr[:i]))
optArr.append(optArrArr*np.prod(lenArr[:i]))
setArr.append(setArrArr*np.prod(lenArr[:i]))
else:
telArr.append(telArrArr)
camArr.append(camArrArr)
chArr.append( chArrArr)
optArr.append(optArrArr)
setArr.append(setArrArr)
self.telArr = np.array(telArr)
self.camArr = np.array(camArr)
self.chArr = np.array(chArr)
self.optArr = np.array(optArr)
self.setArr = np.array(setArr)
#**** Public Methods ****
def vary(self):
self.sim.verbosity = 0
self.sim.generateExps()
self.sim.verbosity = None
self.experiments = self.sim.experiments
#At which level to regenerate each parameter
exR = False; tlR = False; cmR = False
for i in range(len(self.setArr)):
if np.any(self.tels != ''):
exR = True
if np.any(self.cams[i] != ''):
tlR = True
if np.any(self.chs[i] != ''):
cmR = True
#Loop over experiments and store optical power, photon NEP, and NET
expNames = []
telNames = []
camNames = []
chnNames = []
filledNames = False
popt_final = []; poptstd_final = []
nepph_final = []; nepphstd_final = []
net_final = []; netstd_final = []
self.totIters = len(self.experiments)*len(self.setArr[0])
print ("Calculating %d mapping speeds..." % (int(self.totIters)))
for n in range(len(self.experiments)):
experiment = self.experiments[n]
popt = []; poptstd = []
nepph = []; nepphstd = []
net = []; netstd = []
for i in range(len(self.setArr[0])):
for j in range(len(self.setArr)):
if self.tels[j] != '':
if self.cams[j] != '':
if self.chs[j] != '':
if self.opts[j] != '':
experiment.telescopes[self.tels[j]].cameras[self.cams[j]].optChain.optics[self.opts[j]].params[self.params[j]].change(self.setArr[j][i], bandID=int(self.chs[j]))
experiment.telescopes[self.tels[j]].cameras[self.cams[j]].channels[self.chs[j]].generate()
else:
experiment.telescopes[self.tels[j]].cameras[self.cams[j]].channels[self.chs[j]].params[self.params[j]].change(self.setArr[j][i], bandID=int(self.chs[j]))
experiment.telescopes[self.tels[j]].cameras[self.cams[j]].channels[self.chs[j]].generate()
else:
experiment.telescopes[self.tels[j]].cameras[self.cams[j]].params[self.params[j]].change(self.setArr[j][i])
experiment.telescopes[self.tels[j]].cameras[self.cams[j]].generate()
else:
experiment.telescopes[self.tels[j]].params[self.params[j]].change(self.setArr[j][i])
experiment.telescopes[self.tels[j]].generate()
else:
experiment.params[self.params[j]].change(self.setArr[j][i])
experiment.generate()
#After new parameters are stored, re-run mapping speed calculation
dsp = self.sim.calculate()
#Store new sensitivity values
valDict = dsp.dict
#Write the names and values
poptArr = []
nepPhArr = []
netArr = []
for t in sorted(experiment.telescopes.keys()):
telescope = experiment.telescopes[t]
for c in sorted(telescope.cameras.keys()):
camera = telescope.cameras[c]
for h in sorted(camera.channels.keys()):
channel = camera.channels[h]
#Only need to store names of telescopes, cameras, and channels one time
if not filledNames:
expNames.append(experiment.name)
telNames.append(telescope.name)
camNames.append(camera.name)
chnNames.append(channel.name)
poptArr.append(valDict[telescope.name][camera.name][channel.name]['Optical Power'])
nepPhArr.append(valDict[telescope.name][camera.name][channel.name]['Photon NEP'])
netArr.append(valDict[telescope.name][camera.name][channel.name]['Array NET'])
filledNames = True
popt.append(np.array(poptArr).T[0])
poptstd.append(np.array(poptArr).T[1])
nepph.append(np.array(nepPhArr).T[0])
nepphstd.append(np.array(nepPhArr).T[1])
net.append(np.array(netArr).T[0])
netstd.append(np.array(netArr).T[1])
iter = n*len(self.setArr[0])*len(self.setArr) + i + 1
self.__status(iter)
popt_final.append(popt)
poptstd_final.append(poptstd)
nepph_final.append(nepph)
nepphstd_final.append(nepphstd)
net_final.append(net)
netstd_final.append(netstd)
#Store the names of the telescopes, cameras, and channels
self.expNames = expNames
self.telNames = telNames
self.camNames = camNames
self.chnNames = chnNames
#Calculate average and standard deviation across experiments
self.popt_final = np.mean(popt_final, axis=0); self.poptstd_final = np.sqrt(np.mean(np.array(poptstd_final)**2, axis=0) + np.var(np.array(popt_final), axis=0))
self.nepph_final = np.mean(nepph_final, axis=0); self.nepphstd_final = np.sqrt(np.mean(np.array(nepphstd_final)**2, axis=0) + np.var(np.array(nepph_final), axis=0))
self.net_final = np.mean(net_final, axis=0); self.netstd_final = np.sqrt(np.mean(np.array(netstd_final)**2, axis=0) + np.var(np.array(net_final), axis=0))
sy.stdout.write('\n')
def save(self):
#Save parameters to files
#Crate string for file names
if not self.fileHandle is None:
paramString = '_'+self.fileHandle.rstrip('_').lstrip('_')
else:
paramString = ""
for i in range(len(self.params)):
if not self.tels[i] == '':
paramString += ("_%s" % (self.tels[i]))
if not self.cams[i] == '':
paramString += ("_%s" % (self.cams[i]))
if not self.chs[i] == '':
paramString += ("_%s" % (self.chs[i]))
if not self.opts[i] == '':
paramString += ("_%s" % (self.opts[i]))
if not self.params[i] == '':
paramString += ("_%s" % (self.params[i]))
savedir = "paramVary"
id = "mappingSpeedVary"
#fname_popt = ('%s/%s/mappingSpeedVary_Popt%s.txt' % (self.experiments[0].dir, savedir, paramString))
#fname_nepph = ('%s/%s/mappingSpeedVary_NEPph%s.txt' % (self.experiments[0].dir, savedir, paramString))
#fname_net = ('%s/%s/mappingSpeedVary_NETarr%s.txt' % (self.experiments[0].dir, savedir, paramString))
fname_popt = os.path.join(self.experiments[0].dir, savedir, ('%s_Popt%s.txt' % (id, paramString)))
fname_nepph = os.path.join(self.experiments[0].dir, savedir, ('%s_NEPph%s.txt' % (id, paramString)))
fname_net = os.path.join(self.experiments[0].dir, savedir, ('%s_NETarr%s.txt' % (id, paramString)))
#Write optical power file
f = open(fname_popt, 'w')
#Line 1
for i in range(self.numParams):
f.write('%-15s' % (self.tels[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.telNames)):
f.write('%-17s' % (self.telNames[i]))
if i < len(self.telNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Line 2
for i in range(self.numParams):
f.write('%-15s' % (self.cams[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.camNames)):
f.write('%-17s' % (self.camNames[i]))
if i < len(self.camNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Line 3
for i in range(self.numParams):
f.write('%-15s' % (self.chs[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.chnNames)):
f.write('%-17s' % (self.chnNames[i]))
if i < len(self.chnNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Line 4
for i in range(self.numParams):
f.write('%-15s' % (self.opts[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.chnNames)):
f.write(' '*17)
if i < len(self.chnNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Line 5
for i in range(self.numParams):
f.write('%-15s' % (self.params[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.chnNames)):
f.write(' '*17)
if i < len(self.chnNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Write the rest of the lines
for i in range(self.numEntries):
for j in range(self.numParams):
f.write('%-15f' % (self.setArr[j][i]))
if j < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for j in range(len(self.popt_final[i])):
f.write('%6.2f +/- %-6.2f' % (self.popt_final[i][j], self.poptstd_final[i][j]))
if j < len(self.popt_final[i])-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Close file
f.close()
#Write photon NEP to a file
f = open(fname_nepph, 'w')
#Line 1
for i in range(self.numParams):
f.write('%-15s' % (self.tels[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.telNames)):
f.write('%-17s' % (self.telNames[i]))
if i < len(self.telNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Line 2
for i in range(self.numParams):
f.write('%-15s' % (self.cams[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.camNames)):
f.write('%-17s' % (self.camNames[i]))
if i < len(self.camNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Line 3
for i in range(self.numParams):
f.write('%-15s' % (self.chs[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.chnNames)):
f.write('%-17s' % (self.chnNames[i]))
if i < len(self.chnNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Line 4
for i in range(self.numParams):
f.write('%-15s' % (self.opts[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.chnNames)):
f.write(' '*17)
if i < len(self.chnNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Line 5
for i in range(self.numParams):
f.write('%-15s' % (self.params[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.chnNames)):
f.write(' '*17)
if i < len(self.chnNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Write the rest of the lines
for i in range(self.numEntries):
for j in range(self.numParams):
f.write('%-15f' % (self.setArr[j][i]))
if j < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for j in range(len(self.nepph_final[i])):
f.write('%6.2f +/- %-6.2f' % (self.nepph_final[i][j], self.nepphstd_final[i][j]))
if j < len(self.nepph_final[i])-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Close file
f.close()
#Write mapping speed to a file
f = open(fname_net, 'w')
#Line 1
for i in range(self.numParams):
f.write('%-15s' % (self.tels[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.telNames)):
f.write('%-17s' % (self.telNames[i]))
if i < len(self.telNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Line 2
for i in range(self.numParams):
f.write('%-15s' % (self.cams[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.camNames)):
f.write('%-17s' % (self.camNames[i]))
if i < len(self.camNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Line 3
for i in range(self.numParams):
f.write('%-15s' % (self.chs[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.chnNames)):
f.write('%-17s' % (self.chnNames[i]))
if i < len(self.chnNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Line 4
for i in range(self.numParams):
f.write('%-15s' % (self.opts[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.chnNames)):
f.write(' '*17)
if i < len(self.chnNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Line 5
for i in range(self.numParams):
f.write('%-15s' % (self.params[i]))
if i < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for i in range(len(self.chnNames)):
f.write(' '*17)
if i < len(self.chnNames)-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Write the rest of the lines
for i in range(self.numEntries):
for j in range(self.numParams):
f.write('%-15f' % (self.setArr[j][i]))
if j < self.numParams-1:
f.write(' | ')
f.write(' ||| ')
for j in range(len(self.net_final[i])):
f.write('%6.2f +/- %-6.2f' % (self.net_final[i][j], self.netstd_final[i][j]))
if j < len(self.net_final[i])-1:
f.write(' | ')
f.write('\n')
f.write(('-'*(self.numParams*15 + len(self.telNames)*17 + (self.numParams-1)*3 + (len(self.telNames)-1)*3 + 5))+'\n')
#Close file
f.close()
# ***** Private Methods *****
#Status bar
def __status(self, rel):
frac = float(rel)/float(self.totIters)
sy.stdout.write('\r')
sy.stdout.write("[%-*s] %02.1f%%" % (int(self.barLen), '='*int(self.barLen*frac), frac*100.))
sy.stdout.flush()