def stop_beam(self,result): """ Callback function to stop the beam """ if self.stop_pv.value != 0: printnow('Received stop signal') self._pp.close()
def setLaserDrop(NshotsPerDrop, NshotsOff=1, seq=event, codes=dict(lason=183, lasoff=184)): if NshotsPerDrop < 1: print 'this should be a positive integer!' return seqstep = 0 seq.setstep(seqstep, codes['lason'], 1, fiducial=0, comment='LaserOn') seqstep += 1 for shotNo in range(NshotsOff): seq.setstep(seqstep, codes['lasoff'], 1, fiducial=0, comment='LaserOff') seqstep += 1 for shotNo in range(NshotsPerDrop - 1): seq.setstep(seqstep, codes['lason'], 1, fiducial=0, comment='LaserOn') seqstep += 1 seq.setnsteps(seqstep) seq.update() printnow("... done\n")
def __init__(self, **kwargs): super(EpicsArchMotorsExp, self).__init__(**kwargs) arch_dir = kwargs["arch_dir"] arch_files = kwargs["arch_files"] motors_obj = kwargs.get("motors_obj") use_existing = kwargs.get("use_existing", False) if not isinstance(arch_files, list): arch_files = [arch_files] if not isinstance(motors_obj, list): motors_obj = [motors_obj] self._motors = None other_motors = [] for obj in motors_obj: if isinstance(obj, Motors) and self._motors is None: self._motors = obj continue else: other_motors.append(obj) if self._motors is None: self._motors = Motors() if use_existing: all_motors = [] for m in [self._motors] + other_motors: if isinstance(m, Motors): all_motors.extend(m.all.get_motors()) else: all_motors.extend([ n for n in m.__dict__.values() if isinstance(n, Motor) ]) try: printnow("Importing motors from ") for file in arch_files: printnow(file + "... ") full_path = os.path.join(arch_dir, file) if use_existing: group = self._motors.import_epicsArch( full_path, skip_import=all_motors) else: group = self._motors.import_epicsArch(full_path) self._motors.groups.add("user", *group.get_motors()) user_motors = self._motors.groups.user.get_motors() for motor in user_motors: setattr(self, motor.name, motor) for group in other_motors: if isinstance(group, Motors): group.add(motor, group="user") else: setattr(group, motor.name, motor) print("done") except Exception as exc: print("Importing from epicsArch failed!") print(exc)
def make_ready(self,result): """ Callback function to check a change in the Analog channel """ if self.analog.value < self.ttl_high and not self.latch: printnow('Received TTL Pulse, setting ready flag\n') self.latch = True self.ready_for_row.set() elif self.analog.value > self.ttl_low: self.latch = False
def pre_scan(self, scan): iterscan.Hooks.pre_scan(self, scan) printnow("Moving motor to start position...") scan.to_first_point() scan.wait() print "done." print "Starting daq and beginning delay scan." self.daq.begin(events=self.events, duration=self.duration, use_l3t=self.use_l3t) self.start_timer() self.daq_proc.start() self.timer_thread.start()
def getT(self, printit=False): """ Check which filters are `in` and calculate the transmission for the energy defined with the `setE` command The finding is returned as dictionary """ self.wait() ret = {} ret['1st'] = self.getT1value() ret['3rd'] = self.getT3value() ret['E'] = self.__E ret['E3'] = self.__E3 if printit: printnow(self.status()) return ret
def start_imprints(self, use_daq=False, gasdet_min=-1., configure=True): """ Start imprints with STARTROW signal from Roadrunner for each X-ray pulse - configure: configure event sequencer for single shot pulse picker - gasdet_min: minimum gas detector value (GDET:FEE1:241:ENRC) to start a row [mJ] (default: -1) - use_daq: use daq """ runstr = None istep = 0 self.STOP = 0 if configure: self.free_run(daq=use_daq) env.event.modeOnce() try: printnow('Ready to run') 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: 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)) start_time = time.time() env.event.start() env.event.wait() istep += 1 printnow('Shot {:} taken'.format(istep)) time.sleep(0.01) printnow("Received STOP signal!\n") except KeyboardInterrupt: printnow("\nStopping row runner...") # abort sequencer env.event.stop() self._pp.close() finally: # clear STOP flag self.STOP = 0 if configure: self.stop_freerun(daq=use_daq)
def post_scan(self, scan): with IgnoreKeyboardInterrupt(): try: # Raises AttributeError if proc never started (race condition) self.daq_proc.terminate() except AttributeError: pass try: # Raises RuntimeError if thread never started (race condition) self.timer_thread.join() except RuntimeError: pass printnow("Returning motor to pre-scan position...") iterscan.Hooks.post_scan(self, scan) print "done."
def delay_scan(self, points, events=None, duration=None, use_l3t=False): """ Scan the new delay stage, live. Assumes the daq is configured. Parameters: points: an array of 2 points to scan back and forth between. can also specify a long array to go from first point to second to third, etc., wrapping around to the first events: the number of events to take in the scan. duration: the length of time of the scan in seconds. Either events or duration needs to be specified, but not both. If both are specified, use duration. use_l3t: use the l3t filter or not """ if self.empty_scan.is_scanning(): print "Stopping empty scan..." self.empty_scan.stop() try: print "Configuring daq..." self._daq.feedback.connect() self._daq.configure(events=events, duration=duration, use_l3t=use_l3t) self._daq.write_feedback_pvs([self.motor],[points],0,0) printnow("Initializing delay scan...") in_pipe, out_pipe = mp.Pipe() daq_proc = mp.Process(target=daq_watch_thread, args=(self._daq, out_pipe,)) hooks = DelayScanHooks(in_pipe, self._daq, daq_proc, events, duration, use_l3t) scan = iterscan.IterScan(self.motor, cycle_gen(points, self.motor), hooks) scan.do_print = False print "done." scan.scan() daq_proc.join() except KeyboardInterrupt: pass finally: with IgnoreKeyboardInterrupt(): print "Cleaning up delay scan..." time.sleep(0.5) print "Cleaning EPICS feedback fields..." self._daq.feedback.cleanFields() print "Stopping daq run..." self._daq.endrun() print "Delay scan complete"
def free_run(self, nevents=432000, eventCode=None, daq=True, start=False, beam_rate=30, picker=True, prePP=3, test=False): """ Free run for nevents """ if test: picker_ec = 201 else: picker_ec = self._pp._codes['pp'] motor_ec = self.motor_ec readout_ec = self._pp._codes['daq'] drop_ec = self._pp._codes['drop'] seqstep=0 if not eventCode: eventCode = self.motor_ec env.event.setSyncMarker(beam_rate) env.event.stop() if picker: env.event.setstep(seqstep, env.pp._codes['pp'], prePP,fiducial=0,comment='PulsePicker');seqstep+=1 env.event.setstep(seqstep, env.pp._codes['drop'], 0,fiducial=0,comment='OffEvent');seqstep+=1 env.event.setstep(seqstep, eventCode, 1,fiducial=0,comment='DaqReadout');seqstep+=1 else: env.pp.close() env.event.setstep(seqstep, eventCode, 1,fiducial=0,comment='DaqReadout');seqstep+=1 env.event.setnsteps(seqstep) for i in range(seqstep-20): env.event.setstep(seqstep, 0, 0,fiducial=0,comment=' ');seqstep+=1 env.event.update() printnow("Done with sequence\n") env.event.modeForever() if start: env.event.start() if daq: env.daq.connect() env.daq.begin(nevents)
def new_archive_data(self, pv, time_selection=30, chunk=False): pv = urllib.quote(pv, safe="") url = urlbase.format(pv) startdate, enddate = self._interpret_time_selection(time_selection) url += urlfrom.format(self._date_format(startdate)) url += urlto.format(self._date_format(enddate)) if not chunk: url += nochunk printnow("Connecting to new archive ...") req = urllib2.urlopen(url, timeout=1) printnow(" done\n") printnow("Extracting data from new archive ...") data = json.load(req) t = [ datetime.datetime.fromtimestamp(x["secs"]) for x in data[0]["data"] ] y = [x["val"] for x in data[0]["data"]] printnow(" done\n") return t, y
def old_archive_data(self, pv, time_selection=30): if not self.considerOldArch: print "Not configured to access old archive, must init with hutch." return startdate, enddate = self._interpret_time_selection(time_selection) self._get_channel(pv) printnow("Extracting data from old archive ...") time, data = self._get_timeinterval_values_from_arch( startdate, enddate) printnow(" done\n") if len(time) == 0: printnow("WARNING: No data found for {0}.\n".format(pv)) return time, data
def setT(self, transmission, wait=False, E=None, printit=False, use3rd=False, checkSide=False): """ Determines which filters have to be moved in othe beam to achieve a transmission as close as possible to the requested one. Note : the function moves the filters Note2: use the `setE` command before to choose which energy to use for calculation""" # Check the status of the attenuator stat = self.get_par('Status') if stat != 'OK': warn_str = 'The attenuator is not ready - status is ' + str(stat) printnow(warn_str) return if E is not None: self.setE(E, use3rd=use3rd) elif self.get_par('Eget') == 'Passive' and (abs(self.get_par('E1st') - Pv.get('SIOC:SYS0:ML00:AO627') ) > 0.010): printnow('The current set energy for the fundamental (%.5f) is not the beam energy (%.5f).' %(self.get_par('E1st'), Pv.get('SIOC:SYS0:ML00:AO627') )) if raw_input('Is that intended? (y/n)\n') is 'n': self.setE() if use3rd: self.put_par('Td3rd', transmission, wait=True) time.sleep(0.1) self.wait_par('CalcPend', 'No') # wait for T_CALC record to process floor = self.get_par('T3rd_f') ceiling = self.get_par('T3rd_c') else: self.put_par('Td1st', transmission, wait=True) time.sleep(0.1) self.wait_par('CalcPend', 'No') # wait for T_CALC record to process floor = self.get_par('T1st_f') ceiling = self.get_par('T1st_c') if printit or checkSide: printnow('Possible transmissions are: %.5f (floor) and %.5f (ceiling).' %(floor, ceiling)) if checkSide: if raw_input('Use ceiling or floor? (c/f)\n') is 'c': self.put_par('Go', 3) tval = ceiling else: self.put_par('Go', 2) tval = floor else: if abs(floor - transmission) >= abs(ceiling - transmission): self.put_par('Go', 3) tval = ceiling else: self.put_par('Go', 2) tval = floor # wait for put to happen time.sleep(0.1) if wait: self.wait() if use3rd: self.wait_par('E3rd') # wait for T_CALC record to process tval = self.getT3value() else: self.wait_par('E1st') # wait for T_CALC record to process tval = self.getT1value() if printit or (transmission != 0 and abs((tval-transmission)/transmission)>0.1): printnow('Closest possible transmission of %.3f has been applied\n'%(tval)) return tval
from blutil import config, printnow from blutil.organize import SimpleContainer from experiments import load_exp printnow("Loading active experiment {0}...".format(config.expname)) try: exp_obj = load_exp(config.expname) print "...done!" except Exception, e: print e print "Failed!" exp_obj = SimpleContainer()
def print_data(self, pv, time_selection=30, chunk=False): time, data = self.pv_archive_data(pv, time_selection, chunk) for t, d in zip(time, data): printnow("%s\t%f\n" % (t, d))
def configure_sequencer(self,test=False,readOnMotor=True, addDrop=False): """ Configure the sequencer based on the current set of USER PVS Epics pv inputs that define event sequence: - nstart=CXI:USR:ACC: the number of sync pulses to send before starting xray pulses. - ncells=CXI:USR:CELLS: the number of cells to shoot in a row of the sample holder. - freq=CXI:USR:FREQ: the frequency used for both motor sync triggers and the xray pulses (default: 120 Hz). - ngap=CXI:USR:GAP: gap between windows - nwindows=CXI:USR:WINDOWS number of windows """ nstart=self.ACC ncells=self.CELLS nwindows=self.WINDOWS ngap=self.GAP freq=self.FREQ sample_name=self.CHIP runstr = None # Sequencer set to use burst delay off of next shot self._pp._burstdelay = 0.0008 self._pp._flipflopdelay = 0.0008 if test: picker_ec = 201 else: picker_ec = self._pp._codes['pp'] self.STOP = 0 motor_ec = self.motor_ec readout_ec = self._pp._codes['daq'] drop_ec = self._pp._codes['drop'] latch = False # istep is the daq run 'calibration' step istep = 0 env.event.modeOnce() seqstep = 0 motsync_com = 'MotorSync' readout_com = 'Readout' pp_com = 'PulsePicker' drop_com = 'DroppedShot' if self._base_freq % freq != 0: printnow("Warning: %.1f is not an allowed frequency - choosing closest avaiable!"%freq) pulse_step = int(math.ceil(self._base_freq/freq)) printnow("Configuring sequencer for rows with %d cells at pulse frequency of %.1f Hz ..."%(ncells, self._base_freq/pulse_step)) printnow('***********************************\n') printnow(self.sample_info()) if pulse_step == 1: ## set pulse picker to burst mode #if Pv.get(self._pp._PVname('SE')) != 3: print 'Setting PulsePicker to Burst mode' #Pv.put(self._pp._PVname('RUN_BURSTMODE'),1) self._pp.burst() # adding starting pulses before pulse pickers starts to open for index in range(nstart): env.event.setstep(seqstep, motor_ec, pulse_step,fiducial=0,comment=motsync_com);seqstep+=1 if addDrop: env.event.setstep(seqstep, drop_ec, 0,fiducial=0,comment=drop_com);seqstep+=1 # Repeat for nwindows: for iwindow in range(nwindows): # open pulse picker env.event.setstep(seqstep, picker_ec, 0,fiducial=0,comment=pp_com);seqstep+=1 # add all but the last xray shot for index in range(ncells): # close pulsepicker and read last shot in window if index == ncells-1: env.event.setstep(seqstep, picker_ec, 0,fiducial=0,comment=pp_com);seqstep+=1 env.event.setstep(seqstep, motor_ec, pulse_step,fiducial=0,comment=motsync_com);seqstep+=1 if not readOnMotor: env.event.setstep(seqstep, readout_ec, 0,fiducial=0,comment=readout_com);seqstep+=1 # Skip ngap pulses for each window for igap in range(ngap): env.event.setstep(seqstep, motor_ec, pulse_step,fiducial=0,comment=motsync_com);seqstep+=1 if addDrop: env.event.setstep(seqstep, drop_ec, 0,fiducial=0,comment=drop_com);seqstep+=1 # Provide Motor Sync pulses for deacceleration for index in range(nstart-ngap): env.event.setstep(seqstep, motor_ec, pulse_step,fiducial=0,comment=motsync_com);seqstep+=1 if addDrop: env.event.setstep(seqstep, drop_ec, 0,fiducial=0,comment=drop_com);seqstep+=1 elif pulse_step >= 4: # set pulse picker to flip flop mode if Pv.get(self._pp._PVname('SE')) != 2: print 'Setting PulsePicker to FlipFlop mode' #Pv.put(self._pp._PVname('RUN_FLIPFLOP'),1) self._pp.flipflop() # adding starting MotorSync pulses before pulse pickers starts to open for index in range(nstart): env.event.setstep(seqstep, motor_ec, pulse_step,fiducial=0,comment=motsync_com);seqstep+=1 if addDrop: env.event.setstep(seqstep, drop_ec, 0,fiducial=0,comment=drop_com);seqstep+=1 # start ncell number of flip-flops of the pulse picker pp_open_delay = 1 pp_ff_delay = pulse_step - pp_open_delay for iwindow in range(nwindows): for index in range(ncells): env.event.setstep(seqstep, picker_ec, pp_ff_delay,fiducial=0,comment=pp_com);seqstep+=1 if not readOnMotor: env.event.setstep(seqstep, readout_ec, pp_open_delay,fiducial=0,comment=readout_com);seqstep+=1 else: env.event.setstep(seqstep, drop_ec, pp_open_delay,fiducial=0,comment=drop_com);seqstep+=1 env.event.setstep(seqstep, motor_ec, 0,fiducial=0,comment=motsync_com);seqstep+=1 # Skip ngap pulses for each window for igap in range(ngap): env.event.setstep(seqstep, motor_ec, pulse_step,fiducial=0,comment=motsync_com);seqstep+=1 if addDrop: env.event.setstep(seqstep, drop_ec, 0,fiducial=0,comment=drop_com);seqstep+=1 # Add additional deceleration pulses for MotorSync for index in range(nstart): env.event.setstep(seqstep, motor_ec, pulse_step,fiducial=0,comment=motsync_com);seqstep+=1 if addDrop: env.event.setstep(seqstep, drop_ec, 0,fiducial=0,comment=drop_com);seqstep+=1 else: printnow("\nA frequency choice of %.2f Hz is not allowed in this mode! - Aborting...\n"%freq) return # finalize sequence env.event.setnsteps(seqstep) env.event.update() printnow("Done with sequence\n")
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()
INSTRUMENT = 'CXI' __all__ = [] def export(*names): __all__.extend(names) def warning(text): """Print text to screen in BOLD RED lettering.""" print(estr(text, color="red", type="bold")) printnow("defining lcls_linac...") try: from blinst import linac lcls_linac = linac.Linac() export("lcls_linac") printnow("...done\n") except Exception, exc: lcls_linac = None warning("Error loading lcls_linac!") print exc printnow("defining motors...") try: from blbase import motorsfile motors = motorsfile.Motors() motors.import_epicsArch(config.epicsArch)