################################################################################
# classes
# scanDim holds all of the data associated with a single execution of a single sscan record.
class scanDim:
def __init__(self):
self.rank = 0 # [1..n] 1 means this is the "innermost" or only scan dimension
self.dim = 0 # dimensionality of data (numerically same as rank)
self.npts = 0 # number of data points planned
self.curr_pt = 0 # number of data points actually acquired
self.plower_scans = 0 # file offsets of next lower rank scans
self.name = "" # name of sscan record that acquired the data
self.time = "" # time at which scan (dimension) started
self.np = 0 # number of positioners
self.p = [] # list of scanPositioner instances
self.nd = 0 # number of detectors
self.d = [] # list of scanDetector instances
self.nt = 0 # number of detector triggers
self.t = [] # list of scanTrigger instances
def __str__(self):
if self.name != '':
s = "%dD data from \"%s\" acquired on %s:\n%d/%d pts; %d positioners, %d detectors" % (
self.dim, self.name, self.time, self.curr_pt, self.npts, self.np, self.nd)
else:
s = "%dD data (not read in)" % (self.dim)
return s
# scanPositioner holds all the information associated with a single positioner, and
# all the data written and acquired by that positioner during an entire (possibly
# multidimensional) scan.
class scanPositioner:
def __init__(self):
self.number = 0 # positioner number in sscan record
self.fieldName = "" # name of sscanRecord PV
self.name = "" # name of EPICS PV this positioner wrote to
self.desc = "" # description of 'name' PV
self.step_mode = "" # 'LINEAR', 'TABLE', or 'FLY'
self.unit = "" # units of 'name' PV
self.readback_name = "" # name of EPICS PV this positioner read from, if any
self.readback_desc = "" # description of 'readback_name' PV
self.readback_unit = "" # units of 'readback_name' PV
self.data = [] # list of values written to 'name' PV. If rank==2, lists of lists, etc.
def __str__(self):
global use_numpy
data = self.data
if use_numpy:
n = data.ndim
if n==1:
dimString = '(' + str(data.shape[0]) + ')'
else:
dimString = str(data.shape)
else:
n = 1
dimString = str(len(data))
while (len(data)>0) and ((type(data[0]) == type([])) or (type(data[0]) == type(()))):
data = data[0]
n = n+1
dimString = dimString+"x"+str(len(data))
dimString = '('+dimString+')'
s = "positioner <scanRecord>.%s\nPV name '%s'\nPV desc. '%s'\nPV units '%s'\nstep mode: %s\nRB name '%s'\nRB desc. '%s'\nRB units '%s'\ndata: %dD array %s\n" % (self.fieldName,
self.name, self.desc, self.unit, self.step_mode, self.name, self.desc, self.unit, n, dimString)
return s
# scanDetector holds all the information associated with a single detector, and
# all the data acquired by that detector during an entire (possibly multidimensional) scan.
class scanDetector:
def __init__(self):
self.number = 0 # detector number in sscan record
self.fieldName = "" # name of sscanRecord PV
self.name = "" # name of EPICS PV this detector read from
self.desc = "" # description of 'name' PV
self.unit = "" # units of 'name' PV
self.data = [] # list of values read from 'name' PV. If rank==2, lists of lists, etc.
def __str__(self):
global use_numpy
data = self.data
if use_numpy:
n = data.ndim
if n==1:
dimString = '(' + str(data.shape[0]) + ')'
else:
dimString = str(data.shape)
else:
n = 1
dimString = str(len(data))
while (len(data)>0) and ((type(data[0]) == type([])) or (type(data[0]) == type(()))):
data = data[0]
n = n+1
dimString = dimString+"x"+str(len(data))
dimString = '('+dimString+')'
s = "detector <scanRecord>.%s\nPV name '%s'\nPV desc. '%s'\nPV units '%s'\ndata: %dD array %s\n" % (self.fieldName,
self.name, self.desc, self.unit, n, dimString)
return s
# scanTrigger holds all the information associated with a single detector trigger.
class scanTrigger:
def __init__(self):
self.number = 0 # detector-trigger number in sscan record
self.name = "" # name of sscanRecord PV
self.command = 0.0 # value written to 'name' PV
def __str__(self):
s = "trigger %d (%s), command=%f\n" % (self.number,
self.name, self.command)
return s