def __init__(self, detsym, detectortype, controlprefix, imageprefix, comment): if DEBUG: print("Defining "+str(detsym)+" with PVs="+str(controlprefix)+ ' and '+str(imageprefix)) if globals().get(detsym) is None: globals()[detsym] = self else: raise spec.specException('Variable '+str(detsym)+' is in use') global detectorTypeList if detectortype not in detectorTypeList: detectorTypeList.append(detectortype) self.detectortype = detectortype #else: # raise spec.specException('Type '+str(detectortype)+'for detector '+str(detsym)+ # ' is not defined,\n allowed choices are: '+str(detectorTypeList)) self.symbol = detsym if controlprefix[-1] == ":": self.controlprefix = controlprefix else: self.controlprefix = controlprefix + ':' if imageprefix[-1] == ":": self.imageprefix = imageprefix else: self.imageprefix = imageprefix + ':' self.comment = comment
def AD_show(detsym=None,allowprint=True): '''Shows all the commands defined for a particular detector, or with any detector. :param object detsym: An area detector variable (or name as a string), as defined in :func:`DefineAreaDetector`. Default is to only list commands that can be used with all detectors. :param bool allowprint: If True (default) prints a list of the allowed commands :returns: a list of allowed commands ''' if detsym is None: detTyp = None if allowprint: print("Defined AD_get() & AD_set() commands for all Area Detectors") else: detObj = globals().get(detsym) if detObj is None: detObj = detsym if not isinstance(detObj,_ADobject): raise spec.specException('AD_show error: detsym '+str(detsym)+' is not defined in DefineAreaDetector') detTyp = detObj.detectortype if allowprint: print('Defined AD_get() & AD_set() commands for "'+str(detTyp)+'" Area Detectors') cmdlist = [] for cmd in sorted(CommandDict): for cmdObj in CommandDict[cmd]: if cmdObj.detectortype == detTyp or cmdObj.detectortype is None: if allowprint: print(' '+("%-14s" % cmd)+'\t'+str(cmdObj.comment)) cmdlist.append(cmd) break return cmdlist
def AD_done(detsyms,wait=True): """Test and optionally wait for the detector(s) have completed data collection :param object detsyms: An area detector variable (or name as a string), as defined in :func:`DefineAreaDetector`. Alternately, a list of area detectors variable or names (as strings) can be supplied. :param bool wait: If False test and return immediately; if True (default), return after the ``state`` command (if defined) indicates the data collection is done for each detector. :returns: True if all detector(s) are done; False is wait is False and any detectors are not done; or None if after 30 seconds, any detector is not complete """ # is the detector specified as a string? if isinstance(detsyms,str): detsyms = tuple((detsyms,)) # is there a list of detectors? try: symList = tuple(detsyms) except TypeError: symList = tuple((detsyms,)) alldone = True sleeptime = 0.0 for sym in symList: detObj = globals().get(sym) if detObj is None: detObj = sym if not isinstance(detObj,_ADobject): raise spec.specException('AD_done error: detsyms '+str(sym)+' is not defined in DefineAreaDetector') # get cmdObj of correct type for the current detector ============================== for cmdObj in CommandDict['state']: if cmdObj.detectortype is None: break # this a generic command if cmdObj.detectortype == detObj.detectortype: break # matches selected device else: continue if cmdObj.readstr == "": continue if cmdObj.useImagePrefix: PV = detObj.imageprefix + cmdObj.readstr else: PV = detObj.controlprefix + cmdObj.readstr if not (EPICS and spec.UseEPICS()): # in simulation print("Confirming detector "+detObj.symbol+" is done with collection") continue else: val = ep.caget(PV) if val == 0: continue # detector has completed if not wait: return False # detector is not done and a wait is requested while val != 0: if sleeptime > 30.0: print('AD_done wait exceeded count*frames+30 seconds for'+detObj.symbol+', continuing with script') return spec.sleep(0.1) sleeptime += 0.1 val = ep.caget(PV) # all detector(s) have signed off as done return True
def DefineAreaDetector(detsym, detectortype, controlprefix, imageprefix=None, comment=''): """Define an area detector for use in this module :param str detsym: a symbolic name for the detector. A global variable is defined in this module's name space with this name, This must be unique; exception specException is raised if a name is reused. :param str detectortype: the type of the detector. This must match one of the entries in global variable detectorTypeList (case sensitive). :param str controlprefix: the prefix for the detector PV (dev:camN). Omit the detector record field names (.NumImages, etc.). Inclusion of a final colon (':') is optional. :param str imageprefix: the prefix for the detector PV (dev:fmt). Omit the detector record field names (.FileNumber, etc.). Inclusion of a final colon (':') is optional. If not specified, defaults to the value for controlprefix :param string comment: a optional human-readable text field that describes the detector. :returns: detector object created for the detector Example: >>> DefineAreaDetector('GE1', 'GE', 'GE1:cam1', comment='bottom') >>> DefineAreaDetector('GE2', 'GE', 'GE2:cam1', comment='left') >>> DefineAreaDetector('GE3', 'GE', 'GE3:cam1', comment='top') >>> DefineAreaDetector('GE4', 'GE', 'GE4:cam1', comment='right') >>> DefineAreaDetector('ScintX', 'ScintX', 'ScintX:cam1', 'ScintX:TIFF1:') >>> DefineAreaDetector('Retiga1', 'Retiga', 'QIMAGE1:cam1:', 'QIMAGE1:TIFF1:') >>> DefineAreaDetector('Retiga2', 'Retiga', 'QIMAGE2:cam1:', 'QIMAGE2:TIFF1:') """ if imageprefix==None: imageprefix = controlprefix try: obj = _ADobject(detsym, detectortype, controlprefix, imageprefix, comment) except spec.specException,err: print('Error in creating detector '+str(detsym)+'\n '+str(err)) raise spec.specException('Error defining Area Detector '+str(detsym))
def AD_set(detsyms,cmd,value,ignoreOK=False): '''Set a parameter for an area detector. *This routine has been patched to add a \0 to strings, to fix a problem in EPICS.* :param object detsyms: An area detector variable (or name as a string), as defined in :func:`DefineAreaDetector`. Alternately, a list of area detectors variable or names (as strings) can be supplied. The command (``cmd``) must be defined for all supplied detectors, or an exception occurs. :param str cmd: a command that has been defined using :func:`defADcmd` :param str value: The value to set the parameter. This value will be set to the type defined for the command from :func:`defADcmd` if possible and will be checked against the enumeration range, if one is supplied. If the type conversion fails or the check fails, an exception is raised. :param bool ignoreOK: if ignoreOK is False (default) an exception will be raised if command cmd is not defined for a detector. If True, the command will be ignored :returns: the as-read parameter. The type will be determined by the PV associated with the command. Examples: >>> AD.DefineAreaDetector('GE1', 'GE', 'GE1:cam1') >>> val = AD.AD_set(AD.GE1,'acquire_time',3) or >>> val = AD.AD_set('GE1','acquire_time',3) also >>> hydra = (AD.GE1,AD.GE2,AD.GE3,AD.GE4) >>> val = AD.AD_set(hydra,'trigger_mode',0) ''' if cmd not in CommandDict: raise spec.specException('AD_set error: command '+str(cmd)+' is not defined') # is the detector specified as a string? if isinstance(detsyms,str): detsyms = tuple((detsyms,)) # is there a list of detectors? try: symList = tuple(detsyms) except TypeError: symList = tuple((detsyms,)) for sym in symList: detObj = globals().get(sym) if detObj is None: detObj = sym if not isinstance(detObj,_ADobject): raise spec.specException('AD_set error: detsyms '+str(sym)+' is not defined in DefineAreaDetector') # get cmdObj of correct type for the current detector ============================== for cmdObj in CommandDict[cmd]: if cmdObj.detectortype is None: break # this a generic command if cmdObj.detectortype == detObj.detectortype: break # matches selected device else: if ignoreOK: continue raise spec.specException('AD_set error: no match for command '+str(cmd)+ ' and detector type '+detObj.detectortype) if cmdObj.setstr == "": raise spec.specException('No AD_set "'+str(cmd)+'" set command') # validate the supplied value ========================================================= if cmdObj.enum is not None and not isinstance(cmdObj.enum,str): if value in cmdObj.enum: val = value else: raise spec.specException('AD_set error: value '+str(value)+ ' is not in allowed list: '+str(cmdObj.enum)) else: try: val = cmdObj.valtyp(value) except Exception, err: raise spec.specException('AD_set error: value '+str(value)+' is not of correct type') if isinstance(cmdObj.enum,str): try: tst = eval(cmdObj.enum) except Exception, err: tst = True print("AD_set: Error evaluating expression "+cmdObj.enum) print err if not tst: raise spec.specException('AD_set error: value '+str(value)+' is outside allowed range: '+cmdObj.enum)
def AD_get(detsyms,cmd,ignoreOK=False): '''Read a parameter from an area detector :param object detsyms: An area detector variable (or name as a string), as defined in :func:`DefineAreaDetector` or a list of area detector variables or strings. If a list (or tuple) of detectors is used, the function may return a list of values (but only if they differ.) :param str cmd: a command string that has been defined using :func:`defADcmd` :param bool ignoreOK: if ignoreOK is False (default) an exception will be raised if command cmd is not defined for a detector. If True, the command will be ignored :returns: the as-read parameter. The type will be determined by the PV associated with the command. If detsyms is a list and the read values differ, then a list of values is returned. Otherwise, only the (common) value is return. Examples: >>> AD.DefineAreaDetector('GE1', 'GE', 'GE1:cam1') >>> val = AD.AD_get(AD.GE1,'acquire_time') or >>> val = AD.AD_get('GE1','acquire_time') also >>> hydra = (AD.GE1,AD.GE2,AD.GE3,AD.GE4) >>> val = AD.AD_get(hydra,'trigger_mode') >>> try: >>> if len(val) == 4 and not isinstance(val,str): >>> print 'values disagree' >>> except TypeError: >>> pass ''' valList = [] if cmd not in CommandDict: raise spec.specException('AD_get error: command '+str(cmd)+' is not defined') # is the detector specified as a string? if isinstance(detsyms,str): detsyms = tuple((detsyms,)) # is there a list of detectors? try: symList = tuple(detsyms) except TypeError: symList = tuple((detsyms,)) for sym in symList: detObj = globals().get(sym) if detObj is None: detObj = sym if not isinstance(detObj,_ADobject): raise spec.specException('AD_get error: detsyms '+str(sym)+' is not defined in DefineAreaDetector') # get cmdObj of correct type for the current detector ============================== for cmdObj in CommandDict[cmd]: if cmdObj.detectortype is None: break # this a generic command if cmdObj.detectortype == detObj.detectortype: break # matches selected device else: if ignoreOK: continue raise spec.specException('AD_get error: no match for command '+str(cmd)+ ' and detector type '+detObj.detectortype) if cmdObj.readstr == "": raise spec.specException('No AD_get "'+str(cmd)+'" read command') if cmdObj.useImagePrefix: PV = detObj.imageprefix + cmdObj.readstr else: PV = detObj.controlprefix + cmdObj.readstr if not (EPICS and spec.UseEPICS()): # in simulation val = pvSim.get(PV) if cmd == 'state': val = 0 print("For "+detObj.symbol+" reading PV="+str(PV)+' value= '+str(val)) valList.append(val) continue valList.append( ep.caget(PV,as_string=(cmdObj.valtyp==str)) ) if len(valList) == 0: raise spec.specException('AD_get error: no detectors specified in '+str(detsyms)) # return a single value or a list if they don't agree val = valList[0] for v in valList: if v != val: return valList return valList