""" Line/vector/area/holo scan of multiple spectral regions save this script into your script/user folder before editing! usage: 1. uncomment one of the MOTORS lines. add another line if necessary. 2. uncomment one of the scan blocks and adjust the parameters. add another block if necessary. 3. declare the regions. 4. add the regions to the REGIONS list. 5. run the script. """ # dummy scan (time series) #MOTORS = [dummy] # photon energy scan (do not include 'ephot' in regions in this case!) #MOTORS = [Eph] # phi scan #MOTORS = [ManipulatorPhi] # holo scan MOTORS = (ManipulatorPhi, ManipulatorTheta) # 2D YZ scan #MOTORS = [ManipulatorY, ManipulatorZ] # line scan [start, stop, step] #POSITIONS = [0., 10., 0.5] #SCAN = 'lscan' # vector scan [pos1, pos2, pos3, ...] #POSITIONS = [200., 300., 400., 500.] #SCAN = 'vscan' # area scan [(start1, start2), (stop1, stop2), (step1, step2)] # corresponding to (positioner1, positioner2) #POSITIONS = [(-1., 114.), (+1., 116.), (20, 20)] #ZIGZAG = True #SCAN = 'ascan' # holo scan #PHI_RANGE = (-170.0, 170.0) # (tuple (min, max)) PHI_RANGE = (-160.0, 160.0) # (tuple (min, max)) THETA_RANGE = (-9.5, 80.5) # (tuple (min, max)) STEPS = (40.0, 1.0) # (tuple (phi, theta)) ZIGZAG = True POSITIONS = [(PHI_RANGE[0], THETA_RANGE[0]), (PHI_RANGE[1], THETA_RANGE[1]), STEPS] SCAN = 'ascan' # seconds to wait between positioning command and triggering the detector LATENCY = 0.0 # region setup # # for each region, define a python dictionary with the following items. # optional items can be left unspecified and will default to the indicated values. # for swept mode, include 'elo', 'ehi', 'estep', 'iter' values, but do not include 'efix'. # for fixed mode, include 'efix' value, but do not include 'elo', 'ehi', 'estep', 'iter'. # # 'name': user-specific name of the region (for graph title and RegionName attribute in data file) # 'elo': lower kinetic energy boundary of the spectrum # 'ehi': upper kinetic energy boundary of the spectrum # 'estep': energy step size # 'efix': center kinetic energy in fixed mode # 'epass': pass energy # 'ephot': photon energy (default: unchanged) # 'tstep': dwell time in seconds # 'iter': number of iterations/sweeps (default 1) # 'cis': True = constant initial state (photoemission line), False = constant final state (Auger peak), (default False) # 'slit': exit slit (default: unchanged) REGION1 = {'name': 'Tb 4d', 'elo': 892.5, 'ehi': 899.0, 'estep': 0.1, 'epass': 50., 'tstep': 0.8, 'iter': 1, 'cis': False} REGION2 = {'name': 'Au 4f', 'efix': 957.2, 'epass': 20., 'tstep': 0.8, 'iter': 1, 'cis': False} # list of region dictionaries to execute at each scan position REGIONS = [REGION1, REGION2] #REGIONS = [REGION1] # close beam shutter and turn off analyser at the end of the scan CLOSE_SHUTTER_AT_END = True # --- DO NOT EDIT BELOW THIS LINE! --- set_exec_pars(keep=False) set_exec_pars(compression=True) def check_region(region): """ check region dictionary items and apply defaults where necessary """ region['fixed'] = 'efix' in region if region['fixed']: region['elo'] = region['efix'] region['ehi'] = region['efix'] if 'iter' not in region: region['iter'] = 1 print("region {0}: setting default iter = {1}".format(region['name'], region['iter'])) if 'cis' not in region: region['cis'] = False print("region {0}: setting default cis = {1}".format(region['name'], region['cis'])) class SpectrumReader(ReadonlyRegisterBase, ReadonlyRegisterArray): def initialize(self): #super(SpectrumReader, self).initialize() self.scan_index = -1 def create_datasets(self): path = get_exec_pars().scanPath + self.region_name + "/" if self.region['fixed']: self.channel_center_dataset_name = path + "ScientaChannelCenter" create_dataset(self.channel_center_dataset_name, 'd') else: self.channel_begin_dataset_name = path + "ScientaChannelBegin" self.channel_end_dataset_name = path + "ScientaChannelEnd" self.step_energy_dataset_name = path + "ScientaStepEnergy" create_dataset(self.channel_begin_dataset_name, 'd') create_dataset(self.channel_end_dataset_name, 'd') create_dataset(self.step_energy_dataset_name, 'd') if 'epass' in self.region: self.pass_energy_dataset_name = path + "ScientaPassEnergy" create_dataset(self.pass_energy_dataset_name, 'd') if 'tstep' in self.region: self.step_time_dataset_name = path + "ScientaStepTime" create_dataset(self.step_time_dataset_name, 'd') if 'iter' in self.region: self.iterations_dataset_name = path + "ScientaIterations" create_dataset(self.iterations_dataset_name, 'd') if 'slit' in self.region: self.slit_dataset_name = path + "ExitSlit" create_dataset(self.slit_dataset_name, 'd') def setup(self): # print("spectrum.setup") if self.scan_index != get_exec_pars().index: self.scan_index = get_exec_pars().index self.create_datasets() if self.region_index == 0: print "scan {0}".format(self.scan_index) print "scan {0}, region {1}".format(self.scan_index, self.region_index) edelta = 0.0 try: ephot = self.region['ephot'] Eph.move(ephot) except KeyError: ephot = Eph.take(100) if isinstance(ephot, float) and ephot > 0.: try: if self.region['cis']: edelta = ephot - self.ephot_start except AttributeError: self.ephot_start = ephot elo = self.region['elo'] + edelta ehi = self.region['ehi'] + edelta if self.region['fixed']: Scienta.setAcquisitionMode(ch.psi.pshell.epics.Scienta.AcquisitionMode.Fixed) Scienta.centerEnergy.write(elo) append_dataset(self.channel_center_dataset_name, elo) else: Scienta.setAcquisitionMode(ch.psi.pshell.epics.Scienta.AcquisitionMode.Swept) Scienta.lowEnergy.write(elo) Scienta.highEnergy.write(ehi) Scienta.stepSize.write(self.region['estep']) append_dataset(self.channel_begin_dataset_name, elo) append_dataset(self.channel_end_dataset_name, ehi) append_dataset(self.step_energy_dataset_name, self.region['estep']) try: Scienta.setPassEnergy(int(self.region['epass'])) append_dataset(self.pass_energy_dataset_name, self.region['epass']) except KeyError: pass try: Scienta.stepTime.write(self.region['tstep']) append_dataset(self.step_time_dataset_name, self.region['tstep']) except KeyError: pass try: Scienta.setIterations(self.region['iter']) append_dataset(self.iterations_dataset_name, self.region['iter']) except KeyError: pass try: ExitSlit.write(self.region['slit']) append_dataset(self.slit_dataset_name, self.region['slit']) except KeyError: pass Scienta.update() def read(self): # print("spectrum.read") global current_region_index current_region_index = self.region_index self.setup() print("Acquiring region {0}.".format(self.region['name'])) trig_scienta() time.sleep(0.5) sp = Scienta.getSpectrum().read() return sp def getSize(self): if self.region['fixed']: nx = 992 else: nx = int((self.region['ehi'] - self.region['elo']) / self.region['estep']) + 1 return nx class ImageReader(ReadonlyRegisterBase, ReadonlyRegisterMatrix): def read(self): # print("image.read") return Scienta.getDataMatrix().read() def getWidth(self): if self.region['fixed']: nx = 992 else: nx = int((self.region['ehi'] - self.region['elo']) / self.region['estep']) + 1 return nx def getHeight(self): ny = Scienta.slices.read() return ny def setup_live_plots(regions): global live_plots global current_region_index names = [region['name'] for region in regions] live_plots = plot(None, names, title="Live Spectra") current_region_index = 0 def update_live_plots(): global live_plots global current_region_index try: while get_context().state.running: y = Scienta.spectrum.take(100) x = Scienta.spectrumX try: series = live_plots[current_region_index].getSeries(0) series.setData(x, y) except IndexError: pass time.sleep(1.0) finally: print "Stopping live spectra" def do_scan(scan, motors, positions, regions, latency): global SENSORS SENSORS = [] for (index, region) in enumerate(regions): check_region(region) reader = SpectrumReader() reader.region_index = index reader.region_name = "region{0}".format(index + 1) reader.region = region reader.initialize() set_device_alias(reader, reader.region_name + "/ScientaSpectrum") SENSORS.append(reader) image = ImageReader() image.region_index = index image.region = region image.initialize() set_device_alias(image, reader.region_name + "/ScientaImage") SENSORS.append(image) SENSORS.append(SampleCurrent) SENSORS.append(RefCurrent) adjust_sensors() set_adc_averaging() if scan == 'ascan': ascan(motors, SENSORS, positions[0], positions[1], positions[2], latency, False, zigzag = True, before_read=wait_beam, after_read = after_readout) elif scan == 'lscan': lscan(motors, SENSORS, positions[0], positions[1], positions[2], latency, False, before_read=wait_beam, after_read = after_readout) elif scan == 'vscan': vscan(motors, SENSORS, positions, True, latency,False, before_read=wait_beam, after_read = after_readout) else: print('unknown scan mode {}'.format(scan)) for (index, region) in enumerate(regions): set_attribute(get_exec_pars().scanPath + "region{0}/ScientaSpectrum".format(index + 1), "RegionName", region['name']) set_attribute(get_exec_pars().scanPath + "region{0}/ScientaImage".format(index + 1), "RegionName", region['name']) set_attribute(get_exec_pars().scanPath, "Regions", [region['name'] for region in regions]) try: setup_live_plots(REGIONS) task = fork(update_live_plots) do_scan(SCAN, MOTORS, POSITIONS, REGIONS, LATENCY) finally: if CLOSE_SHUTTER_AT_END: after_scan()