Skip to content

Commit

Permalink
Flyer with multiple passes
Browse files Browse the repository at this point in the history
  • Loading branch information
mrakitin authored and SRX Operator committed Jul 28, 2021
1 parent 498c5ef commit d269e54
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 12 deletions.
2 changes: 2 additions & 0 deletions startup/00-base.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,5 @@ def reload(self):
RE.md["beamline_id"] = "SRX"
RE.md["md_version"] = "1.0"

from bluesky.utils import ts_msg_hook
RE.msg_hook = ts_msg_hook
1 change: 1 addition & 0 deletions startup/10-machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ class FlyScanParameters(Device):
id_energy_offset = Cpt(EpicsSignal, write_pv='IDOffset_eV-SP', read_pv='IDOffset_eV-RB', add_prefix=('read_pv', 'write_pv'), put_complete=True)
timing_offset = Cpt(EpicsSignal, write_pv='TriggerOffset-SP', read_pv='TriggerOffset-RB', add_prefix=('read_pv', 'write_pv'), put_complete=True)
trigger_count = Cpt(EpicsSignalRO, 'TriggerCount-RB')
trigger_count_reset = Cpt(EpicsSignal, 'TriggerCount-Reset.PROC')
num_scans = Cpt(EpicsSignal, write_pv='NScans-SP', read_pv='NScans-RB', add_prefix=('read_pv', 'write_pv'), put_complete=True)
current_scan = Cpt(EpicsSignalRO, 'IScan-RB')

Expand Down
108 changes: 96 additions & 12 deletions startup/60-xanes.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ def stage(self):
# Scaler config
self.scaler.count_mode.put(0) # put SIS3820 into single count (not autocount) mode
self.scaler.stop_all.put(1) # stop scaler
self.scaler.nuse_all.put(total_points)
self.scaler.nuse_all.put(2*total_points)
self.scaler.erase_start.put(1)

# TODO: These parameters are for the bpmAD camera, move them to the relevant class in 21-cameras.
Expand Down Expand Up @@ -605,9 +605,25 @@ def kickoff(self, *args, **kwargs):
getattr(self.zebra, self.pulse_cpt).time_units.put('s') # 'Time Units' in CSS

# SYS tab of the Zebra CSS
for out in [1, 2, 3, 4]:
# for out in [1, 2, 3, 4]:
for out in [1, 2, 4]:
getattr(self.zebra, f'output{out}').ttl.addr.put(52) # 'OUTx TTL' in CSS

# TESTING
self.zebra.output3.ttl.addr.put(36)

self.zebra.pulse3.input_addr.put(52)
self.zebra.pulse3.input_edge.put(0)
self.zebra.pulse3.time_units.put('ms')
self.zebra.pulse3.width.put(0.0001)
self.zebra.pulse3.delay.put(0.0)

self.zebra.pulse4.input_addr.put(52)
self.zebra.pulse4.input_edge.put(1)
self.zebra.pulse4.time_units.put('ms')
self.zebra.pulse4.width.put(0.0001)
self.zebra.pulse4.delay.put(0.0)

width_s = self.pulse_width
speed = self.flying_dev.parameters.speed.get()

Expand Down Expand Up @@ -636,6 +652,10 @@ def kickoff(self, *args, **kwargs):
print(f'Enabling fly scan')
self.flying_dev.control.control.put(1)

# Reset the trigger count:
self.flying_dev.parameters.trigger_count_reset.put(1)
ttime.sleep(0.5)

# Main RUN command:
self.flying_dev.control.run.put(1)

Expand All @@ -651,15 +671,19 @@ def callback(value, old_value, **kwargs):
return status

def complete(self, *args, **kwargs):
if self.xs_detectors[0]._staged.value == 'no':
self.stage()

def callback(value, old_value, **kwargs):
print(f'{print_now()} in complete: {old_value} ---> {value}')
if int(round(old_value)) == 1 and int(round(value)) == 0:
if int(round(value)) == int(round(self.flying_dev.parameters.num_triggers.get())):
for xs_det in self.xs_detectors:
xs_det.complete()
return True
return False

status = SubscriptionStatus(self.status, callback)
# status = SubscriptionStatus(self.status, callback)
status = SubscriptionStatus(self.flying_dev.parameters.trigger_count, callback, run=False)
return status

# TODO: Fix the configuration (also for v2).
Expand Down Expand Up @@ -719,16 +743,36 @@ def collect(self, *args, **kwargs):
# raise RuntimeError(f"The number of collected datum ids ({self._datum_ids}) "
# f"does not match the number of triggers ({num_triggers})")

i0_time = self.scaler.mca1.get()
i0 = self.scaler.mca2.get()
im = self.scaler.mca3.get()
it = self.scaler.mca4.get()
ttime.sleep(self.pulse_width + 0.1)

orig_read_attrs = self.scaler.read_attrs
self.scaler.read_attrs = ['mca1', 'mca2', 'mca3', 'mca4']

scaler_mca_data = self.scaler.read()

i0_time = scaler_mca_data[f"{self.scaler.name}_mca1"]['value']
i0 = scaler_mca_data[f"{self.scaler.name}_mca2"]['value']
im = scaler_mca_data[f"{self.scaler.name}_mca3"]['value']
it = scaler_mca_data[f"{self.scaler.name}_mca4"]['value']

self.scaler.read_attrs = orig_read_attrs


print(f"Length of 'i0_time': {len(i0_time)}")
print(f"Length of 'i0' : {len(i0)}")
print(f"Length of 'im' : {len(im)}")
print(f"Length of 'it' : {len(it)}")

i0_time = i0_time[1::2]
i0 = i0[1::2]
im = im[1::2]
it = it[1::2]

print(f"Truncated length of 'i0_time': {len(i0_time)}")
print(f"Truncated length of 'i0' : {len(i0)}")
print(f"Truncated length of 'im' : {len(im)}")
print(f"Truncated length of 'it' : {len(it)}")

if len(i0_time) != len(i0) != len(im) != len(it):
raise RuntimeError(f"Lengths of the collected arrays are not equal")

Expand Down Expand Up @@ -802,10 +846,19 @@ def collect_asset_docs(self):


# Helper functions for quick vis:
def plot_flyer_id_mono_data(uid_or_scanid, e_min, e_max, fname, num_channels=4):
def plot_flyer_id_mono_data(uid_or_scanid, e_min=None, e_max=None, fname=None, root='/home/xf05id1/current_user_data/', num_channels=4):
hdr = db[uid_or_scanid]
tbl = hdr.table()

if (e_min is None):
e_min = xs.channel1.rois.roi01.bin_low.get()
if (e_max is None):
e_max = xs.channel1.rois.roi01.bin_high.get()

if (fname is None):
fname = f"scan{hdr.start['scan_id']}.txt"
fname = root + fname

d = []
for i in range(num_channels):
d.append(np.array(list(hdr.data(f'xs_id_mono_fly_ch{i + 1}')))[:, e_min:e_max].sum(axis=1))
Expand All @@ -824,15 +877,46 @@ def plot_flyer_id_mono_data(uid_or_scanid, e_min, e_max, fname, num_channels=4):
np.savetxt(fname, res.T)
return res

def flying_xas():
def flying_xas(num_passes=1, shutter=True, md=None):
v = flyer_id_mono.flying_dev.parameters.speed.get()
w = flyer_id_mono.flying_dev.parameters.trigger_width.get()
dt = w / v
flyer_id_mono.pulse_width = dt
yield from check_shutters(shutter, 'Open')
yield from bp.fly([flyer_id_mono])
# yield from fly_multiple_passes([flyer_id_mono], num_passes=num_passes,
# md=md, shutter=shutter)
yield from check_shutters(shutter, 'Close')


def fly_multiple_passes(flyers, num_scans=1, md=None, shutter=True):
"""This is a modified version of bp.fly to support multiple passes of the flyer."""

yield from check_shutters(shutter, 'Open')

if md is None:
md = {}
md = get_stock_md(md)
md['scan']['num_scans'] = num_scans
md['scan']['type'] = 'XAS_FLY'

uid = yield from bps.open_run(md)
for flyer in flyers:
yield from bps.mv(flyer.flying_dev.parameters.num_scans, num_scans)
yield from bps.kickoff(flyer, wait=True)
for n in range(num_scans):
print(f"\n\n*** Iteration #{n+1} ***\n")
for flyer in flyers:
yield from bps.complete(flyer, wait=True)
for flyer in flyers:
yield from bps.collect(flyer)
yield from bps.close_run()
yield from check_shutters(shutter, 'Close')
return uid


"""
TODO: All scan directions and modes (uni/bi-directional)
TODO: setup stage_sigs for scaler
TODO: Monitor and LivePlot of data
TODO: All scan directions and modes (uni/bi-directional)
"""
"""

0 comments on commit d269e54

Please sign in to comment.