def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor self.name = 'cooler' # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.vocab = [ ('cooler', '[<timeout>] raw', self.coolerRaw), ('cooler', 'status', self.status), ('cooler', 'temps', self.temps), ('cooler', 'on <setpoint>', self.tempLoop), ('cooler', 'power <setpoint>', self.powerLoop), ('cooler', 'off', self.off), ('cooler2', '[<timeout>] raw', self.coolerRaw), ('cooler2', 'status', self.status), ('cooler2', 'temps', self.temps), ('cooler2', 'on <setpoint>', self.tempLoop), ('cooler2', 'power <setpoint>', self.powerLoop), ('cooler2', 'off', self.off), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary( "xcu_cooler", (1, 2), keys.Key("setpoint", types.Float(), help='cooler setpoint'), keys.Key("timeout", types.Float(), help='timeout (in seconds) for raw command.'), )
def __init__(self, actor): self.actor = actor self.cam = actor.name[:4] self.version = actor.version # ecamera files should not be gzipped, to make processing in IRAF easier. if 'ecamera' in actor.name: self.doCompress = False self.ext = '' else: self.doCompress = True self.ext = '.gz' self.dataRoot = self.actor.config.get(self.actor.name, 'dataRoot') self.filePrefix = self.actor.config.get(self.actor.name, 'filePrefix') # We track the names of any currently valid dark and flat files. self.biasFile = None self.darkFile = None self.biasTemp = 99.9 self.darkTemp = 99.9 self.flatFile = None self.flatCartridge = -1 self.simRoot = None self.simSeqno = 1 self.resync(actor.bcast, doFinish=False) self.keys = opsKeys.KeysDictionary("gcamera_camera", (1, 1), opsKeys.Key("time", types.Float(), help="exposure time."), opsKeys.Key("mjd", types.String(), help="MJD for simulation sequence"), opsKeys.Key("cartridge", types.Int(), help="cartridge number; used to bind flats to images."), opsKeys.Key("seqno", types.Int(), help="image number for simulation sequence."), opsKeys.Key("filename", types.String(), help="the filename to write to"), opsKeys.Key("stack", types.Int(), help="number of exposures to take and stack."), opsKeys.Key("temp", types.Float(), help="camera temperature setpoint."), opsKeys.Key("n", types.Int(), help="number of times to loop status queries."), ) self.vocab = [ ('ping', '', self.pingCmd), ('status', '', self.status), ('deathStatus', '<n>', self.deathStatus), ('setBOSSFormat', '', self.setBOSSFormat), ('setFlatFormat', '', self.setFlatFormat), ('simulate', '(off)', self.simulateOff), ('simulate', '<mjd> <seqno>', self.simulateFromSeq), ('setTemp', '<temp>', self.setTemp), ('expose', '<time> [<cartridge>] [<filename>] [<stack>] [force]', self.expose), ('bias', '[<stack>]', self.expose), ('dark', '<time> [<filename>] [<stack>]', self.expose), ('flat', '<time> [<cartridge>] [<filename>] [<stack>]', self.expose), ('reconnect', '', self.reconnect), ('aph', '', self.reconnect), ('resync', '', self.resync), ('shutdown', '[force]', self.shutdown) ]
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.vocab = [ ('pcm', '@raw', self.pcmRaw), # ('pcm', 'status [@(clear)]', self.udpStatus), ('power', '@(on|off|cycle) @(motors|gauge|cooler|temps|bee|fee|interlock|heaters|all) [@(force)]', self.nPower), # ('power', '@(on|off) @(motors|gauge|cooler|temps|bee|fee|interlock|heaters|all) [@(force)]', self.power), ('power', '@(voltage|current) @(ups|aux|motors|gauge|cooler|temps|bee|fee|interlock|heaters|all) [<n>] [@(counts)]', self.getPower), ('power', '@(status)', self.getPowerStatus), ('pcm', '@(calibrate) @(voltage|current|environment) @(ups|aux|motors|gauge|cooler|temps|bee|fee|interlock|heaters|temperature|pressure) <r1> <m1> <r2> <m2>', self.calibrateChannel), ('pcm', '@(saveCalData)', self.saveCalDataToROM), ('pcm', '@(environment) @(temperature|pressure|all)', self.getEnvironment), ('pcm', 'status', self.getPCMStatus), ('pcm', '@(reset) @(ethernet|system) [@(force)]', self.resetPCM), ('pcm', '@(setMask) @(powerOn|lowVoltage) <mask>', self.setMask), ('pcm', '@(getMask) @(powerOn|lowVoltage)', self.getMask), ('pcm', '@(getThreshold) @(upsBattery|upsLow|auxLow)', self.getThreshold), ('pcm', '@(setThreshold) @(upsBattery|upsLow|auxLow) <v>', self.setThreshold), ('pcm', '@(bootload) <filename>', self.bootloader), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary( "xcu_pcm", (1, 1), keys.Key("n", types.Int(), help='number of samples'), keys.Key("m1", types.Float(), help='measured value 1 (low)'), keys.Key("m2", types.Float(), help='measured value 2 (high)'), keys.Key("r1", types.Float(), help='raw count 1 (low)'), keys.Key("r2", types.Float(), help='raw count 2 (low)'), keys.Key("mask", types.String(), help='mask value, 8 bit binary string'), keys.Key("v", types.Float(), help='thershold voltage'), keys.Key("filename", types.String(), help='new firmware file name'), )
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.vocab = [ ('pi', '@raw', self.sunssRaw), ('pi', 'move <degrees>', self.move), ('pi', 'move <steps>', self.move), ('status', '', self.status), ('stop', '', self.stop), ('track', '<ra> <dec> [<speed>] [<exptime>]', self.track), ('enable', '[<strategy>]', self.enable), ('disable', '', self.disable), ('startExposures', '', self.startExposures), ('takeFlats', '', self.takeFlats), ('reloadTracker', '', self.reloadTracker), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary( "sunss", (1, 1), keys.Key("ra", types.Float(), help='RA degrees to start tracking from'), keys.Key("dec", types.Float(), help='Dec degrees to start tracking from'), keys.Key("exptime", types.Float(), help='Exposure time'), keys.Key("degrees", types.Float(), help='Degrees to move frm current position'), keys.Key("steps", types.Int(), help='Steps to move frm current position'), keys.Key("speed", types.Int(), default=1, help='Tracking speed multiple to test with'), keys.Key("strategy", types.String(), help='How to respond to telescope changes'), ) self.state = 'stopped' self.connected = False
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a le le argument, the parsed and typed command. # self.name = "sync" self.vocab = [ ('slit', '<focus> [@(microns)] [@(abs)] [<cams>]', self.slitFocus), ('slit', 'dither [<x>] [<y>] [@(pixels|microns)] [@(abs)] [<cams>]', self.slitDither), ('ccdMotors', 'move [<a>] [<b>] [<c>] [<piston>] [@(microns)] [@(abs)] [<cams>]', self.ccdMotors), ('iis', '[<on>] [<warmingTime>] [<cams>]', self.iisOn), ('iis', '<off> [<cams>]', self.iisOff), ('checkFocus', '[<cams>]', self.checkFocus), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary( "sps_sync", (1, 1), keys.Key('focus', types.Float(), help='focus value'), keys.Key("cams", types.String() * (1, ), help='list of camera to take exposure from'), keys.Key("a", types.Float(), help='the number of ticks/microns to move actuator A'), keys.Key("b", types.Float(), help='the number of ticks/microns to move actuator B'), keys.Key("c", types.Float(), help='the number of ticks/microns to move actuator C'), keys.Key( "piston", types.Float(), help='the number of ticks/microns to move actuators A,B, and C' ), keys.Key("x", types.Float(), help='dither in pixels wrt ccd x direction'), keys.Key("y", types.Float(), help='dither in pixels wrt ccd y direction'), keys.Key('on', types.String() * (1, None), help='which iis lamp to switch on.'), keys.Key('off', types.String() * (1, None), help='which iis lamp to switch off.'), keys.Key('warmingTime', types.Float(), help='customizable warming time'), )
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.vocab = [ ('ccd', 'status', self.status), ('ccd', 'wipe', self.wipe), ('ccd', 'read [@(bias|dark|flat|arc|object|junk)] [<exptime>] [<obstime>]', self.read), ('ccd', 'expose <nbias>', self.exposeBiases), ('ccd', 'temps', self.fetchTemps), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary("fsm_ccd", (1, 1), keys.Key("obstime", types.String(), help='official DATE-OBS string'), keys.Key("exptime", types.Float(), help='official EXPTIME'), keys.Key("nbias", types.Int(), help='number of biases to take'), )
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.vocab = [ ('ping', '', self.ping), ('status', '', self.status), ('inventory', '', self.inventory), ('testArgs', '[<cnt>] [<exptime>]', self.testArgs), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary("core_core", (1, 1), keys.Key("device", types.String(), help='device name, probably like bee_r1'), keys.Key("cam", types.String(), help='camera name, e.g. r1'), keys.Key("cnt", types.Int(), help='a count'), keys.Key("exptime", types.Float(), help='exposure time'), )
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.name = 'drpProcess' self.vocab = [ ('ping', '', self.ping), ('status', '', self.status), ('ingest', '<fitsPath>', self.ingest), ('detrend', '[<context>] <fitsPath>', self.detrend), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary( "drp_drp", (1, 1), keys.Key("expTime", types.Float(), help="The exposure time"), keys.Key("context", types.String(), help="custom drp folder"), keys.Key("fitsPath", types.String(), help="FITS File path"), )
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.vocab = [ ('getVisit', '', self.getVisit), ('getFitsCards', '<frameId> <expTime> <expType>', self.getFitsCards), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary("core_core", (1, 1), keys.Key("expType", types.Enum('bias', 'dark', 'arc', 'flat', 'object', 'acquisition'), help='exposure type for FITS header'), keys.Key("expTime", types.Float(), help='exposure time'), keys.Key("frameId", types.String(), help='Gen2 frame ID'), )
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.name = "mono" self.vocab = [ (self.name, 'status', self.status), (self.name, 'init', self.initialise), (self.name, '@(shutter) @(open|close)', self.cmdShutter), (self.name, '@(set) <grating>', self.setGrating), (self.name, '@(set) <outport>', self.setOutport), (self.name, '@(set) <wave>', self.setWave), (self.name, 'stop', self.stop), (self.name, 'start [@(operation|simulation)]', self.start), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary( "dcb__mono", (1, 1), keys.Key("grating", types.Int(), help="Grating Id"), keys.Key("outport", types.Int(), help="Outport Id"), keys.Key("wave", types.Float(), help="Wavelength"), )
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # identArgs = '[<cam>] [<arm>] [<sm>]' self.vocab = [ ('sps', f'@startExposures <exptime> {identArgs} [<name>] [<comments>] [@doBias] [@doTest]', self.startExposures), ('domeArc', f'<exptime> {identArgs} [<name>] [<comments>] [<duplicate>] [@doTest]', self.domeArc), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary('iic_sunss', (1, 1), keys.Key('exptime', types.Float() * (1,), help='exptime list (seconds)'), keys.Key('cam', types.String() * (1,), help='camera(s) to take exposure from'), keys.Key('arm', types.String() * (1,), help='arm to take exposure from'), keys.Key('sm', types.Int() * (1,), help='spectrograph module(s) to take exposure from'), keys.Key('name', types.String(), help='iic_sequence name'), keys.Key('comments', types.String(), help='iic_sequence comments'), keys.Key('duplicate', types.Int(), help='exposure duplicate (1 is default)'), )
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a le le argument, the parsed and typed command. # exptypes = "|".join(ExposeCmd.expTypes[1:]) self.exp = dict() self.vocab = [( 'expose', f'@({exptypes}) <exptime> [<visit>] [<cam>] [<cams>] [@doLamps] [@doTest]', self.doExposure), ('expose', 'bias [<visit>] [<cam>] [<cams>] [doTest]', self.doExposure), ('exposure', 'abort <visit>', self.abort), ('exposure', 'finish <visit>', self.finish), ('exposure', 'status', self.status)] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary( "sps_expose", (1, 1), keys.Key("exptime", types.Float(), help="The exposure time"), keys.Key("cam", types.String(), help='single camera to take exposure from'), keys.Key("cams", types.String() * (1, ), help='list of camera to take exposure from'), keys.Key("visit", types.Int(), help='PFS visit id'), )
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.vocab = [ ('fpaMotors', 'findRange <cam> [<current>] [<axis>]', self.findRange), ('fpaMotors', 'checkRepeats <cam> [<reps>] [<axis>] [<distance>] [<delay>]', self.checkRepeats), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary("test.test", (1, 1), keys.Key("cam", types.String(), help='camera name, e.g. b2'), keys.Key("axis", types.Enum('a','b','c'), default=None, help='axis name'), keys.Key("reps", types.Int(), default=10, help='number of repetitions'), keys.Key("delay", types.Float(), default=60, help='delay between repetitions'), keys.Key("distance", types.Int(), default=3000, help='how far to move'), keys.Key("current", types.Int(), help='motor current override'), )
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.vocab = [ ('gatevalve', 'status', self.status), ('gatevalve', 'open [@(underVacuum)] [@(atAtmosphere)] [@(ok)] [@(reallyforce)] [@(dryrun)]', self.open), ('gatevalve', 'close', self.close), ('interlock', 'status', self.status), ('interlock', '@raw', self.interlockRaw), ('interlock', 'sendImage <path> [@doWait] [@sendReboot] [@straightToCode]', self.sendImage), ('setLimits', '[<atm>] [<soft>] [<hard>]', self.setLimits), ('sam', 'off', self.samOff), ('sam', 'on', self.samOn), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary("xcu_gatevalve", (1, 2), keys.Key("path", types.String(), help='path of firmware file'), keys.Key("soft", types.Float(), help='soft limit for dPressure'), keys.Key("atm", types.Float(), help='lower limit for atmospheric pressure'), keys.Key("hard", types.Float(), help='hard limit for dPressure'), ) # The valve manual declares 30 mbar/22.5 Torr as the maximum pressure across the valve. self.atmThreshold = 460.0 # The absolute lowest air pressure to accept as at atmosphere, Torr self.dPressSoftLimit = 22 # The overridable pressure difference limit for opening, Torr self.dPressHardLimit = 22 # The absolute pressure difference limit for opening, Torr try: self.actor.config.get('interlock', 'port') val = 'new' except Exception: val = 'old' self._interlockType = val
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.vocab = [ ('ping', '', self.ping), ('status', '', self.status), ('start', '<cam> <setpoint> [<period>] [<kp>]', self.startLoop), ('stop', '<cam>', self.stopLoop), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary('regul_regul', (1, 1), keys.Key('setpoint', types.Float(), help='Detector box temperature setpoint'), keys.Key('period', types.Float(), help='control loop period (hours), default=8'), keys.Key('kp', types.Float(), help='control loop coefficient, default=1.1'), keys.Key('cam', types.String(), help='single camera to regulate'), )
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.vocab = [ ('led', '@raw', self.raw), ('led', '@(on|flash|off)', self.setPower), ('led', '@(config|configflash) [<ledperiod>] [<dutycycle>]', self.configParameters), ('led', 'status', self.status), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary( "peb_led", (1, 2), keys.Key("ledperiod", types.Int(), help="Period in us"), keys.Key("dutycycle", types.Float(), help="Duty cycle in %"), )
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.vocab = [ ('ping', '', self.ping), ('status', '', self.status), ('connect', '<controller> [<name>]', self.connect), ('disconnect', '<controller>', self.disconnect), ('monitor', '<controllers> <period>', self.monitor), ('temps', '', self.temps), ('temps', 'status', self.temps), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary( "ccd_ccd", (1, 1), keys.Key("name", types.String(), help='the name of a multi-instance controller.'), keys.Key("period", types.Float(), help='how often a periodic monitor should be called. '), keys.Key("controller", types.String(), help='the name of a controller.'), keys.Key("controllers", types.String() * (1, None), help='the names of 1 or more controllers to work on'), )
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.vocab = [ ('wipe', '[<nrows>] [<ncols>] [@fast]', self.wipe), ('read', '[@(bias|dark|flat|arc|object|domeflat|test|junk)] [<nrows>] [<ncols>] [<visit>] ' '[<exptime>] [<darktime>] [<obstime>] [<comment>] [@nope] [@swoff] [@fast] [<row0>]', self.read), ('erase', '', self.erase), ('clock', '[<nrows>] <ncols>', self.clock), ('revread', '[<nrows>] [<binning>]', self.revRead), ('clearExposure', '', self.clearExposure), ('expose', '<nbias>', self.exposeBiases), ('expose', '<darks>', self.exposeDarks), ('setOffset', '<offset> <value>', self.setOffset), ('setOffsets', '<filename>', self.setOffsets), ('controlLVDS', '@(on|off)', self.controlLVDS), ('readCtrlWord', '', self.readCtrlWord), ('setClocks', '[<on>] [<off>]', self.setClocks), ('holdClocks', '[<on>] [<off>]', self.holdClocks), ('setAdcMode', '@(msb|mid|lsb)', self.setAdcMode), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary( "ccd_fee", (1, 1), keys.Key("nrows", types.Int(), help='Number of rows to readout'), keys.Key("ncols", types.Int(), help='Number of amp columns to readout'), keys.Key("binning", types.Int(), help='number of rows to bin'), keys.Key("filename", types.String(), help='the name of a file to load from.'), keys.Key("visit", types.Int(), help='PFS visit to ass ign to filename'), keys.Key("obstime", types.String(), help='official DATE-OBS string'), keys.Key("exptime", types.Float(), help='official EXPTIME'), keys.Key("darktime", types.Float(), help='official EXPTIME'), keys.Key("comment", types.String(), help='a comment to add.'), keys.Key("nbias", types.Int(), help='number of biases to take'), keys.Key("darks", types.Float() * (1, ), help='list of dark times to take'), keys.Key("offset", types.Int(), types.Int(), types.String(), help='offset value'), keys.Key("value", types.Float(), help='offset value'), keys.Key("on", types.Enum(*sorted([c.label for c in clockIDs.signals])) * (1, ), help="signals to turn on"), keys.Key("off", types.Enum(*sorted([c.label for c in clockIDs.signals])) * (1, ), help="signals to turn off"), keys.Key("row0", types.Int(), help='first row of band to read'), ) self.exposureState = 'idle' self.nrows = None self.ncols = None self.actor.exposure = None self.initCallbacks() self.genStatus()
def __init__(self, actor): # initialize from the superclass super(SopCmd_APO, self).__init__(actor) # Define APO specific keys. self.keys.extend([ keys.Key('narc', types.Int(), help='Number of arcs to take'), keys.Key('nbias', types.Int(), help='Number of biases to take'), keys.Key('ndark', types.Int(), help='Number of darks to take'), keys.Key('nexp', types.Int(), help='Number of exposures to take'), keys.Key('nflat', types.Int(), help='Number of flats to take'), keys.Key('arcTime', types.Float(), help='Exposure time for arcs'), keys.Key('darkTime', types.Float(), help='Exposure time for flats'), keys.Key('flatTime', types.Float(), help='Exposure time for flats'), keys.Key('test', help='Assert that the exposures are ' 'not expected to be meaningful'), keys.Key('sp1', help='Select SP1'), keys.Key('sp2', help='Select SP2'), keys.Key('nStep', types.Int(), help='Number of dithered ' 'exposures to take'), keys.Key('nTick', types.Int(), help='Number of ticks ' 'to move collimator'), keys.Key('dither', types.String(), help='MaNGA dither position ' 'for a single dither.'), keys.Key('dithers', types.String(), help='MaNGA dither positions ' 'for a dither sequence.'), keys.Key('mangaDithers', types.String(), help='MaNGA dither ' 'positions for a ' 'dither sequence.'), keys.Key('mangaDither', types.String(), help='MaNGA dither ' 'position for a ' 'single dither.'), keys.Key('count', types.Int(), help='Number of MaNGA dither ' 'sets to perform.'), keys.Key('noHartmann', help='Don\'t make Hartmann corrections'), keys.Key('noCalibs', help='Don\'t run the calibration step'), keys.Key('keepOffsets', help='When slewing, do not clear ' 'accumulated offsets'), keys.Key('ditherSeq', types.String(), help='dither positions for ' 'each sequence. ' 'e.g. AB') ]) # Define new commands for APO self.vocab = [ ('doBossCalibs', '[<narc>] [<nbias>] [<ndark>] [<nflat>] ' '[<arcTime>] [<darkTime>] [<flatTime>] ' '[<guiderFlatTime>] [abort]', self.doBossCalibs), ('doBossScience', '[<expTime>] [<nexp>] [abort] [stop] [test]', self.doBossScience), ('doMangaDither', '[<expTime>] [<dither>] [stop] [abort]', self.doMangaDither), ('doMangaSequence', '[<expTime>] [<dithers>] [<count>] [stop] ' '[abort]', self.doMangaSequence), ('doApogeeMangaDither', '[<mangaDither>] [<comment>] ' '[stop] [abort]', self.doApogeeMangaDither), ('doApogeeMangaSequence', '[<mangaDithers>] [<count>] [<comment>] ' '[stop] [abort]', self.doApogeeMangaSequence), ('gotoField', '[<arcTime>] [<flatTime>] [<guiderFlatTime>] ' '[<guiderTime>] [noSlew] [noHartmann] [noCalibs] ' '[noGuider] [abort] [keepOffsets]', self.gotoField), ('ditheredFlat', '[sp1] [sp2] [<expTime>] [<nStep>] [<nTick>]', self.ditheredFlat), ('hartmann', '[<expTime>]', self.hartmann), ('collimateBoss', '', self.collimateBoss), ('lampsOff', '', self.lampsOff) ]
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor self.boresightLoop = None # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # seqArgs = '[<name>] [<comments>]' self.vocab = [ ('startBoresightAcquisition', '[<expTime>] [<nExposures>]', self.startBoresightAcquisition), ('addBoresightPosition', '', self.addBoresightPosition), ('reduceBoresightData', '', self.reduceBoresightData), ('abortBoresightAcquisition', '', self.abortBoresightAcquisition), ('fpsLoop', '[<expTime>] [<cnt>]', self.fpsLoop), # ('mcsLoop', '[<expTime>] [<cnt>] [@noCentroids]', self.mcsLoop), ('moveToPfsDesign', f'<designId> {seqArgs}', self.moveToPfsDesign), ('movePhiToAngle', f'<angle> <iteration> {seqArgs}', self.movePhiToAngle), ('moveToHome', f'@(phi|theta|all) {seqArgs}', self.moveToHome), ('moveToSafePosition', f'{seqArgs}', self.moveToSafePosition), ('gotoVerticalFromPhi60', f'{seqArgs}', self.gotoVerticalFromPhi60), ('makeMotorMap', f'@(phi|theta) <stepsize> <repeat> [@slowOnly] {seqArgs}', self.makeMotorMap), ('makeOntimeMap', f'@(phi|theta) {seqArgs}', self.makeOntimeMap), ('angleConvergenceTest', f'@(phi|theta) <angleTargets> {seqArgs}', self.angleConvergenceTest), ('targetConvergenceTest', f'@(ontime|speed) <totalTargets> <maxsteps> {seqArgs}', self.targetConvergenceTest), ('motorOntimeSearch', f'@(phi|theta) {seqArgs}', self.motorOntimeSearch), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary( "iic_iic", (1, 1), keys.Key("nPositions", types.Int(), help="number of angles to measure at"), keys.Key("nExposures", types.Int(), help="number of exposures to take at each position"), keys.Key("expTime", types.Float(), default=1.0, help="Seconds for exposure"), keys.Key('name', types.String(), help='sps_sequence name'), keys.Key('comments', types.String(), help='sps_sequence comments'), keys.Key("cnt", types.Int(), default=1, help="times to run loop"), keys.Key("angle", types.Int(), help="arm angle"), keys.Key("stepsize", types.Int(), help="step size of motor"), keys.Key("repeat", types.Int(), help="number of iteration for motor map generation"), keys.Key("angleTargets", types.Int(), help="Target number for angle convergence"), keys.Key("totalTargets", types.Int(), help="Target number for 2D convergence"), keys.Key("maxsteps", types.Int(), help="Maximum step number for 2D convergence test"), keys.Key("iteration", types.Int(), help="Interation number"), keys.Key( "designId", types.Long(), help= "pfsDesignId for the field,which defines the fiber positions"), )
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor self.logger = self.actor.logger if self.actor.instrument != 'CHARIS': self.logger.info('not CHARIS, skipping CharisCmd.py') self.vocab = [] self.keys = keys.KeysDictionary('charis', (1, 1)) return # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.vocab = [ ('backend', '@(windows|unix)', self.setBackend), ('win', '@raw', self.winRaw), ('wingetconfig', '', self.winGetconfig), ('winflush', '', self.flushProgramInput), ('charisConfig', '', self.charisConfig), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary( "hx", (1, 2), keys.Key("seqno", types.Int(), default=None, help='If set, the assigned sequence number.'), keys.Key("nramp", types.Int(), default=1, help='number of ramps to take.'), keys.Key("nreset", types.Int(), default=1, help='number of resets to make.'), keys.Key("nread", types.Int(), default=2, help='number of readss to take.'), keys.Key("ngroup", types.Int(), default=1, help='number of groups.'), keys.Key("ndrop", types.Int(), default=0, help='number of drops to waste.'), keys.Key("itime", types.Float(), default=None, help='desired integration time'), keys.Key("exptype", types.String(), default=None, help='What to put in IMAGETYP/DATA-TYP.'), keys.Key("objname", types.String(), default=None, help='What to put in OBJECT.'), keys.Key("configName", types.String(), default=None, help='configuration name'), keys.Key("voltageName", types.String(), default=None, help='voltage name'), keys.Key("voltage", types.Float(), default=None, help='voltage'), ) self.backend = 'hxhal' self.rampConfig = None self.dataRoot = "/home/data/charis" self.dataPrefix = "CRSA" from hxActor.charis import seqPath self.fileGenerator = seqPath.NightFilenameGen( self.dataRoot, filePrefix=self.dataPrefix)
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # self.vocab = [ ('motors', '@raw', self.motorsRaw), ('motors', 'status', self.motorStatus), ('motors', 'initDefaults', self.storePowerOnParameters), ('motors', 'initCcd', self.initCcd), ('motors', 'init', self.initCcd), ('motors', 'homeCcd [<axes>]', self.homeCcd), ('motors', 'home [<axes>]', self.homeCcd), ('motors', 'moveCcd [<a>] [<b>] [<c>] [<piston>] [@(microns)] [@(abs)] [@(force)]', self.moveCcd), ('motors', 'move [<a>] [<b>] [<c>] [<piston>] [@(microns)] [@(abs)] [@(force)]', self.moveCcd), ('motors', 'moveFocus [<microns>] [@(abs)]', self.moveFocus), ('motors', 'halt', self.haltMotors), ('motors', '@(toSwitch) @(a|b|c) @(home|far) @(set|clear)', self.toSwitch), ('motors', '@(toCenter|toFocus|nearFar|nearHome)', self.moveToName), ('motors', 'okPositions', self.okPositions), ('motors', 'declareMove', self.declareMove), ('motors', 'reloadConfig', self.loadConfig), ('motors', 'setTilts <spatial> <spectral>', self.setTilts), ('motors', 'setArmOffsets [<a>] [<b>] [<c>]', self.setArmOffsets), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary("xcu_motors", (1, 1), keys.Key("axes", types.String()*(1,3), help='list of motor names'), keys.Key("a", types.Float(), help='the number of ticks/microns to move actuator A'), keys.Key("b", types.Float(), help='the number of ticks/microns to move actuator B'), keys.Key("c", types.Float(), help='the number of ticks/microns to move actuator C'), keys.Key("piston", types.Float(), help='the number of ticks/microns to move actuators A,B, and C'), keys.Key("microns", types.Float(), help='the number of microns to move actuators'), keys.Key("spatial", types.Float(), help='microns of spatial tilt'), keys.Key("spectral", types.Float(), help='microns of spectral tilt'), ) if self.actor.isNir(): self.pivotRatios = (40.62, 40.26, 40.26) else: self.pivotRatios = (36.77, 36.02, 36.02) # Precalculate conversion factors to convert microns to motor steps # microsteps per rev * pivot ratio / screw pitch self.a_microns_to_steps = self.stepsPerRev * self.pivotRatios[0] / self.leadScrewPitch self.b_microns_to_steps = self.stepsPerRev * self.pivotRatios[1] / self.leadScrewPitch self.c_microns_to_steps = self.stepsPerRev * self.pivotRatios[2] / self.leadScrewPitch self.microns_to_steps = np.array([self.a_microns_to_steps, self.b_microns_to_steps, self.c_microns_to_steps]) self.a_microns_to_microsteps = self.a_microns_to_steps * self.microstepping self.b_microns_to_microsteps = self.b_microns_to_steps * self.microstepping self.c_microns_to_microsteps = self.c_microns_to_steps * self.microstepping self.homeDistance = 400 * self.a_microns_to_microsteps # max steps for homing try: self.brokenLAMr1A = self.actor.config.getboolean('hacks', 'brokenLAMr1A') except: self.brokenLAMr1A = False self.instData = instdata.InstData(self.actor) self.instConfig = instdata.InstConfig(self.actor.name, idDict=self.actor.ids.idDict) self.loadConfig()
def __init__(self, actor): self.actor = actor self.replyQueue = sopActor.Queue('(replyQueue)', 0) # # Declare keys that we're going to use # self.keys = keys.KeysDictionary( "sop_sop", (2, 0), keys.Key("abort", help="Abort a command"), keys.Key("clear", help="Clear a flag"), keys.Key("expTime", types.Float(), help="Exposure time"), keys.Key("fiberId", types.Int(), help="A fiber ID"), keys.Key("keepQueues", help="Restart thread queues"), keys.Key("noSlew", help="Don't slew to field"), keys.Key("noDomeFlat", help="Don't run the dome flat step"), keys.Key("geek", help="Show things that only some of us love"), keys.Key("subSystem", types.String() * (1, ), help="The sub-systems to bypass"), keys.Key("threads", types.String() * (1, ), help="Threads to restart; default: all"), keys.Key("ditherPairs", types.Int(), help="Number of dither pairs (AB or BA) to observe"), keys.Key('guiderTime', types.Float(), help='Exposure time ' 'for guider'), keys.Key('guiderFlatTime', types.Float(), help='Exposure time ' 'for guider flats'), keys.Key('noGuider', help='Don\'t start the guider'), keys.Key("comment", types.String(), help="comment for headers"), keys.Key("scriptName", types.String(), help="name of script to run"), keys.Key("az", types.Float(), help="what azimuth to slew to"), keys.Key("rotOffset", types.Float(), help="what rotator offset to add"), keys.Key("alt", types.Float(), help="what altitude to slew to"), ) # # Declare commands # self.vocab = [ ("bypass", "<subSystem> [clear]", self.bypass), ("doApogeeScience", "[<expTime>] [<ditherPairs>] [stop] [<abort>] [<comment>]", self.doApogeeScience), ("doApogeeSkyFlats", "[<expTime>] [<ditherPairs>] [stop] [abort]", self.doApogeeSkyFlats), ("ping", "", self.ping), ("restart", "[<threads>] [keepQueues]", self.restart), ("gotoInstrumentChange", "[abort] [stop]", self.gotoInstrumentChange), ("gotoStow", "[abort] [stop]", self.gotoStow), ("gotoAll60", "[abort] [stop]", self.gotoAll60), ("gotoStow60", "[abort] [stop]", self.gotoStow60), ("gotoGangChange", "[<alt>] [abort] [stop] [noDomeFlat] [noSlew]", self.gotoGangChange), ("doApogeeDomeFlat", "[stop] [abort]", self.doApogeeDomeFlat), ("setFakeField", "[<az>] [<alt>] [<rotOffset>]", self.setFakeField), ("status", "[geek]", self.status), ("reinit", "", self.reinit), ("runScript", "<scriptName>", self.runScript), ("listScripts", "", self.listScripts), ]
def __init__(self, actor): # This lets us access the rest of the actor. self.actor = actor self.seq = None # Declare the commands we implement. When the actor is started # these are registered with the parser, which will call the # associated methods when matched. The callbacks will be # passed a single argument, the parsed and typed command. # seqArgs = '[<name>] [<comments>] [<head>] [<tail>] [@doTest]' identArgs = '[<cam>] [<arm>] [<sm>]' commonArgs = f'{identArgs} [<duplicate>] {seqArgs}' dcbArgs = f'[<switchOn>] [<switchOff>] [<warmingTime>] [<attenuator>] [force]' timedLampsArcArgs = '[<hgar>] [<hgcd>] [<argon>] [<neon>] [<krypton>] [<xenon>] [@doShutterTiming]' self.vocab = [ ('masterBiases', f'{commonArgs}', self.masterBiases), ('masterDarks', f'[<exptime>] {commonArgs}', self.masterDarks), ('ditheredFlats', f'<exptime> [<pixels>] [<nPositions>] [switchOff] {dcbArgs} {commonArgs}', self.ditheredFlats), ('scienceArc', f'<exptime> {dcbArgs} {commonArgs}', self.scienceArc), ('scienceTrace', f'<exptime> [<window>] [switchOff] {dcbArgs} {commonArgs}', self.scienceTrace), ('scienceObject', f'<exptime> [<window>] {commonArgs}', self.scienceObject), ('domeFlat', f'<exptime> [<window>] {commonArgs}', self.domeFlat), ('bias', f'{commonArgs}', self.doBias), ('dark', f'<exptime> {commonArgs}', self.doDark), ('expose', f'arc <exptime> {dcbArgs} {commonArgs}', self.scienceArc), ('expose', f'flat <exptime> [noLampCtl] [switchOff] {dcbArgs} {commonArgs}', self.scienceTrace), ('slit', f'throughfocus <exptime> <position> {dcbArgs} {commonArgs}', self.slitThroughFocus), ('detector', f'throughfocus <exptime> <position> [<tilt>] {dcbArgs} {commonArgs}', self.detThroughFocus), ('dither', f'arc <exptime> <pixels> [doMinus] {dcbArgs} {commonArgs}', self.ditheredArcs), ('defocus', f'arc <exptime> <position> {dcbArgs} {commonArgs}', self.defocusedArcs), ('custom', '[<name>] [<comments>] [<head>] [<tail>]', self.custom), ('ditheredFlats', f'<halogen> [@doShutterTiming] [<pixels>] [<nPositions>] {commonArgs}', self.ditheredFlats), ('scienceArc', f'{timedLampsArcArgs} {commonArgs}', self.scienceArc), ('scienceTrace', f'<halogen> [@doShutterTiming] [<window>] {commonArgs}', self.scienceTrace), ('expose', f'arc {timedLampsArcArgs} {commonArgs}', self.scienceArc), ('expose', f'flat <halogen> {commonArgs}', self.scienceTrace), ('test', f'hexapodStability {timedLampsArcArgs} [<position>] {commonArgs}', self.hexapodStability), ('dither', f'arc {timedLampsArcArgs} <pixels> [doMinus] {commonArgs}', self.ditheredArcs), ('detector', f'throughfocus {timedLampsArcArgs} <position> [<tilt>] {commonArgs}', self.detThroughFocus), ('defocus', f'arc {timedLampsArcArgs} <position> {commonArgs}', self.defocusedArcs), ('sps', 'rdaMove (low|med) [<sm>]', self.rdaMove), ] # Define typed command arguments for the above commands. self.keys = keys.KeysDictionary( 'iic_iic', (1, 1), keys.Key('exptime', types.Float() * (1, ), help='exptime list (seconds)'), keys.Key('duplicate', types.Int(), help='exposure duplicate (1 is default)'), keys.Key('cam', types.String() * (1, ), help='camera(s) to take exposure from'), keys.Key('arm', types.String() * (1, ), help='arm to take exposure from'), keys.Key('sm', types.Int() * (1, ), help='spectrograph module(s) to take exposure from'), keys.Key('name', types.String(), help='iic_sequence name'), keys.Key('comments', types.String(), help='iic_sequence comments'), keys.Key('head', types.String() * (1, ), help='cmdStr list to process before'), keys.Key('tail', types.String() * (1, ), help='cmdStr list to process after'), keys.Key('switchOn', types.String() * (1, None), help='which dcb lamp to switch on.'), keys.Key('switchOff', types.String() * (1, None), help='which dcb lamp to switch off.'), keys.Key('iisOn', types.String() * (1, None), help='which iis lamp to switch on.'), keys.Key('iisOff', types.String() * (1, None), help='which iis lamp to switch off.'), keys.Key('attenuator', types.Int(), help='Attenuator value.'), keys.Key( 'position', types.Float() * (1, 3), help= 'slit/motor position for throughfocus same args as np.linspace' ), keys.Key('tilt', types.Float() * (1, 3), help='motor tilt (a, b, c)'), keys.Key( 'nPositions', types.Int(), help='Number of position for dithered flats (default : 20)'), keys.Key('pixels', types.Float(), help='dithering step in pixels'), keys.Key('warmingTime', types.Float(), help='customizable warming time'), keys.Key('halogen', types.Float(), help='quartz halogen lamp on time'), keys.Key('argon', types.Float(), help='Ar lamp on time'), keys.Key('hgar', types.Float(), help='HgAr lamp on time'), keys.Key('neon', types.Float(), help='Ne lamp on time'), keys.Key('krypton', types.Float(), help='Kr lamp on time'), keys.Key('hgcd', types.Float(), help='HgCd lamp on time'), keys.Key('xenon', types.Float(), help='Xenon lamp on time'), keys.Key("window", types.Int() * (1, 2), help='first row, total number of rows to read'), )
def __init__(self, actor): """Declares keys that this actor uses, and available commands that can be sent to it. actor is the actor that this is part of (guiderActor, in this case). """ self.actor = actor # Declare keys that we're going to use self.keys = keys.KeysDictionary( 'guider_guider', (2, 1), keys.Key( 'cartridge', types.Int(), help='A cartridge ID'), keys.Key( 'fscanId', types.Int(), help='The fscanId identifying a plate scanning'), keys.Key( 'mjd', types.Int(), help='The MJD when a plate was scanned'), keys.Key( 'plate', types.Int(), help='A plugplate ID'), keys.Key( 'guideWavelength', types.Float(), help='The wavelength at which to guide'), keys.Key( 'fibers', types.Int() * (1, None), help='A list of fibers'), keys.Key( 'probe', types.Int(), help='A probe ID, 1-indexed'), keys.Key( 'gprobe', types.Int(), help='A probe ID, 1-indexed'), keys.Key( 'fromProbe', types.Int(), help='A probe ID, 1-indexed'), keys.Key( 'fromGprobe', types.Int(), help='A probe ID, 1-indexed'), keys.Key( 'pointing', types.String(), help='A pointing for the given plugplate'), keys.Key( 'time', types.Float(), help='Exposure time for guider'), keys.Key( 'force', help='Force requested action to happen'), keys.Key( 'gprobes', types.Enum('acquire', 'guide'), help='Type of gprobe'), keys.Key( 'oneExposure', help='Take just one exposure'), keys.Key( 'Kp', types.Float(), help='Proportional gain'), keys.Key( 'Ti', types.Float(), help='Integral time'), keys.Key( 'Td', types.Float(), help='Derivative time'), keys.Key( 'Imax', types.Float(), help='|maximum value of I| (-ve to disable)'), keys.Key( "nfilt", types.Int(), help='number of input readings to filter with.'), keys.Key( "geek", help='Show things that only some of us love'), keys.Key( 'cartfile', types.String(), help='cartridge file'), keys.Key( 'plugfile', types.String(), help='plugmap file'), keys.Key( 'file', types.String(), help='guider file'), keys.Key( 'decenterRA', types.Float(), help='Telescope absolute offset for guiding in RA arcsec'), keys.Key( 'decenterDec', types.Float(), help='Telescope absolute offset for guiding in Dec arcsec'), keys.Key( 'decenterRot', types.Float(), help='Telescope absolute offset for guiding in Rot'), keys.Key( 'ditherPos', types.String(), help='Named MaNGA guider dither position'), keys.Key( 'scale', types.Float(), help='Current scale from \"tcc show scale\"'), keys.Key( 'delta', types.Float(), help='Delta scale (percent)'), keys.Key( 'stack', types.Int(), help='number of itime gcamera integrations to request per exposure.'), keys.Key( 'corrRatio', types.Float(), help='How much refraction correction to apply (0..)'), keys.Key( 'plateType', types.String(), help='Name of the current plateType (survey concatenation)'), keys.Key( 'surveyMode', types.String(), help='Name of the current surveyMode'), keys.Key( 'movieMJD', types.String(), help='The MJD that we want to generate the movie for.'), keys.Key( 'start', types.Int(), help='Guider frame number to start the movie at.'), keys.Key( 'end', types.Int(), help='Guider frame number to end the movie at.'), keys.Key( 'bin', types.Int(), help='bin factor for exposure'), keys.Key( "algorithm", types.String(), help="The fitting algorithm to use."), ) # Declare commands self.vocab = [ ('on', '[<time>] [force] [oneExposure] [<stack>]', self.guideOn), ('off', '', self.guideOff), ('setExpTime', '<time> [<stack>]', self.setExpTime), ('setPID', '(raDec|rot|focus|scale) <Kp> [<Ti>] [<Td>] [<Imax>] [nfilt]', self.setPID), ('resetPID', '[(raDec|rot|focus|scale)]', self.resetPID), ('disable', '<fibers>|<gprobes>', self.disableFibers), ('enable', '<fibers>|<gprobes>', self.enableFibers), ('loadCartridge', '[<cartridge>] [<pointing>] [<plate>] [<mjd>] ' '[<fscanId>] [<guideWavelength>] [force]', self.loadCartridge), ('showCartridge', '', self.showCartridge), ('loadPlateFiles', '<cartfile> <plugfile>', self.loadPlateFiles), ('reprocessFile', '<file>', self.reprocessFile), ('flat', '[<time>]', self.flat), ('dark', '[<time>] [<stack>]', self.dark), ('ping', '', self.ping), ('restart', '', self.restart), ('axes', '(on|off)', self.axes), ('focus', '(on|off)', self.focus), ('scale', '(on|off)', self.scale), ('status', '[geek]', self.status), ('centerUp', '', self.centerUp), ('fk5InFiber', '[<probe>] [<time>]', self.fk5InFiber), ('starInFiber', '[<probe>] [<gprobe>] [<fromProbe>] [<fromGprobe>]', self.starInFiber), ('setScale', '<delta>|<scale>', self.setScale), ('scaleChange', '<delta>|<scale>', self.scaleChange), ('decenter', '(on|off)', self.decenter), ('setDecenter', '[<decenterRA>] [<decenterDec>] [<decenterRot>]', self.setDecenter), ('mangaDither', '<ditherPos>', self.mangaDither), ('setRefractionBalance', '[<corrRatio>] [<plateType>] [<surveyMode>]', self.setRefractionBalance), # noqa ('makeMovie', '[<movieMJD>] <start> <end>', self.makeMovie), ('findstar', '[<time>] [<bin>]', self.ecam_findstar), ('setFittingAlgorithm', '<algorithm>', self.setFittingAlgorithm) ]
import twisted.internet.tksupport import tkinter root = tkinter.Tk() twisted.internet.tksupport.install(root) kvd = CmdKeyVarDispatcher() def showVal(keyVar): print("keyVar %s.%s = %r, isCurrent = %s" % (keyVar.actor, keyVar.name, keyVar.valueList, keyVar.isCurrent)) # scalars keyList = ( protoKeys.Key("StringKey", protoTypes.String()), protoKeys.Key("IntKey", protoTypes.Int()), protoKeys.Key("FloatKey", protoTypes.Float()), protoKeys.Key("BooleanKey", protoTypes.Bool("F", "T")), protoKeys.Key("KeyList", protoTypes.String(), protoTypes.Int()), ) keyVarList = [keyvar.KeyVar("test", key) for key in keyList] for keyVar in keyVarList: keyVar.addCallback(showVal) kvd.addKeyVar(keyVar) # command callback def cmdCall(cmdVar): print("command callback for actor=%s, cmdID=%d, cmdStr=%r, isDone=%s" % \ (cmdVar.actor, cmdVar.cmdID, cmdVar.cmdStr, cmdVar.isDone)) # command cmdVar = keyvar.CmdVar(