separate multi-region facility into its own module

This commit is contained in:
2019-01-24 18:17:31 +01:00
committed by gac-x03da
parent c82a8d6091
commit 9270f8e343
2 changed files with 274 additions and 0 deletions
+232
View File
@@ -0,0 +1,232 @@
"""
facility for multi-region scans
usage: import this module into your script and call the run function with the arguments described below.
this file should not be edited for specific scan parameters!
this file should not be called directly!
import MultiRegion
MultiRegion.run(motors, positions, regions, latency=0.0, close_shutter_at_end=True)
motors: list of scan positioners.
positions: discrete list of scan positions.
regions: list of region dictionaries to execute at each scan position.
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
'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 current value)
latency: seconds to wait between positioning command and triggering the detector.
close_shutter_at_end: close beam shutter and turn off analyser at the end of the scan
"""
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']))
if 'slit' not in region:
region['slit'] = ExitSlit.read()
print("region {0}: setting default slit = {1}".format(region['name'], region['slit']))
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 + "/"
self.channel_begin_dataset_name = path + "ScientaChannelBegin"
self.channel_end_dataset_name = path + "ScientaChannelEnd"
self.channel_center_dataset_name = path + "ScientaChannelCenter"
self.pass_energy_dataset_name = path + "ScientaPassEnergy"
self.step_energy_dataset_name = path + "ScientaStepEnergy"
self.step_time_dataset_name = path + "ScientaStepTime"
self.iterations_dataset_name = path + "ScientaIterations"
self.slit_dataset_name = path + "ExitSlit"
create_dataset(self.channel_begin_dataset_name, 'd')
create_dataset(self.channel_end_dataset_name, 'd')
create_dataset(self.channel_center_dataset_name, 'd')
create_dataset(self.pass_energy_dataset_name, 'd')
create_dataset(self.step_energy_dataset_name, 'd')
create_dataset(self.step_time_dataset_name, 'd')
create_dataset(self.iterations_dataset_name, 'd')
create_dataset(self.slit_dataset_name, 'd')
def setup(self):
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)
ephot = Eph.read()
try:
if self.region['cis']:
edelta = ephot - self.ephot_start
else:
edelta = 0.0
except AttributeError:
self.ephot_start = ephot
edelta = 0.0
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)
else:
Scienta.setAcquisitionMode(ch.psi.pshell.epics.Scienta.AcquisitionMode.Swept)
Scienta.lowEnergy.write(elo)
Scienta.highEnergy.write(ehi)
Scienta.stepSize.write(self.region['estep'])
Scienta.setPassEnergy(self.region['epass'])
Scienta.stepTime.write(self.region['tstep'])
Scienta.setIterations(self.region['iter'])
ExitSlit.write(self.region['slit'])
Scienta.update()
if self.region['fixed']:
append_dataset(self.channel_center_dataset_name, elo)
else:
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'])
append_dataset(self.pass_energy_dataset_name, self.region['epass'])
append_dataset(self.step_time_dataset_name, self.region['tstep'])
append_dataset(self.iterations_dataset_name, self.region['iter'])
append_dataset(self.slit_dataset_name, self.region['slit'])
def read(self):
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):
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(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()
vscan(motors, SENSORS, positions, True, latency,False, before_read=wait_beam, after_read = after_readout)
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])
def run(motors, positions, regions, latency=0.0, close_shutter_at_end=True):
"""
see the module description for arguments.
"""
try:
setup_live_plots(regions)
task = fork(update_live_plots)
do_scan(motors, positions, regions, latency)
finally:
if close_shutter_at_end:
after_scan()
+42
View File
@@ -0,0 +1,42 @@
"""
Discrete photon energy scan (vector scan) of multiple spectral regions
"""
import MultiRegion
# scan positioner: Eph = photon energy
MOTORS = [Eph]
# comma-separated discrete list of scan positions
POSITIONS = [600.0, 610.0]
# 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
# '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 current value)
REGION1 = {'name': 'Peak 1', 'elo': 243.0, 'ehi': 253.0, 'estep': 0.1, 'epass': 50, 'tstep': 0.1, 'iter': 1, 'cis': True}
REGION2 = {'name': 'Peak 2', 'elo': 214.0, 'ehi': 219.0, 'estep': 0.1, 'epass': 50, 'tstep': 0.1, 'iter': 2, 'cis': False}
# list of region dictionaries to execute at each scan position
REGIONS = [REGION1, REGION2]
# close beam shutter and turn off analyser at the end of the scan
CLOSE_SHUTTER_AT_END = False
MultiRegion.run(MOTORS, POSITIONS, REGIONS, LATENCY, CLOSE_SHUTTER_AT_END)