mirror of
https://github.com/nqrduck/LimeDriver.git
synced 2024-11-25 03:22:25 +00:00
Merge pull request #3 from nqrduck/dump_arguments
Dump configuration from binary - tested with LimeSDR USB
This commit is contained in:
commit
28af177728
2 changed files with 413 additions and 286 deletions
|
@ -9,13 +9,15 @@ LimeSuite
|
|||
HDF5 library
|
||||
|
||||
compilation:
|
||||
$(h5c++ -show) limedriver.cpp -std=c++11 $(pkg-config --cflags --libs LimeSuite) -o limedriver
|
||||
$(h5c++ -show) limedriver.cpp -std=c++11 $(pkg-config --cflags --libs LimeSuite)
|
||||
-o limedriver
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "H5Cpp.h"
|
||||
#include "lime/LimeSuite.h"
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
@ -25,6 +27,7 @@ $(h5c++ -show) limedriver.cpp -std=c++11 $(pkg-config --cflags --libs LimeSuite)
|
|||
#include <string.h>
|
||||
|
||||
#include <errno.h> // errno, ENOENT, EEXIST
|
||||
#include <string>
|
||||
#include <sys/stat.h> // stat
|
||||
#include <sys/types.h>
|
||||
#if defined(_WIN32)
|
||||
|
@ -252,6 +255,75 @@ int GetGainRXTX(int *RXgain, int *TXgain) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void dumpConfig(Config2HDFattr_t *config, size_t size) {
|
||||
/* Dump the configuration to stdout in JSON format
|
||||
|
||||
@param config: Array of Config2HDFattr_t
|
||||
@param size: Size of the array
|
||||
|
||||
*/
|
||||
|
||||
int ii_oupargs = 0; // TODO: Better name
|
||||
|
||||
std::cout << "{" << std::endl;
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
|
||||
// Handle the "///" arguments
|
||||
|
||||
string arg = config[i].arg;
|
||||
|
||||
if (strcmp(config[i].arg.c_str(), "///") == 0) {
|
||||
arg = "//" + std::to_string(ii_oupargs);
|
||||
ii_oupargs++;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
string arg;
|
||||
H5std_string Name;
|
||||
H5::DataType dType;
|
||||
void *Value;
|
||||
hsize_t dim;
|
||||
|
||||
*/
|
||||
|
||||
// Turn arguments to JSON objects
|
||||
|
||||
std::cout << "\"" << arg << "\": {";
|
||||
|
||||
std::cout << "\"name\": \"" << config[i].Name << "\", ";
|
||||
std::cout << "\"type\": \"" << typeid(config[i]).name() << "\", ";
|
||||
std::cout << "\"value\": \"";
|
||||
|
||||
// Need to cast void* data pointer to the correct type
|
||||
// TODO: Do we lose precision here?
|
||||
if (config[i].dType == H5::PredType::NATIVE_INT) {
|
||||
std::cout << *(static_cast<int *>(config[i].Value));
|
||||
} else if (config[i].dType == H5::PredType::IEEE_F32LE) {
|
||||
std::cout << *(static_cast<float *>(config[i].Value));
|
||||
} else if (config[i].dType == H5::PredType::IEEE_F64LE) {
|
||||
std::cout << *(static_cast<double *>(config[i].Value));
|
||||
} else {
|
||||
std::cout << static_cast<char *>(config[i].Value);
|
||||
}
|
||||
|
||||
std::cout << "\", ";
|
||||
|
||||
std::cout << "\"dim\": " << config[i].dim;
|
||||
|
||||
std::cout << "}";
|
||||
|
||||
if (i < size - 1) {
|
||||
std::cout << ",";
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "}" << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const double pi = acos(-1);
|
||||
|
||||
|
@ -467,6 +539,21 @@ int main(int argc, char **argv) {
|
|||
(void *)LimeCfg.stamp_end.c_str(), 1}};
|
||||
int no_of_attr = sizeof(HDFattr) / sizeof(Config2HDFattr_t);
|
||||
|
||||
bool dumpFlag = false;
|
||||
|
||||
// Checking for dump flag
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (strcmp(argv[i], "--dump") == 0) {
|
||||
dumpFlag = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If dump flag is set, dump the config and exit
|
||||
if (dumpFlag) {
|
||||
dumpConfig(HDFattr, no_of_attr);
|
||||
std::exit(0);
|
||||
}
|
||||
|
||||
// iterate through arguments to parse eventual user input
|
||||
// (exposing the actual content of the struct to python would be nicer...)
|
||||
bool parse_prob = false;
|
||||
|
@ -1112,8 +1199,8 @@ int main(int argc, char **argv) {
|
|||
<< " excitation buffers is required to fit the experiment" << endl;
|
||||
|
||||
// TX buffers
|
||||
// int16_t tx_buffer[num_phavar][exc_buffers][2*buffersize]; // buffer to
|
||||
// hold complex values (2* samples), including phase cycles
|
||||
// int16_t tx_buffer[num_phavar][exc_buffers][2*buffersize]; //
|
||||
// buffer to hold complex values (2* samples), including phase cycles
|
||||
// TODO: put in the same way as the acq buffer, i.e. as an array of pointers.
|
||||
// Otherwise, there is a limitation in space that can be used
|
||||
int16_t *tx_buffer[num_phavar][exc_buffers];
|
||||
|
|
604
src/limr.py
604
src/limr.py
|
@ -15,437 +15,478 @@ 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
|
||||
|
||||
"""
|
||||
import subprocess # to call the program
|
||||
import datetime # to generate timestamps for parsweeps
|
||||
import h5py # to have organized data storage.....
|
||||
import numpy as np # ...
|
||||
import subprocess # to call the program
|
||||
import datetime # to generate timestamps for parsweeps
|
||||
import h5py # to have organized data storage.....
|
||||
import numpy as np # ...
|
||||
import matplotlib.pyplot as plt
|
||||
import json
|
||||
|
||||
|
||||
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'
|
||||
|
||||
class limr:
|
||||
|
||||
def __init__(self, filename="./limedriver"):
|
||||
# the program to call
|
||||
self.Cprog = self.Csrc[:-4]
|
||||
|
||||
fp = open(self.Csrc, 'r')
|
||||
self.Cprog = filename
|
||||
|
||||
# fetch the default parameters from the limedriver binary
|
||||
str2call = self.Cprog + " --dump"
|
||||
|
||||
p = subprocess.Popen(
|
||||
str2call.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
||||
)
|
||||
|
||||
# read the output
|
||||
in_arg = json.loads(p.stdout.read().decode("utf-8"))
|
||||
|
||||
# initialize the parameters
|
||||
for key in in_arg.keys():
|
||||
in_arg[key]["argument"] = []
|
||||
setattr(self, key, [])
|
||||
|
||||
in_arg = {}
|
||||
startpattern = 'struct Config2HDFattr_t HDFattr[]'
|
||||
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
|
||||
|
||||
for key in in_arg:
|
||||
setattr(self, key, in_arg[key][0])
|
||||
|
||||
# initialize other variables
|
||||
self.parvar = {}
|
||||
self.parvar_cpl = {}
|
||||
|
||||
# initialize other variables
|
||||
self.parvar = {}
|
||||
self.parvar_cpl = {}
|
||||
self.HDFfile = []
|
||||
|
||||
|
||||
self.HDF = HDF()
|
||||
|
||||
|
||||
self.segcount = 0
|
||||
|
||||
|
||||
# print the arguments that have been set
|
||||
def print_params(self, allel = False):
|
||||
for key in sorted(self.parsinp):
|
||||
val = getattr(self,key)
|
||||
def print_params(self, allel=False):
|
||||
for key in sorted(self.parsinp.keys()):
|
||||
val = getattr(self, key)
|
||||
if (val != []) | (allel):
|
||||
print('{:<5}: {:>50} {:<25}'.format(key, val, self.parsinp[key][1]))
|
||||
|
||||
|
||||
|
||||
# add parameter variation:
|
||||
print("{:<5}: {:>50} {:<25}".format(key, val, self.parsinp[key]["name"]))
|
||||
|
||||
# add parameter variation:
|
||||
# key is the argument to vary
|
||||
# idx the indices of values
|
||||
# strt the starting point
|
||||
# end the endpoint
|
||||
# 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
|
||||
try:
|
||||
vals = getattr(self,key)
|
||||
vals = getattr(self, key)
|
||||
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)
|
||||
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
|
||||
if (vals == []):
|
||||
print('Problem with sweep: Initialize first a value to argument ' + key +'. I will try with assuming zero')
|
||||
vals = 0;
|
||||
if vals == []:
|
||||
print(
|
||||
"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 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
|
||||
startlist = [[vals[jj] for jj in range(len(vals))] for ii in range(npts)]
|
||||
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
|
||||
else:
|
||||
startlist = [[vals] for ii in range(npts)]
|
||||
|
||||
# check if a parvar already exists for this key
|
||||
if len(self.parvar) == 0:
|
||||
self.parvar['sweeplist'] = startlist
|
||||
elif not((key == self.parvar['key']) & (npts == self.parvar['dim'])):
|
||||
self.parvar['sweeplist'] = startlist
|
||||
|
||||
self.parvar['key'] = key
|
||||
self.parvar['dim'] = npts
|
||||
|
||||
self.parvar["sweeplist"] = startlist
|
||||
elif not ((key == self.parvar["key"]) & (npts == self.parvar["dim"])):
|
||||
self.parvar["sweeplist"] = startlist
|
||||
|
||||
self.parvar["key"] = key
|
||||
self.parvar["dim"] = npts
|
||||
|
||||
if npts > 1:
|
||||
incr = (end - strt)/(npts-1)
|
||||
incr = (end - strt) / (npts - 1)
|
||||
else:
|
||||
incr = 0;
|
||||
|
||||
|
||||
incr = 0
|
||||
|
||||
for ii_swp in range(npts):
|
||||
for swp_idx in idx:
|
||||
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....)
|
||||
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....)
|
||||
# key is the argument to vary
|
||||
# idx the indices of values
|
||||
# strt the starting point
|
||||
# end the endpoint
|
||||
# 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
|
||||
try:
|
||||
vals = getattr(self,key)
|
||||
vals = getattr(self, key)
|
||||
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)
|
||||
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
|
||||
if (vals == []):
|
||||
print('Problem with sweep: Initialize first a value to argument ' + key +'. I will try with assuming zero')
|
||||
vals = 0;
|
||||
if vals == []:
|
||||
print(
|
||||
"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 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
|
||||
startlist = [[vals[jj] for jj in range(len(vals))] for ii in range(npts)]
|
||||
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
|
||||
else:
|
||||
startlist = [[vals] for ii in range(npts)]
|
||||
|
||||
# check if a parvar already exists for this key
|
||||
if len(self.parvar_cpl) == 0:
|
||||
self.parvar_cpl['sweeplist'] = startlist
|
||||
elif not((key == self.parvar_cpl['key']) & (npts == self.parvar_cpl['dim'])):
|
||||
self.parvar_cpl['sweeplist'] = startlist
|
||||
|
||||
self.parvar_cpl['key'] = key
|
||||
self.parvar_cpl['dim'] = npts
|
||||
|
||||
incr = (end - strt)/(npts-1)
|
||||
|
||||
self.parvar_cpl["sweeplist"] = startlist
|
||||
elif not ((key == self.parvar_cpl["key"]) & (npts == self.parvar_cpl["dim"])):
|
||||
self.parvar_cpl["sweeplist"] = startlist
|
||||
|
||||
self.parvar_cpl["key"] = key
|
||||
self.parvar_cpl["dim"] = npts
|
||||
|
||||
incr = (end - strt) / (npts - 1)
|
||||
|
||||
for ii_swp in range(npts):
|
||||
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
|
||||
if len(self.parvar) == 0:
|
||||
self.__run_single(oup)
|
||||
else:
|
||||
# store the value currently in the swept parameter
|
||||
stdval = getattr(self, self.parvar['key'])
|
||||
|
||||
if len(self.parvar_cpl) != 0:
|
||||
stdval2 = getattr(self, self.parvar_cpl['key'])
|
||||
|
||||
# handle the timestamp
|
||||
stddatestr = getattr(self,'fst')
|
||||
if (stddatestr == []):
|
||||
setattr(self, 'fst', datetime.datetime.now().strftime("%Y%m%d_%H%M%S"))
|
||||
stdval = getattr(self, self.parvar["key"])
|
||||
|
||||
if len(self.parvar_cpl) != 0:
|
||||
stdval2 = getattr(self, self.parvar_cpl["key"])
|
||||
|
||||
# handle the timestamp
|
||||
stddatestr = getattr(self, "fst")
|
||||
if stddatestr == []:
|
||||
setattr(self, "fst", datetime.datetime.now().strftime("%Y%m%d_%H%M%S"))
|
||||
|
||||
# give it a useful name
|
||||
stdfilepat = getattr(self, "fpa")
|
||||
if stdfilepat == []:
|
||||
setattr(self, "fpa", self.parvar["key"] + "_swp")
|
||||
|
||||
# give it a useful name
|
||||
stdfilepat = getattr(self,'fpa')
|
||||
if (stdfilepat == []):
|
||||
setattr(self, 'fpa', self.parvar['key'] + '_swp')
|
||||
|
||||
# actual iteration over the sweeplist
|
||||
for ii in range(self.parvar['dim']):
|
||||
setattr(self, self.parvar['key'], self.parvar['sweeplist'][ii])
|
||||
if len(self.parvar_cpl) != 0: # as well as the coupled variable
|
||||
setattr(self, self.parvar_cpl['key'], self.parvar_cpl['sweeplist'][ii])
|
||||
|
||||
for ii in range(self.parvar["dim"]):
|
||||
setattr(self, self.parvar["key"], self.parvar["sweeplist"][ii])
|
||||
if len(self.parvar_cpl) != 0: # as well as the coupled variable
|
||||
setattr(
|
||||
self, self.parvar_cpl["key"], self.parvar_cpl["sweeplist"][ii]
|
||||
)
|
||||
|
||||
self.__run_single(oup)
|
||||
|
||||
|
||||
# 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 == []:
|
||||
self.HDFfile = self.__guess_savepath()
|
||||
try:
|
||||
# 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:
|
||||
f.attrs.create(key, self.parvar[key])
|
||||
f.close()
|
||||
except:
|
||||
print('Problem opening file ' + self.HDFfile)
|
||||
|
||||
setattr(self, self.parvar['key'], stdval) # 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
|
||||
if len(self.parvar_cpl) != 0:
|
||||
setattr(self, self.parvar_cpl['key'], stdval2) # set back to non-swept value
|
||||
print("Problem opening file " + self.HDFfile)
|
||||
|
||||
|
||||
def readHDF(self, filename = ''):
|
||||
if filename != '':
|
||||
setattr(self, self.parvar["key"], stdval) # 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
|
||||
if len(self.parvar_cpl) != 0:
|
||||
setattr(
|
||||
self, self.parvar_cpl["key"], stdval2
|
||||
) # set back to non-swept value
|
||||
|
||||
def readHDF(self, filename=""):
|
||||
if filename != "":
|
||||
self.HDFfile = filename
|
||||
|
||||
|
||||
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):
|
||||
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[-1] != '/': savepath += '/' # and that little fix since users seldomly put the '/' for the directory...
|
||||
savepath = savepath + getattr(self,'fst') + '_' + getattr(self,'fpa') + '.h5'
|
||||
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[-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
|
||||
|
||||
# run for one single constellation
|
||||
def __run_single(self, oup = True):
|
||||
|
||||
# run for one single constellation
|
||||
def __run_single(self, oup=True):
|
||||
terminated = False
|
||||
|
||||
while (terminated == False):
|
||||
|
||||
str2call= self.Cprog
|
||||
|
||||
for key in self.parsinp:
|
||||
vals = getattr(self,key)
|
||||
if (vals == []): continue # ignore arguments that are not set
|
||||
str2call += ' -' + key # set the key and then the value/s
|
||||
|
||||
while terminated == False:
|
||||
|
||||
str2call = self.Cprog
|
||||
|
||||
for key in self.parsinp.keys():
|
||||
vals = getattr(self, key)
|
||||
if vals == []:
|
||||
continue # ignore arguments that are not set
|
||||
str2call += " -" + key # set the key and then the value/s
|
||||
if isinstance(vals, (list, np.ndarray)):
|
||||
for val in vals:
|
||||
str2call += ' ' + str(val)
|
||||
str2call += " " + str(val)
|
||||
else:
|
||||
str2call += ' ' + str(vals)
|
||||
|
||||
|
||||
if oup: print(str2call)
|
||||
p = subprocess.Popen(str2call.split(), shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT);
|
||||
|
||||
if getattr(self,'nos') != 0:
|
||||
terminated = True
|
||||
|
||||
str2call += " " + str(vals)
|
||||
|
||||
if oup:
|
||||
print(str2call)
|
||||
p = subprocess.Popen(
|
||||
str2call.split(),
|
||||
shell=False,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
|
||||
if getattr(self, "nos") != 0:
|
||||
terminated = True
|
||||
|
||||
for line_b in p.stdout.readlines():
|
||||
line = line_b.decode('utf-8').rstrip()
|
||||
if oup: print(line),
|
||||
if '.h5' in line:
|
||||
line = line_b.decode("utf-8").rstrip()
|
||||
if oup:
|
||||
print(line),
|
||||
if ".h5" in line:
|
||||
self.HDFfile = line
|
||||
terminated = True
|
||||
if 'Unable to open device' in line:
|
||||
if "Unable to open device" in line:
|
||||
terminated = True
|
||||
if 'Muted output, exiting immediate' in line:
|
||||
if "Muted output, exiting immediate" in line:
|
||||
terminated = True
|
||||
if self.Cprog + ': not found' in line:
|
||||
if self.Cprog + ": not found" in line:
|
||||
terminated = True
|
||||
if 'Devices found: 0' in line:
|
||||
if "Devices found: 0" in line:
|
||||
terminated = True
|
||||
if 'Segmentation' in line:
|
||||
if "Segmentation" in line:
|
||||
self.segcount += 1
|
||||
terminated = False
|
||||
self.retval = p.wait()
|
||||
|
||||
|
||||
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 HDF():
|
||||
|
||||
def __init__(self, filename = ''):
|
||||
|
||||
class HDF:
|
||||
|
||||
def __init__(self, filename=""):
|
||||
|
||||
# check first for the filename provided
|
||||
if filename != '':
|
||||
if filename != "":
|
||||
self.HDFsrc = filename
|
||||
else:
|
||||
self.HDFsrc = ''
|
||||
|
||||
self.HDFsrc = ""
|
||||
|
||||
# get data
|
||||
self.__get_data()
|
||||
|
||||
|
||||
# just an alias for __init__ that does load a specific file
|
||||
def load(self, filename = ''):
|
||||
def load(self, filename=""):
|
||||
self.__init__(filename)
|
||||
|
||||
# gets the data of the file
|
||||
|
||||
# gets the data of the file
|
||||
def __get_data(self):
|
||||
|
||||
if (self.HDFsrc == '') | (self.HDFsrc == []):
|
||||
|
||||
if (self.HDFsrc == "") | (self.HDFsrc == []):
|
||||
# initialize all as empty
|
||||
self.tdy = []
|
||||
self.tdx = []
|
||||
self.attrs = []
|
||||
self.parsoutp = {}
|
||||
self.parvar = {}
|
||||
|
||||
|
||||
else:
|
||||
f = h5py.File(self.HDFsrc, 'r')
|
||||
|
||||
|
||||
f = h5py.File(self.HDFsrc, "r")
|
||||
|
||||
HDFkeys = list(f.keys())
|
||||
|
||||
|
||||
for ii, HDFkey in enumerate(HDFkeys):
|
||||
if ii == 0:
|
||||
# initialize data array
|
||||
dsize = f[HDFkey].shape
|
||||
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
|
||||
self.attrs = [dynclass() for jj in range(len(HDFkeys))]
|
||||
|
||||
|
||||
# get the attribute keys
|
||||
self.parsoutp = {}
|
||||
ii_oupargs = 0
|
||||
for item in f[HDFkey].attrs.items():
|
||||
itemname = item[0][5:]
|
||||
itemarg = item[0][1:4]
|
||||
if not ('///' in itemarg):
|
||||
self.parsoutp[itemarg] = [ item[1], itemname]
|
||||
if not ("///" in itemarg):
|
||||
self.parsoutp[itemarg] = [item[1], itemname]
|
||||
else:
|
||||
self.parsoutp['//'+str(ii_oupargs)] = [ item[1], itemname]
|
||||
ii_oupargs+=1
|
||||
|
||||
self.parsoutp["//" + str(ii_oupargs)] = [item[1], itemname]
|
||||
ii_oupargs += 1
|
||||
|
||||
# look for eventual parvar lists
|
||||
self.parvar = {}
|
||||
for item in f.attrs.items():
|
||||
self.parvar[item[0]] = item[1]
|
||||
|
||||
|
||||
|
||||
# Get the data
|
||||
data_raw = np.array(f[HDFkey])
|
||||
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:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
# Get the arguments
|
||||
ii_oupargs = 0
|
||||
ii_oupargs = 0
|
||||
for item in f[HDFkey].attrs.items():
|
||||
itemname = item[0][5:]
|
||||
itemarg = item[0][1:4]
|
||||
if not ('///' in itemarg):
|
||||
if not ("///" in itemarg):
|
||||
setattr(self.attrs[ii], itemarg, item[1])
|
||||
else:
|
||||
setattr(self.attrs[ii], '//'+str(ii_oupargs), item[1])
|
||||
ii_oupargs+=1
|
||||
|
||||
setattr(self.attrs[ii], "//" + str(ii_oupargs), item[1])
|
||||
ii_oupargs += 1
|
||||
|
||||
f.close()
|
||||
srate_MHz = getattr(self.attrs[0], 'sra')*1e-6
|
||||
self.tdx = 1/srate_MHz*np.arange(self.tdy.shape[0])
|
||||
srate_MHz = getattr(self.attrs[0], "sra") * 1e-6
|
||||
self.tdx = 1 / srate_MHz * np.arange(self.tdy.shape[0])
|
||||
|
||||
# get an argument by matching the text description
|
||||
def attr_by_txt(self, pattern):
|
||||
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)
|
||||
try:
|
||||
ouparr = np.zeros( ( len(attr), len(self.attrs)), attr.dtype)
|
||||
ouparr = np.zeros((len(attr), len(self.attrs)), attr.dtype)
|
||||
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)):
|
||||
ouparr[:,ii] = getattr(self.attrs[ii], key)
|
||||
ouparr[:, ii] = getattr(self.attrs[ii], key)
|
||||
return np.transpose(ouparr)
|
||||
|
||||
print('Problem obtaining the attribute from the description using the pattern ' + pattern + '!')
|
||||
print('Valid descriptions are: ')
|
||||
|
||||
print(
|
||||
"Problem obtaining the attribute from the description using the pattern "
|
||||
+ pattern
|
||||
+ "!"
|
||||
)
|
||||
print("Valid descriptions are: ")
|
||||
self.print_params()
|
||||
|
||||
|
||||
# get an argument by key
|
||||
def attr_by_key(self, key):
|
||||
if key in dir(self.attrs[0]):
|
||||
attr = getattr(self.attrs[0], key)
|
||||
try:
|
||||
ouparr = np.zeros( ( len(attr), len(self.attrs)), attr.dtype)
|
||||
ouparr = np.zeros((len(attr), len(self.attrs)), attr.dtype)
|
||||
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)):
|
||||
ouparr[:,ii] = getattr(self.attrs[ii], key)
|
||||
ouparr[:, ii] = getattr(self.attrs[ii], key)
|
||||
return np.transpose(ouparr)
|
||||
|
||||
print('Problem obtaining the attribute from key ' + key + '!')
|
||||
print('Valid keys are: ')
|
||||
|
||||
print("Problem obtaining the attribute from key " + key + "!")
|
||||
print("Valid keys are: ")
|
||||
self.print_params()
|
||||
|
||||
|
||||
# print the arguments
|
||||
def print_params(self, ouponly = False):
|
||||
def print_params(self, ouponly=False):
|
||||
for key in sorted(self.parsoutp):
|
||||
val = getattr(self.attrs[0], key)
|
||||
if not('//' in key): # input argument?
|
||||
if ouponly: continue;
|
||||
|
||||
print('{:<5}: {:>50} {:<25}'.format(key, val, self.parsoutp[key][1]))
|
||||
|
||||
def plot_dta(self, fignum = 1, stack = False, dtamax = 0.0):
|
||||
if (fignum == 1) & stack: fignum = 2;
|
||||
|
||||
if not ("//" in key): # input argument?
|
||||
if ouponly:
|
||||
continue
|
||||
|
||||
print("{:<5}: {:>50} {:<25}".format(key, val, self.parsoutp[key][1]))
|
||||
|
||||
def plot_dta(self, fignum=1, stack=False, dtamax=0.0):
|
||||
if (fignum == 1) & stack:
|
||||
fignum = 2
|
||||
|
||||
if self.tdy != []:
|
||||
|
||||
|
||||
if dtamax == 0:
|
||||
dtamax = np.max(np.max(abs(self.tdy),axis=0))
|
||||
offset = 1.5*dtamax
|
||||
|
||||
dtamax = np.max(np.max(abs(self.tdy), axis=0))
|
||||
offset = 1.5 * dtamax
|
||||
|
||||
plt.figure(fignum)
|
||||
plt.clf()
|
||||
if stack:
|
||||
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:
|
||||
plt.plot(self.tdx, self.tdy.real)
|
||||
plt.xlabel('$t$ [$\mu$s]')
|
||||
plt.ylabel('$y$ [Counts]')
|
||||
|
||||
plt.xlabel("$t$ [$\mu$s]")
|
||||
plt.ylabel("$y$ [Counts]")
|
||||
|
||||
|
||||
# empty class to store dynamic attributes, basically for the attributes in HDF keys
|
||||
class dynclass:
|
||||
pass
|
||||
|
@ -457,19 +498,20 @@ import serial
|
|||
import time
|
||||
from os import listdir
|
||||
|
||||
class PSU():
|
||||
|
||||
|
||||
class PSU:
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.GperV = 14.309
|
||||
self.sleeptime = 0.4
|
||||
|
||||
devdir = '/dev/'
|
||||
ttydevs = [f for f in listdir(devdir) if 'ttyUSB' in f]
|
||||
# ttydev = devdir + [f for f in ttydevs if int(f[-1]) > 4][0]
|
||||
|
||||
devdir = "/dev/"
|
||||
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][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
|
||||
response = self.psu.read_all()
|
||||
|
@ -477,21 +519,20 @@ class PSU():
|
|||
self.psu.write("*IDN?\r\n")
|
||||
time.sleep(self.sleeptime)
|
||||
response = self.psu.read_all()
|
||||
if response == 'HEWLETT-PACKARD,E3631A,0,2.1-5.0-1.0\r\n':
|
||||
print('Success in opening the HP PSU!')
|
||||
if response == "HEWLETT-PACKARD,E3631A,0,2.1-5.0-1.0\r\n":
|
||||
print("Success in opening the HP PSU!")
|
||||
else:
|
||||
print('Fail!!!')
|
||||
|
||||
print("Fail!!!")
|
||||
|
||||
self.psu.write("INST:SEL P6V\r\n")
|
||||
time.sleep(self.sleeptime)
|
||||
self.psu.write("OUTP:STAT ON\r\n")
|
||||
time.sleep(self.sleeptime)
|
||||
|
||||
|
||||
self.psu.close()
|
||||
|
||||
|
||||
def getVoltage(self):
|
||||
|
||||
|
||||
if not self.psu.isOpen():
|
||||
self.psu.open()
|
||||
# read at the beginning to remove eventual junk
|
||||
|
@ -502,32 +543,31 @@ class PSU():
|
|||
actval = float(self.psu.read_all())
|
||||
self.psu.close()
|
||||
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()
|
||||
|
||||
diff = setval - actval
|
||||
|
||||
diff = setval - actval
|
||||
dVsigned = dV * (-1 if diff < 0 else 1)
|
||||
|
||||
|
||||
if not self.psu.isOpen():
|
||||
self.psu.open()
|
||||
while (abs(diff) > dV):
|
||||
while abs(diff) > dV:
|
||||
actval += dVsigned
|
||||
diff -= dVsigned
|
||||
self.psu.write("VOLT " + str(actval) + "\r\n")
|
||||
time.sleep(ramptime)
|
||||
|
||||
|
||||
self.psu.write("VOLT " + str(setval) + "\r\n")
|
||||
time.sleep(ramptime)
|
||||
|
||||
|
||||
self.psu.close()
|
||||
|
||||
|
||||
def getField(self):
|
||||
|
||||
|
||||
return self.getVoltage() * self.GperV
|
||||
|
||||
def setField(self, field):
|
||||
|
||||
|
||||
return self.setVoltage(field / self.GperV)
|
||||
|
|
Loading…
Reference in a new issue