mirror of
https://github.com/nqrduck/LimeDriver.git
synced 2024-11-25 19:42:29 +00:00
Refactor limr class for enhanced functionality
Refactored the limr class to streamline initialization and improve parameter management by directly fetching default parameters from the `limedriver` binary with a `--dump` flag, eliminating manual parsing, leading to more robust and maintainable code. These changes improve the maintainability and extend the functionality of the parameter handling in the limr class, making it easier to scale and adapt for future requirements.
This commit is contained in:
parent
72e809ccec
commit
a4d109dffd
1 changed files with 316 additions and 279 deletions
409
src/limr.py
409
src/limr.py
|
@ -15,54 +15,31 @@ Note for release: The communication between the python and the Cpp routine is ve
|
||||||
Update Feb 2020: Slight changes to make it compatible with Python 3
|
Update Feb 2020: Slight changes to make it compatible with Python 3
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import subprocess # to call the program
|
import subprocess # to call the program
|
||||||
import datetime # to generate timestamps for parsweeps
|
import datetime # to generate timestamps for parsweeps
|
||||||
import h5py # to have organized data storage.....
|
import h5py # to have organized data storage.....
|
||||||
import numpy as np # ...
|
import numpy as np # ...
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
class limr():
|
class limr:
|
||||||
|
|
||||||
def __init__(self, filename = './pulseN_USB.cpp'):
|
|
||||||
|
|
||||||
# check first for the filename provided
|
|
||||||
if filename[-3:] == 'cpp':
|
|
||||||
self.Csrc = filename
|
|
||||||
else:
|
|
||||||
self.Csrc = './pulseN_USB.cpp'
|
|
||||||
|
|
||||||
|
def __init__(self, filename="./limedriver"):
|
||||||
# the program to call
|
# the program to call
|
||||||
self.Cprog = self.Csrc[:-4]
|
self.Cprog = filename
|
||||||
|
|
||||||
fp = open(self.Csrc, 'r')
|
# fetch the default parameters from the limedriver binary
|
||||||
|
str2call = self.Cprog + " --dump"
|
||||||
|
|
||||||
in_arg = {}
|
p = subprocess.Popen(
|
||||||
startpattern = 'struct Config2HDFattr_t HDFattr[]'
|
str2call.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||||
stoppattern = '};'
|
)
|
||||||
parsing = False
|
|
||||||
ii_oupargs = 0
|
|
||||||
for line in fp.readlines():
|
|
||||||
if (stoppattern in line) & parsing:
|
|
||||||
break
|
|
||||||
if parsing:
|
|
||||||
stripped = line.replace('\t','').replace('"','').strip('\n').strip(',').strip('{').strip('}')
|
|
||||||
splitted = stripped.split(',')
|
|
||||||
# remove irrrelevant stuff
|
|
||||||
rmvidx = range(4,len(splitted)-1)
|
|
||||||
for ii in range(len(rmvidx)):
|
|
||||||
splitted.pop(4)
|
|
||||||
if splitted[0] == '///':
|
|
||||||
splitted[0] = '//' + str(ii_oupargs)
|
|
||||||
ii_oupargs+=1
|
|
||||||
in_arg[splitted[0]] = splitted
|
|
||||||
in_arg[splitted[0]][0] = []
|
|
||||||
if startpattern in line:
|
|
||||||
parsing = True
|
|
||||||
fp.close()
|
|
||||||
|
|
||||||
self.parsinp = in_arg
|
# read the output
|
||||||
|
in_arg = json.loads(p.stdout.read().decode("utf-8"))
|
||||||
|
|
||||||
|
# initialize the parameters
|
||||||
for key in in_arg:
|
for key in in_arg:
|
||||||
setattr(self, key, in_arg[key][0])
|
setattr(self, key, in_arg[key][0])
|
||||||
|
|
||||||
|
@ -76,13 +53,11 @@ class limr():
|
||||||
self.segcount = 0
|
self.segcount = 0
|
||||||
|
|
||||||
# print the arguments that have been set
|
# print the arguments that have been set
|
||||||
def print_params(self, allel = False):
|
def print_params(self, allel=False):
|
||||||
for key in sorted(self.parsinp):
|
for key in sorted(self.parsinp):
|
||||||
val = getattr(self,key)
|
val = getattr(self, key)
|
||||||
if (val != []) | (allel):
|
if (val != []) | (allel):
|
||||||
print('{:<5}: {:>50} {:<25}'.format(key, val, self.parsinp[key][1]))
|
print("{:<5}: {:>50} {:<25}".format(key, val, self.parsinp[key][1]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# add parameter variation:
|
# add parameter variation:
|
||||||
# key is the argument to vary
|
# key is the argument to vary
|
||||||
|
@ -90,51 +65,73 @@ class limr():
|
||||||
# strt the starting point
|
# strt the starting point
|
||||||
# end the endpoint
|
# end the endpoint
|
||||||
# npts the dimension of the sweep
|
# npts the dimension of the sweep
|
||||||
def parsweep(self, key, strt, end, npts, idx = 0):
|
def parsweep(self, key, strt, end, npts, idx=0):
|
||||||
|
|
||||||
if ~isinstance(idx,list): idx = [idx] # idx as list eases iteration
|
if ~isinstance(idx, list):
|
||||||
|
idx = [idx] # idx as list eases iteration
|
||||||
|
|
||||||
# check the key
|
# check the key
|
||||||
try:
|
try:
|
||||||
vals = getattr(self,key)
|
vals = getattr(self, key)
|
||||||
except:
|
except:
|
||||||
print('Problem with sweep: Key ' + key + ' is not valid! See below for valid keys')
|
print(
|
||||||
|
"Problem with sweep: Key "
|
||||||
|
+ key
|
||||||
|
+ " is not valid! See below for valid keys"
|
||||||
|
)
|
||||||
self.print_params(allel=True)
|
self.print_params(allel=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
# check for existing val and for proper dimension. Dimension is a priori not known due to number of pulses that can be flexible
|
# check for existing val and for proper dimension. Dimension is a priori not known due to number of pulses that can be flexible
|
||||||
if (vals == []):
|
if vals == []:
|
||||||
print('Problem with sweep: Initialize first a value to argument ' + key +'. I will try with assuming zero')
|
print(
|
||||||
vals = 0;
|
"Problem with sweep: Initialize first a value to argument "
|
||||||
|
+ key
|
||||||
|
+ ". I will try with assuming zero"
|
||||||
|
)
|
||||||
|
vals = 0
|
||||||
if isinstance(vals, (list, np.ndarray)):
|
if isinstance(vals, (list, np.ndarray)):
|
||||||
if len(vals) < max(idx):
|
if len(vals) < max(idx):
|
||||||
print('Problem with sweep: ' + key + ' has only ' + str(len(vals)) + ' objects, while an index of ' + str(max(idx)) + ' was requested!')
|
print(
|
||||||
|
"Problem with sweep: "
|
||||||
|
+ key
|
||||||
|
+ " has only "
|
||||||
|
+ str(len(vals))
|
||||||
|
+ " objects, while an index of "
|
||||||
|
+ str(max(idx))
|
||||||
|
+ " was requested!"
|
||||||
|
)
|
||||||
return
|
return
|
||||||
startlist = [[vals[jj] for jj in range(len(vals))] for ii in range(npts)]
|
startlist = [[vals[jj] for jj in range(len(vals))] for ii in range(npts)]
|
||||||
elif max(idx) > 0:
|
elif max(idx) > 0:
|
||||||
print('Problem with sweep: ' + key + ' is scalar, while an index of ' + str(max(idx)) + ' was requested!')
|
print(
|
||||||
|
"Problem with sweep: "
|
||||||
|
+ key
|
||||||
|
+ " is scalar, while an index of "
|
||||||
|
+ str(max(idx))
|
||||||
|
+ " was requested!"
|
||||||
|
)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
startlist = [[vals] for ii in range(npts)]
|
startlist = [[vals] for ii in range(npts)]
|
||||||
|
|
||||||
# check if a parvar already exists for this key
|
# check if a parvar already exists for this key
|
||||||
if len(self.parvar) == 0:
|
if len(self.parvar) == 0:
|
||||||
self.parvar['sweeplist'] = startlist
|
self.parvar["sweeplist"] = startlist
|
||||||
elif not((key == self.parvar['key']) & (npts == self.parvar['dim'])):
|
elif not ((key == self.parvar["key"]) & (npts == self.parvar["dim"])):
|
||||||
self.parvar['sweeplist'] = startlist
|
self.parvar["sweeplist"] = startlist
|
||||||
|
|
||||||
self.parvar['key'] = key
|
self.parvar["key"] = key
|
||||||
self.parvar['dim'] = npts
|
self.parvar["dim"] = npts
|
||||||
|
|
||||||
if npts > 1:
|
if npts > 1:
|
||||||
incr = (end - strt)/(npts-1)
|
incr = (end - strt) / (npts - 1)
|
||||||
else:
|
else:
|
||||||
incr = 0;
|
incr = 0
|
||||||
|
|
||||||
|
|
||||||
for ii_swp in range(npts):
|
for ii_swp in range(npts):
|
||||||
for swp_idx in idx:
|
for swp_idx in idx:
|
||||||
self.parvar['sweeplist'][ii_swp][swp_idx] = strt + ii_swp*incr
|
self.parvar["sweeplist"][ii_swp][swp_idx] = strt + ii_swp * incr
|
||||||
|
|
||||||
# add coupled parameter variation of another variable: (one variable is not enough... two neither, but better than one. A list of dicts would more general....)
|
# add coupled parameter variation of another variable: (one variable is not enough... two neither, but better than one. A list of dicts would more general....)
|
||||||
# key is the argument to vary
|
# key is the argument to vary
|
||||||
|
@ -142,183 +139,216 @@ class limr():
|
||||||
# strt the starting point
|
# strt the starting point
|
||||||
# end the endpoint
|
# end the endpoint
|
||||||
# npts the dimension of the sweep
|
# npts the dimension of the sweep
|
||||||
def parsweep_cpl(self, key, strt, end, npts, idx = 0):
|
def parsweep_cpl(self, key, strt, end, npts, idx=0):
|
||||||
|
|
||||||
if ~isinstance(idx,list): idx = [idx] # idx as list eases iteration
|
if ~isinstance(idx, list):
|
||||||
|
idx = [idx] # idx as list eases iteration
|
||||||
|
|
||||||
# check the key
|
# check the key
|
||||||
try:
|
try:
|
||||||
vals = getattr(self,key)
|
vals = getattr(self, key)
|
||||||
except:
|
except:
|
||||||
print('Problem with sweep: Key ' + key + ' is not valid! See below for valid keys')
|
print(
|
||||||
|
"Problem with sweep: Key "
|
||||||
|
+ key
|
||||||
|
+ " is not valid! See below for valid keys"
|
||||||
|
)
|
||||||
self.print_params(allel=True)
|
self.print_params(allel=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
# check for existing val and for proper dimension. Dimension is a priori not known due to number of pulses that can be flexible
|
# check for existing val and for proper dimension. Dimension is a priori not known due to number of pulses that can be flexible
|
||||||
if (vals == []):
|
if vals == []:
|
||||||
print('Problem with sweep: Initialize first a value to argument ' + key +'. I will try with assuming zero')
|
print(
|
||||||
vals = 0;
|
"Problem with sweep: Initialize first a value to argument "
|
||||||
|
+ key
|
||||||
|
+ ". I will try with assuming zero"
|
||||||
|
)
|
||||||
|
vals = 0
|
||||||
if isinstance(vals, (list, np.ndarray)):
|
if isinstance(vals, (list, np.ndarray)):
|
||||||
if len(vals) < max(idx):
|
if len(vals) < max(idx):
|
||||||
print('Problem with sweep: ' + key + ' has only ' + str(len(vals)) + ' objects, while an index of ' + str(max(idx)) + ' was requested!')
|
print(
|
||||||
|
"Problem with sweep: "
|
||||||
|
+ key
|
||||||
|
+ " has only "
|
||||||
|
+ str(len(vals))
|
||||||
|
+ " objects, while an index of "
|
||||||
|
+ str(max(idx))
|
||||||
|
+ " was requested!"
|
||||||
|
)
|
||||||
return
|
return
|
||||||
startlist = [[vals[jj] for jj in range(len(vals))] for ii in range(npts)]
|
startlist = [[vals[jj] for jj in range(len(vals))] for ii in range(npts)]
|
||||||
elif max(idx) > 0:
|
elif max(idx) > 0:
|
||||||
print('Problem with sweep: ' + key + ' is scalar, while an index of ' + str(max(idx)) + ' was requested!')
|
print(
|
||||||
|
"Problem with sweep: "
|
||||||
|
+ key
|
||||||
|
+ " is scalar, while an index of "
|
||||||
|
+ str(max(idx))
|
||||||
|
+ " was requested!"
|
||||||
|
)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
startlist = [[vals] for ii in range(npts)]
|
startlist = [[vals] for ii in range(npts)]
|
||||||
|
|
||||||
# check if a parvar already exists for this key
|
# check if a parvar already exists for this key
|
||||||
if len(self.parvar_cpl) == 0:
|
if len(self.parvar_cpl) == 0:
|
||||||
self.parvar_cpl['sweeplist'] = startlist
|
self.parvar_cpl["sweeplist"] = startlist
|
||||||
elif not((key == self.parvar_cpl['key']) & (npts == self.parvar_cpl['dim'])):
|
elif not ((key == self.parvar_cpl["key"]) & (npts == self.parvar_cpl["dim"])):
|
||||||
self.parvar_cpl['sweeplist'] = startlist
|
self.parvar_cpl["sweeplist"] = startlist
|
||||||
|
|
||||||
self.parvar_cpl['key'] = key
|
self.parvar_cpl["key"] = key
|
||||||
self.parvar_cpl['dim'] = npts
|
self.parvar_cpl["dim"] = npts
|
||||||
|
|
||||||
incr = (end - strt)/(npts-1)
|
incr = (end - strt) / (npts - 1)
|
||||||
|
|
||||||
for ii_swp in range(npts):
|
for ii_swp in range(npts):
|
||||||
for swp_idx in idx:
|
for swp_idx in idx:
|
||||||
self.parvar_cpl['sweeplist'][ii_swp][swp_idx] = strt + ii_swp*incr
|
self.parvar_cpl["sweeplist"][ii_swp][swp_idx] = strt + ii_swp * incr
|
||||||
|
|
||||||
|
def run(self, oup=True):
|
||||||
|
|
||||||
def run(self, oup = True):
|
|
||||||
# check if there is a parvar or only a single
|
# check if there is a parvar or only a single
|
||||||
if len(self.parvar) == 0:
|
if len(self.parvar) == 0:
|
||||||
self.__run_single(oup)
|
self.__run_single(oup)
|
||||||
else:
|
else:
|
||||||
# store the value currently in the swept parameter
|
# store the value currently in the swept parameter
|
||||||
stdval = getattr(self, self.parvar['key'])
|
stdval = getattr(self, self.parvar["key"])
|
||||||
|
|
||||||
if len(self.parvar_cpl) != 0:
|
if len(self.parvar_cpl) != 0:
|
||||||
stdval2 = getattr(self, self.parvar_cpl['key'])
|
stdval2 = getattr(self, self.parvar_cpl["key"])
|
||||||
|
|
||||||
# handle the timestamp
|
# handle the timestamp
|
||||||
stddatestr = getattr(self,'fst')
|
stddatestr = getattr(self, "fst")
|
||||||
if (stddatestr == []):
|
if stddatestr == []:
|
||||||
setattr(self, 'fst', datetime.datetime.now().strftime("%Y%m%d_%H%M%S"))
|
setattr(self, "fst", datetime.datetime.now().strftime("%Y%m%d_%H%M%S"))
|
||||||
|
|
||||||
# give it a useful name
|
# give it a useful name
|
||||||
stdfilepat = getattr(self,'fpa')
|
stdfilepat = getattr(self, "fpa")
|
||||||
if (stdfilepat == []):
|
if stdfilepat == []:
|
||||||
setattr(self, 'fpa', self.parvar['key'] + '_swp')
|
setattr(self, "fpa", self.parvar["key"] + "_swp")
|
||||||
|
|
||||||
# actual iteration over the sweeplist
|
# actual iteration over the sweeplist
|
||||||
for ii in range(self.parvar['dim']):
|
for ii in range(self.parvar["dim"]):
|
||||||
setattr(self, self.parvar['key'], self.parvar['sweeplist'][ii])
|
setattr(self, self.parvar["key"], self.parvar["sweeplist"][ii])
|
||||||
if len(self.parvar_cpl) != 0: # as well as the coupled variable
|
if len(self.parvar_cpl) != 0: # as well as the coupled variable
|
||||||
setattr(self, self.parvar_cpl['key'], self.parvar_cpl['sweeplist'][ii])
|
setattr(
|
||||||
|
self, self.parvar_cpl["key"], self.parvar_cpl["sweeplist"][ii]
|
||||||
|
)
|
||||||
|
|
||||||
self.__run_single(oup)
|
self.__run_single(oup)
|
||||||
|
|
||||||
# save parvar info as attribute, which means that we need to detect the file
|
# save parvar info as attribute, which means that we need to detect the file
|
||||||
if getattr(self,'nos') != 0: # this one is suspicious...
|
if getattr(self, "nos") != 0: # this one is suspicious...
|
||||||
if self.HDFfile == []:
|
if self.HDFfile == []:
|
||||||
self.HDFfile = self.__guess_savepath()
|
self.HDFfile = self.__guess_savepath()
|
||||||
try:
|
try:
|
||||||
# this is probably erroneous and was never recognized...! self.parvar is not a key/value pair
|
# this is probably erroneous and was never recognized...! self.parvar is not a key/value pair
|
||||||
f = h5py.File(self.HDFfile, 'r+')
|
f = h5py.File(self.HDFfile, "r+")
|
||||||
for key in self.parvar:
|
for key in self.parvar:
|
||||||
f.attrs.create(key, self.parvar[key])
|
f.attrs.create(key, self.parvar[key])
|
||||||
f.close()
|
f.close()
|
||||||
except:
|
except:
|
||||||
print('Problem opening file ' + self.HDFfile)
|
print("Problem opening file " + self.HDFfile)
|
||||||
|
|
||||||
setattr(self, self.parvar['key'], stdval) # set back to non-swept value
|
setattr(self, self.parvar["key"], stdval) # set back to non-swept value
|
||||||
setattr(self, 'fst', stddatestr) # set back to non-swept value
|
setattr(self, "fst", stddatestr) # set back to non-swept value
|
||||||
setattr(self, 'fpa', stdfilepat) # set back to non-swept value
|
setattr(self, "fpa", stdfilepat) # set back to non-swept value
|
||||||
if len(self.parvar_cpl) != 0:
|
if len(self.parvar_cpl) != 0:
|
||||||
setattr(self, self.parvar_cpl['key'], stdval2) # set back to non-swept value
|
setattr(
|
||||||
|
self, self.parvar_cpl["key"], stdval2
|
||||||
|
) # set back to non-swept value
|
||||||
|
|
||||||
|
def readHDF(self, filename=""):
|
||||||
def readHDF(self, filename = ''):
|
if filename != "":
|
||||||
if filename != '':
|
|
||||||
self.HDFfile = filename
|
self.HDFfile = filename
|
||||||
|
|
||||||
self.HDF.load(self.HDFfile)
|
self.HDF.load(self.HDFfile)
|
||||||
|
|
||||||
|
|
||||||
# helper functoin to guess the savepath from the file. This should not be called, since it should be obtained from the output of the program call
|
# helper functoin to guess the savepath from the file. This should not be called, since it should be obtained from the output of the program call
|
||||||
def __guess_savepath(self):
|
def __guess_savepath(self):
|
||||||
savepath = getattr(self,'spt')
|
savepath = getattr(self, "spt")
|
||||||
if savepath == []: savepath = './asdf/' # not recommended here: knowledge about the standard directory in the cpp file.... could be parsed, but user will usually provide a folder to limr.spt
|
if savepath == []:
|
||||||
if savepath[-1] != '/': savepath += '/' # and that little fix since users seldomly put the '/' for the directory...
|
savepath = "./asdf/" # not recommended here: knowledge about the standard directory in the cpp file.... could be parsed, but user will usually provide a folder to limr.spt
|
||||||
savepath = savepath + getattr(self,'fst') + '_' + getattr(self,'fpa') + '.h5'
|
if savepath[-1] != "/":
|
||||||
|
savepath += "/" # and that little fix since users seldomly put the '/' for the directory...
|
||||||
|
savepath = savepath + getattr(self, "fst") + "_" + getattr(self, "fpa") + ".h5"
|
||||||
return savepath
|
return savepath
|
||||||
|
|
||||||
# run for one single constellation
|
# run for one single constellation
|
||||||
def __run_single(self, oup = True):
|
def __run_single(self, oup=True):
|
||||||
terminated = False
|
terminated = False
|
||||||
|
|
||||||
while (terminated == False):
|
while terminated == False:
|
||||||
|
|
||||||
str2call= self.Cprog
|
str2call = self.Cprog
|
||||||
|
|
||||||
for key in self.parsinp:
|
for key in self.parsinp:
|
||||||
vals = getattr(self,key)
|
vals = getattr(self, key)
|
||||||
if (vals == []): continue # ignore arguments that are not set
|
if vals == []:
|
||||||
str2call += ' -' + key # set the key and then the value/s
|
continue # ignore arguments that are not set
|
||||||
|
str2call += " -" + key # set the key and then the value/s
|
||||||
if isinstance(vals, (list, np.ndarray)):
|
if isinstance(vals, (list, np.ndarray)):
|
||||||
for val in vals:
|
for val in vals:
|
||||||
str2call += ' ' + str(val)
|
str2call += " " + str(val)
|
||||||
else:
|
else:
|
||||||
str2call += ' ' + str(vals)
|
str2call += " " + str(vals)
|
||||||
|
|
||||||
|
if oup:
|
||||||
|
print(str2call)
|
||||||
|
p = subprocess.Popen(
|
||||||
|
str2call.split(),
|
||||||
|
shell=False,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
)
|
||||||
|
|
||||||
if oup: print(str2call)
|
if getattr(self, "nos") != 0:
|
||||||
p = subprocess.Popen(str2call.split(), shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT);
|
|
||||||
|
|
||||||
if getattr(self,'nos') != 0:
|
|
||||||
terminated = True
|
terminated = True
|
||||||
|
|
||||||
for line_b in p.stdout.readlines():
|
for line_b in p.stdout.readlines():
|
||||||
line = line_b.decode('utf-8').rstrip()
|
line = line_b.decode("utf-8").rstrip()
|
||||||
if oup: print(line),
|
if oup:
|
||||||
if '.h5' in line:
|
print(line),
|
||||||
|
if ".h5" in line:
|
||||||
self.HDFfile = line
|
self.HDFfile = line
|
||||||
terminated = True
|
terminated = True
|
||||||
if 'Unable to open device' in line:
|
if "Unable to open device" in line:
|
||||||
terminated = True
|
terminated = True
|
||||||
if 'Muted output, exiting immediate' in line:
|
if "Muted output, exiting immediate" in line:
|
||||||
terminated = True
|
terminated = True
|
||||||
if self.Cprog + ': not found' in line:
|
if self.Cprog + ": not found" in line:
|
||||||
terminated = True
|
terminated = True
|
||||||
if 'Devices found: 0' in line:
|
if "Devices found: 0" in line:
|
||||||
terminated = True
|
terminated = True
|
||||||
if 'Segmentation' in line:
|
if "Segmentation" in line:
|
||||||
self.segcount += 1
|
self.segcount += 1
|
||||||
terminated = False
|
terminated = False
|
||||||
self.retval = p.wait()
|
self.retval = p.wait()
|
||||||
|
|
||||||
if terminated == False:
|
if terminated == False:
|
||||||
print('RE-RUNNING DUE TO PROBLEM WITH SAVING!!!')
|
print("RE-RUNNING DUE TO PROBLEM WITH SAVING!!!")
|
||||||
|
|
||||||
|
|
||||||
# class for accessing data of stored HDF5 file
|
# class for accessing data of stored HDF5 file
|
||||||
class HDF():
|
class HDF:
|
||||||
|
|
||||||
def __init__(self, filename = ''):
|
def __init__(self, filename=""):
|
||||||
|
|
||||||
# check first for the filename provided
|
# check first for the filename provided
|
||||||
if filename != '':
|
if filename != "":
|
||||||
self.HDFsrc = filename
|
self.HDFsrc = filename
|
||||||
else:
|
else:
|
||||||
self.HDFsrc = ''
|
self.HDFsrc = ""
|
||||||
|
|
||||||
# get data
|
# get data
|
||||||
self.__get_data()
|
self.__get_data()
|
||||||
|
|
||||||
# just an alias for __init__ that does load a specific file
|
# just an alias for __init__ that does load a specific file
|
||||||
def load(self, filename = ''):
|
def load(self, filename=""):
|
||||||
self.__init__(filename)
|
self.__init__(filename)
|
||||||
|
|
||||||
# gets the data of the file
|
# gets the data of the file
|
||||||
def __get_data(self):
|
def __get_data(self):
|
||||||
|
|
||||||
if (self.HDFsrc == '') | (self.HDFsrc == []):
|
if (self.HDFsrc == "") | (self.HDFsrc == []):
|
||||||
# initialize all as empty
|
# initialize all as empty
|
||||||
self.tdy = []
|
self.tdy = []
|
||||||
self.tdx = []
|
self.tdx = []
|
||||||
|
@ -327,8 +357,7 @@ class HDF():
|
||||||
self.parvar = {}
|
self.parvar = {}
|
||||||
|
|
||||||
else:
|
else:
|
||||||
f = h5py.File(self.HDFsrc, 'r')
|
f = h5py.File(self.HDFsrc, "r")
|
||||||
|
|
||||||
|
|
||||||
HDFkeys = list(f.keys())
|
HDFkeys = list(f.keys())
|
||||||
|
|
||||||
|
@ -337,7 +366,10 @@ class HDF():
|
||||||
# initialize data array
|
# initialize data array
|
||||||
dsize = f[HDFkey].shape
|
dsize = f[HDFkey].shape
|
||||||
inddim = dsize[0]
|
inddim = dsize[0]
|
||||||
self.tdy = np.zeros((int(dsize[1]/2), int(dsize[0] * len(HDFkeys))),dtype=np.complex_)
|
self.tdy = np.zeros(
|
||||||
|
(int(dsize[1] / 2), int(dsize[0] * len(HDFkeys))),
|
||||||
|
dtype=np.complex_,
|
||||||
|
)
|
||||||
|
|
||||||
# initialize the output objects
|
# initialize the output objects
|
||||||
self.attrs = [dynclass() for jj in range(len(HDFkeys))]
|
self.attrs = [dynclass() for jj in range(len(HDFkeys))]
|
||||||
|
@ -348,57 +380,61 @@ class HDF():
|
||||||
for item in f[HDFkey].attrs.items():
|
for item in f[HDFkey].attrs.items():
|
||||||
itemname = item[0][5:]
|
itemname = item[0][5:]
|
||||||
itemarg = item[0][1:4]
|
itemarg = item[0][1:4]
|
||||||
if not ('///' in itemarg):
|
if not ("///" in itemarg):
|
||||||
self.parsoutp[itemarg] = [ item[1], itemname]
|
self.parsoutp[itemarg] = [item[1], itemname]
|
||||||
else:
|
else:
|
||||||
self.parsoutp['//'+str(ii_oupargs)] = [ item[1], itemname]
|
self.parsoutp["//" + str(ii_oupargs)] = [item[1], itemname]
|
||||||
ii_oupargs+=1
|
ii_oupargs += 1
|
||||||
|
|
||||||
# look for eventual parvar lists
|
# look for eventual parvar lists
|
||||||
self.parvar = {}
|
self.parvar = {}
|
||||||
for item in f.attrs.items():
|
for item in f.attrs.items():
|
||||||
self.parvar[item[0]] = item[1]
|
self.parvar[item[0]] = item[1]
|
||||||
|
|
||||||
|
|
||||||
# Get the data
|
# Get the data
|
||||||
data_raw = np.array(f[HDFkey])
|
data_raw = np.array(f[HDFkey])
|
||||||
try:
|
try:
|
||||||
self.tdy[:,ii*inddim:(ii+1)*inddim] = np.transpose(np.float_(data_raw[:,::2])) + 1j*np.transpose(np.float_(data_raw[:,1::2]))
|
self.tdy[:, ii * inddim : (ii + 1) * inddim] = np.transpose(
|
||||||
|
np.float_(data_raw[:, ::2])
|
||||||
|
) + 1j * np.transpose(np.float_(data_raw[:, 1::2]))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# Get the arguments
|
# Get the arguments
|
||||||
ii_oupargs = 0
|
ii_oupargs = 0
|
||||||
for item in f[HDFkey].attrs.items():
|
for item in f[HDFkey].attrs.items():
|
||||||
itemname = item[0][5:]
|
itemname = item[0][5:]
|
||||||
itemarg = item[0][1:4]
|
itemarg = item[0][1:4]
|
||||||
if not ('///' in itemarg):
|
if not ("///" in itemarg):
|
||||||
setattr(self.attrs[ii], itemarg, item[1])
|
setattr(self.attrs[ii], itemarg, item[1])
|
||||||
else:
|
else:
|
||||||
setattr(self.attrs[ii], '//'+str(ii_oupargs), item[1])
|
setattr(self.attrs[ii], "//" + str(ii_oupargs), item[1])
|
||||||
ii_oupargs+=1
|
ii_oupargs += 1
|
||||||
|
|
||||||
f.close()
|
f.close()
|
||||||
srate_MHz = getattr(self.attrs[0], 'sra')*1e-6
|
srate_MHz = getattr(self.attrs[0], "sra") * 1e-6
|
||||||
self.tdx = 1/srate_MHz*np.arange(self.tdy.shape[0])
|
self.tdx = 1 / srate_MHz * np.arange(self.tdy.shape[0])
|
||||||
|
|
||||||
# get an argument by matching the text description
|
# get an argument by matching the text description
|
||||||
def attr_by_txt(self, pattern):
|
def attr_by_txt(self, pattern):
|
||||||
for key in sorted(self.parsoutp):
|
for key in sorted(self.parsoutp):
|
||||||
if pattern in self.parsoutp[key][1]: # pattern match
|
if pattern in self.parsoutp[key][1]: # pattern match
|
||||||
attr = getattr(self.attrs[0], key)
|
attr = getattr(self.attrs[0], key)
|
||||||
try:
|
try:
|
||||||
ouparr = np.zeros( ( len(attr), len(self.attrs)), attr.dtype)
|
ouparr = np.zeros((len(attr), len(self.attrs)), attr.dtype)
|
||||||
except:
|
except:
|
||||||
ouparr = np.zeros( ( 1, len(self.attrs)), attr.dtype)
|
ouparr = np.zeros((1, len(self.attrs)), attr.dtype)
|
||||||
|
|
||||||
for ii in np.arange(len(self.attrs)):
|
for ii in np.arange(len(self.attrs)):
|
||||||
ouparr[:,ii] = getattr(self.attrs[ii], key)
|
ouparr[:, ii] = getattr(self.attrs[ii], key)
|
||||||
return np.transpose(ouparr)
|
return np.transpose(ouparr)
|
||||||
|
|
||||||
print('Problem obtaining the attribute from the description using the pattern ' + pattern + '!')
|
print(
|
||||||
print('Valid descriptions are: ')
|
"Problem obtaining the attribute from the description using the pattern "
|
||||||
|
+ pattern
|
||||||
|
+ "!"
|
||||||
|
)
|
||||||
|
print("Valid descriptions are: ")
|
||||||
self.print_params()
|
self.print_params()
|
||||||
|
|
||||||
# get an argument by key
|
# get an argument by key
|
||||||
|
@ -406,45 +442,47 @@ class HDF():
|
||||||
if key in dir(self.attrs[0]):
|
if key in dir(self.attrs[0]):
|
||||||
attr = getattr(self.attrs[0], key)
|
attr = getattr(self.attrs[0], key)
|
||||||
try:
|
try:
|
||||||
ouparr = np.zeros( ( len(attr), len(self.attrs)), attr.dtype)
|
ouparr = np.zeros((len(attr), len(self.attrs)), attr.dtype)
|
||||||
except:
|
except:
|
||||||
ouparr = np.zeros( ( 1, len(self.attrs)), attr.dtype)
|
ouparr = np.zeros((1, len(self.attrs)), attr.dtype)
|
||||||
for ii in np.arange(len(self.attrs)):
|
for ii in np.arange(len(self.attrs)):
|
||||||
ouparr[:,ii] = getattr(self.attrs[ii], key)
|
ouparr[:, ii] = getattr(self.attrs[ii], key)
|
||||||
return np.transpose(ouparr)
|
return np.transpose(ouparr)
|
||||||
|
|
||||||
print('Problem obtaining the attribute from key ' + key + '!')
|
print("Problem obtaining the attribute from key " + key + "!")
|
||||||
print('Valid keys are: ')
|
print("Valid keys are: ")
|
||||||
self.print_params()
|
self.print_params()
|
||||||
|
|
||||||
|
|
||||||
# print the arguments
|
# print the arguments
|
||||||
def print_params(self, ouponly = False):
|
def print_params(self, ouponly=False):
|
||||||
for key in sorted(self.parsoutp):
|
for key in sorted(self.parsoutp):
|
||||||
val = getattr(self.attrs[0], key)
|
val = getattr(self.attrs[0], key)
|
||||||
if not('//' in key): # input argument?
|
if not ("//" in key): # input argument?
|
||||||
if ouponly: continue;
|
if ouponly:
|
||||||
|
continue
|
||||||
|
|
||||||
print('{:<5}: {:>50} {:<25}'.format(key, val, self.parsoutp[key][1]))
|
print("{:<5}: {:>50} {:<25}".format(key, val, self.parsoutp[key][1]))
|
||||||
|
|
||||||
def plot_dta(self, fignum = 1, stack = False, dtamax = 0.0):
|
def plot_dta(self, fignum=1, stack=False, dtamax=0.0):
|
||||||
if (fignum == 1) & stack: fignum = 2;
|
if (fignum == 1) & stack:
|
||||||
|
fignum = 2
|
||||||
|
|
||||||
if self.tdy != []:
|
if self.tdy != []:
|
||||||
|
|
||||||
if dtamax == 0:
|
if dtamax == 0:
|
||||||
dtamax = np.max(np.max(abs(self.tdy),axis=0))
|
dtamax = np.max(np.max(abs(self.tdy), axis=0))
|
||||||
offset = 1.5*dtamax
|
offset = 1.5 * dtamax
|
||||||
|
|
||||||
plt.figure(fignum)
|
plt.figure(fignum)
|
||||||
plt.clf()
|
plt.clf()
|
||||||
if stack:
|
if stack:
|
||||||
for ii in np.arange(self.tdy.shape[1]):
|
for ii in np.arange(self.tdy.shape[1]):
|
||||||
plt.plot(self.tdx, self.tdy[:,ii].real + ii* offset)
|
plt.plot(self.tdx, self.tdy[:, ii].real + ii * offset)
|
||||||
else:
|
else:
|
||||||
plt.plot(self.tdx, self.tdy.real)
|
plt.plot(self.tdx, self.tdy.real)
|
||||||
plt.xlabel('$t$ [$\mu$s]')
|
plt.xlabel("$t$ [$\mu$s]")
|
||||||
plt.ylabel('$y$ [Counts]')
|
plt.ylabel("$y$ [Counts]")
|
||||||
|
|
||||||
|
|
||||||
# empty class to store dynamic attributes, basically for the attributes in HDF keys
|
# empty class to store dynamic attributes, basically for the attributes in HDF keys
|
||||||
class dynclass:
|
class dynclass:
|
||||||
|
@ -457,19 +495,20 @@ import serial
|
||||||
import time
|
import time
|
||||||
from os import listdir
|
from os import listdir
|
||||||
|
|
||||||
class PSU():
|
|
||||||
|
class PSU:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.GperV = 14.309
|
self.GperV = 14.309
|
||||||
self.sleeptime = 0.4
|
self.sleeptime = 0.4
|
||||||
|
|
||||||
devdir = '/dev/'
|
devdir = "/dev/"
|
||||||
ttydevs = [f for f in listdir(devdir) if 'ttyUSB' in f]
|
ttydevs = [f for f in listdir(devdir) if "ttyUSB" in f]
|
||||||
# ttydev = devdir + [f for f in ttydevs if int(f[-1]) > 4][0]
|
# ttydev = devdir + [f for f in ttydevs if int(f[-1]) > 4][0]
|
||||||
ttydev = devdir + [f for f in ttydevs][0]
|
ttydev = devdir + [f for f in ttydevs][0]
|
||||||
|
|
||||||
self.psu=serial.Serial(ttydev, stopbits=2, dsrdtr=True)
|
self.psu = serial.Serial(ttydev, stopbits=2, dsrdtr=True)
|
||||||
|
|
||||||
# read at the beginning to remove eventual junk
|
# read at the beginning to remove eventual junk
|
||||||
response = self.psu.read_all()
|
response = self.psu.read_all()
|
||||||
|
@ -477,10 +516,10 @@ class PSU():
|
||||||
self.psu.write("*IDN?\r\n")
|
self.psu.write("*IDN?\r\n")
|
||||||
time.sleep(self.sleeptime)
|
time.sleep(self.sleeptime)
|
||||||
response = self.psu.read_all()
|
response = self.psu.read_all()
|
||||||
if response == 'HEWLETT-PACKARD,E3631A,0,2.1-5.0-1.0\r\n':
|
if response == "HEWLETT-PACKARD,E3631A,0,2.1-5.0-1.0\r\n":
|
||||||
print('Success in opening the HP PSU!')
|
print("Success in opening the HP PSU!")
|
||||||
else:
|
else:
|
||||||
print('Fail!!!')
|
print("Fail!!!")
|
||||||
|
|
||||||
self.psu.write("INST:SEL P6V\r\n")
|
self.psu.write("INST:SEL P6V\r\n")
|
||||||
time.sleep(self.sleeptime)
|
time.sleep(self.sleeptime)
|
||||||
|
@ -489,7 +528,6 @@ class PSU():
|
||||||
|
|
||||||
self.psu.close()
|
self.psu.close()
|
||||||
|
|
||||||
|
|
||||||
def getVoltage(self):
|
def getVoltage(self):
|
||||||
|
|
||||||
if not self.psu.isOpen():
|
if not self.psu.isOpen():
|
||||||
|
@ -503,17 +541,16 @@ class PSU():
|
||||||
self.psu.close()
|
self.psu.close()
|
||||||
return actval
|
return actval
|
||||||
|
|
||||||
|
def setVoltage(self, setval, dV=0.02, ramptime=0.1):
|
||||||
def setVoltage(self, setval, dV = 0.02, ramptime = 0.1):
|
|
||||||
|
|
||||||
actval = self.getVoltage()
|
actval = self.getVoltage()
|
||||||
|
|
||||||
diff = setval - actval
|
diff = setval - actval
|
||||||
dVsigned = dV * (-1 if diff < 0 else 1)
|
dVsigned = dV * (-1 if diff < 0 else 1)
|
||||||
|
|
||||||
if not self.psu.isOpen():
|
if not self.psu.isOpen():
|
||||||
self.psu.open()
|
self.psu.open()
|
||||||
while (abs(diff) > dV):
|
while abs(diff) > dV:
|
||||||
actval += dVsigned
|
actval += dVsigned
|
||||||
diff -= dVsigned
|
diff -= dVsigned
|
||||||
self.psu.write("VOLT " + str(actval) + "\r\n")
|
self.psu.write("VOLT " + str(actval) + "\r\n")
|
||||||
|
|
Loading…
Reference in a new issue