def step_info(self, **kwargs): message = Message(quiet=True, **kwargs) for attr in ['ROW', 'ANGLE']: item = self._pvs.get(attr) message('{:18}: {:8} {:6} (pv={:})'.format(item.get('desc'), getattr(self, attr), item.get('units',''), item.get('pv'))) return message
def sample_info(self, **kwargs): message = Message(quiet=True, **kwargs) for attr in ['COMM', 'CHIP', 'TYPE', 'FREQ', 'HORIZONTALPITCH', 'VERTICALPITCH', 'PATT', 'ACC', 'CELLS', 'WINDOWS', 'GAP']: item = self._pvs.get(attr) message('{:18}: {:8} {:6} (pv={:})'.format(item.get('desc'), getattr(self, attr), item.get('units',''), item.get('pv'))) return message
def show_info(self, **kwargs): from psmessage import Message message = Message(quiet=True, **kwargs) if self.alerts or self.warnings: header = '{:15} {:14} {:8} {:22}'.format('detector', 'parameter', 'level', 'error') message(header) message('-' * (len(header))) if self.alerts: for alias, alerts in self.get_alert_info().items(): for attr, alert in alerts.items(): message('{:15} {:14} {:8} {:22}'.format( alias, attr, 'alert', alert)) if self.warnings: for alias, alerts in self.get_warning_info().items(): for attr, alert in alerts.items(): message('{:15} {:14} {:8} {:22}'.format( alias, attr, 'warning', alert)) return message
def start_run(self, use_daq=False, use_steps=True, record=None, test=False, post=True, gasdet_min=-1., readOnMotor=True, addDrop=True, configure=True, safe=False, **kwargs): """ Runs the sequence for a row of samples in a loop until aborted. Each interation of the loop it waits to receive a rising edge signal from the motion controller before starting to play the sequence. Once the sequence is started it sends a continous set of sync triggers to the motion controller at the desired frequency. - gasdet_min: minimum gas detector value (GDET:FEE1:241:ENRC) to start a row [mJ] (default: -1) - use_daq: this controls whether the script will start running the daq and take a calib cycle for each row (default: False). - use_steps: u - test: mode where pulse picker is not used - record: this controls the recording state of the daq (only meaningful if 'use_daq' is set to True). * True: force recording of the run. * False: force off recording of the run. * None: use the option selected in the daq gui (default). - configure: Configure the Sequencer with the current set of PVS """ #### safe=False #### nstart=self.ACC ncells=self.CELLS nwindows=self.WINDOWS ngap=self.GAP freq=self.FREQ sample_name=self.CHIP runstr = None istep = 0 self.STOP = 0 if configure: self.configure_sequencer() self.analog.monitor_start() try: # configure daq if being used if use_daq: env.daq.record = record calibcontrols=[ ('nstart', nstart), ('ncells', ncells), ('nwindows', nwindows), ('freq', freq), ('angle', self.ANGLE), ('row', self.ROW), ('horizontalpitch', self.HORIZONTALPITCH), ('verticalpitch', self.VERTICALPITCH), ('pattern', self.PATT), ] env.daq.configure(controls=calibcontrols,events=0) if not use_steps: env.daq.begin(events=0,controls=calibcontrols) run_num = env.daq.runnumber() if test: runstr = 'Test No Beam' else: runstr = 'Run {:}'.format(env.daq.runnumber()) printnow("if desired setup DAQ & wrote sample_name %s to PV; now waiting for ready signal\n"%sample_name) message = self.sample_info() if safe: printnow("Opening the UM6 shutter...") self.um6_shutter_cmd = 1 while self.um6_shutter_opn != 1: time.sleep(0.01) printnow("done\n") #Start new row, ignore past input triggers self.ready_for_row.clear() printnow('Ready to run') Message('-------------------',append=True) self.STARTROW = 0 time.sleep(0.2) while self.STOP == 0: # Now using epics CXI:USR:STARTROW instead of analog AI if self.STARTROW == 1: try: print "Pontus debug: USE LASER STATUS", self.USELASER if self.USELASER: self.laser_enabled=1 else: self.laser_enabled=0 except: print "Pontus f****d up" self.STARTROW = 0 while self.gasdet_sig < gasdet_min: time.sleep(1.) printnow("Low beam = {:} mJ -- Waiting for beam to return ...\n".format(self.gasdet_sig)) Message("Low beam = {:} mJ -- Waiting for beam to return ...\n".format(self.gasdet_sig), append=True) start_time = time.time() if use_daq and use_steps: calibcontrols=[ ('nstart', nstart), ('ncells', ncells), ('nwindows', nwindows), ('freq', freq), ('angle', self.ANGLE), ('row', self.ROW), ('horizontalpitch', self.HORIZONTALPITCH), ('verticalpitch', self.VERTICALPITCH), ('pattern', self.PATT), ] nEventsRecord = ncells*nwindows if readOnMotor: nEventsRecord = nstart+ncells*nwindows+(nwindows-1)*ngap env.daq.begin(events=nEventsRecord,controls=calibcontrols) #What is this / Why is this here if (time.time()-start_time) < 0.2: time.sleep(0.2-(time.time()-start_time)) if use_daq and use_steps: run_num = env.daq.runnumber() runstr = 'Run {:}'.format(run_num) try: laser_state = 'Laser {:}'.format({0:'Off',1:'On'}.get(self.laser_enabled,'Unknown')) except: laser_state = 'Laser Unknown' print laser_state print runstr self.istep = istep self.runstr = runstr printnow("Starting {:} Step {:}: {:} Row {:}, {:} deg angle ...\n".format(runstr, \ istep, self.CHIP, self.ROW, self.ANGLE)) step_message = "Step {:}: {:} Row {:}, {:} deg angle, {:}".format(istep, \ self.CHIP, self.ROW, self.ANGLE, laser_state) #Clear ready flag self.ready_for_row.clear() env.event.start() if use_daq and use_steps: printnow('Waiting for DAQ end calib cycle') env.daq.wait() printnow('... done\n') printnow('Waiting for Event Sequencer') env.event.wait() self.laser_enabled=0 printnow('... done\n') stop_time = time.time() printnow(" ... Completed in %.2f s\n"%(stop_time-start_time)) Message("{:} -- Completed in {:8.3f} s".format(step_message,stop_time-start_time), append=True) istep += 1 #Do we really need this sleep? time.sleep(0.001) printnow("Received STOP signal!\n") except KeyboardInterrupt: printnow("\nStopping row runner...") # abort sequencer env.event.stop() self._pp.close() finally: #self.seq_state = False # clear STOP flag self.STOP = 0 self.analog.monitor_stop() if safe: printnow("Closing the UM6 shutter...") self.um6_shutter_cmd = 0 while self.um6_shutter_cls != 1: time.sleep(0.01) printnow("done\n") if use_daq: # revert daq record setting to gui control and disconnect #env.daq.wait() env.daq.stop() if runstr and post: Message('{:}: {:} rows'.format(runstr,istep), append=True) message = self.sample_info(append=True) if record: message.post(run_num=run_num) env.daq.record = None env.daq.disconnect()
def banner(ds, base='ds', time0=None): message = Message() ds = getattr(sys.modules['__main__'], base) message.add("*"*80) message.add("") message.add('Data loaded for the psana data_source = {:}'.format(str(ds))) if ds.events: message.add('Total Events = {:}'.format(ds.nevents)) if time0: message.add('Load time = {:5.1f} sec'.format(time.time()-time0)) message.add("") ds.configData.show_info() evt = ds.events.next() message.add("") message.add("*"*80) message.add('{:} is a python friendly (i.e, tab accessible) form of the psana.DataSource.'.format(base)) message.add('Event data is accessible through aliases (psana get and keys methods are also preserved), e.g.,') message.add("") message.add('In [1]: evt = {:}.events.next()'.format(base)) message.add('In [2]: evt.Evr.eventCodes') message.add('Out[2]: {:}'.format(str(evt.Evr.eventCodes))) message.add("") message.add("The current event is also available in the {:}.events object, e.g.,".format(base)) message.add("") message.add('In [3]: ds.events.current.Evr.eventCodes') message.add('Out[3]: {:}'.format(str(ds.events.current.Evr.eventCodes))) message.add("") if ds.data_source.smd: message.add('For offline data (using smd small data access), one can also iterate through "calib cycle" steps. e.g.,') message.add("In [4]: for events in {:}.steps:".format(base)) message.add(" for evt in events:") message.add(" # Do something with events...") message.add("") message.add("*"*80) return message