From b4a99d853ced3b5f66e33922d9683f2d22e55bba Mon Sep 17 00:00:00 2001 From: Dan Allan Date: Thu, 13 Aug 2020 14:18:33 -0400 Subject: [PATCH 1/4] Restage to allow variable sized chunks. --- startup/98-user_scan.py | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/startup/98-user_scan.py b/startup/98-user_scan.py index 361e8fc..e75e1c6 100755 --- a/startup/98-user_scan.py +++ b/startup/98-user_scan.py @@ -790,7 +790,9 @@ def fly_scan2( yield from _set_rotation_speed(rs=rs) print("set rotation speed: {} deg/sec".format(rs)) - @stage_decorator(list(detectors) + motor) + # We manually stage the Andor detector below. See there for why.... + # Stage everything else here in the usual way. + @stage_decorator([ic3, motor]) @bpp.monitor_during_decorator([zps.pi_r]) @run_decorator(md=_md) def fly_inner_scan(): @@ -799,6 +801,21 @@ def fly_inner_scan(): yield from mv(flt, 1) yield from mv(flt, 1) yield from abs_set(Andor.cam.num_images, chunk_size, wait=True) + + # Manually stage the Andor. This creates a Resource document that + # continas the path to the HDF5 file where the detector writes. It also + # encodes the so-called 'frame_per_point' which here is what this plan + # calls chunk_size. The chunk_size CANNOT BE CHANGED later in the scan + # unless we unstage and re-stage the detector and generate a new + # Resource document. + + # This approach imposes some unfortunate overhead (closing the HDF5 + # file, opening a new one, going through all the steps to set the Area + # Detector's filepath PV, etc.). A better approach has been sketched + # in https://github.com/bluesky/area-detector-handlers/pull/11. It + # allows a single HDF5 file to contain multiple chunk_sizes. + + yield from bps.stage(Andor) yield from bps.sleep(1) # open shutter, tomo_images @@ -809,11 +826,17 @@ def fly_inner_scan(): yield from bps.sleep(2) while not status.done: yield from trigger_and_read(list(detectors) + motor) - + # bkg images print("\nTaking background images...") yield from _set_rotation_speed(rs=rot_back_velo) yield from abs_set(Andor.cam.num_images, 20, wait=True) + + # Now that the new chunk_size has been set (20) create a new Resource + # document by unstage and re-staging the detector. + yield from bps.unstage(Andor) + yield from bps.stage(Andor) + yield from bps.sleep(1) yield from _take_bkg_image( motor_x_out, @@ -831,6 +854,8 @@ def fly_inner_scan(): yield from _close_shutter(simu=simu) print("\nshutter closed, taking dark images...") yield from _take_dark_image(detectors, motor, num_dark=1, simu=simu) + + yield from bps.unstage(Andor) # restore fliters yield from _move_sample_in( From 826fd0fb1e853a731aed20caea29bda39745367f Mon Sep 17 00:00:00 2001 From: Dan Allan Date: Thu, 13 Aug 2020 19:43:45 -0400 Subject: [PATCH 2/4] 'motor' was a list of motors. Call it 'motors' for clarity. --- startup/98-user_scan.py | 66 ++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/startup/98-user_scan.py b/startup/98-user_scan.py index e75e1c6..5c11620 100755 --- a/startup/98-user_scan.py +++ b/startup/98-user_scan.py @@ -268,7 +268,7 @@ def user_fly_scan( motor_r_out = motor_r_ini + out_r """ motor_r_ini = zps.pi_r.position - motor = [zps.sx, zps.sy, zps.sz, zps.pi_r, zps.pi_x] + motors = [zps.sx, zps.sy, zps.sz, zps.pi_r, zps.pi_x] detectors = [Andor, ic3] offset_angle = -2.0 * rs @@ -277,7 +277,7 @@ def user_fly_scan( # target_rot_angle = current_rot_angle + relative_rot_angle _md = { "detectors": ["Andor"], - "motors": [mot.name for mot in motor], + "motors": [mot.name for mot in motors], "XEng": XEng.position, "ion_chamber": ic3.name, "plan_args": { @@ -312,13 +312,13 @@ def user_fly_scan( print("set rotation speed: {} deg/sec".format(rs)) - @stage_decorator(list(detectors) + motor) + @stage_decorator(list(detectors) + motors) @bpp.monitor_during_decorator([zps.pi_r]) @run_decorator(md=_md) def inner_scan(): # close shutter, dark images: numer=chunk_size (e.g.20) print("\nshutter closed, taking dark images...") - yield from _take_dark_image(detectors, motor, num_dark=1, simu=simu) + yield from _take_dark_image(detectors, motors, num_dark=1, simu=simu) yield from mv(zps.pi_x, 0) yield from mv(zps.pi_r, -50) @@ -330,7 +330,7 @@ def inner_scan(): status = yield from abs_set(zps.pi_r, 50, wait=False) yield from bps.sleep(2) while not status.done: - yield from trigger_and_read(list(detectors) + motor) + yield from trigger_and_read(list(detectors) + motors) # bkg images print("\nTaking background images...") yield from _set_rotation_speed(rs=30) @@ -338,7 +338,7 @@ def inner_scan(): yield from mv(zps.pi_x, 12) yield from mv(zps.pi_r, 70) - yield from trigger_and_read(list(detectors) + motor) + yield from trigger_and_read(list(detectors) + motors) yield from _close_shutter(simu=simu) yield from mv(zps.pi_r, 0) @@ -728,7 +728,7 @@ def fly_scan2( motor_z_out = out_z if not (out_z is None) else motor_z_ini motor_r_out = out_r if not (out_r is None) else motor_r_ini - motor = [zps.sx, zps.sy, zps.sz, zps.pi_r] + motors = [zps.sx, zps.sy, zps.sz, zps.pi_r] detectors = [Andor, ic3] offset_angle = -2 * rs @@ -737,7 +737,7 @@ def fly_scan2( target_rot_angle = current_rot_angle + relative_rot_angle _md = { "detectors": ["Andor"], - "motors": [mot.name for mot in motor], + "motors": [mot.name for mot in motors], "XEng": XEng.position, "ion_chamber": ic3.name, "plan_args": { @@ -792,7 +792,7 @@ def fly_scan2( # We manually stage the Andor detector below. See there for why.... # Stage everything else here in the usual way. - @stage_decorator([ic3, motor]) + @stage_decorator([ic3] + motors]) @bpp.monitor_during_decorator([zps.pi_r]) @run_decorator(md=_md) def fly_inner_scan(): @@ -825,7 +825,7 @@ def fly_inner_scan(): status = yield from abs_set(zps.pi_r, target_rot_angle, wait=False) yield from bps.sleep(2) while not status.done: - yield from trigger_and_read(list(detectors) + motor) + yield from trigger_and_read(list(detectors) + motors) # bkg images print("\nTaking background images...") @@ -844,7 +844,7 @@ def fly_inner_scan(): motor_z_out, motor_r_out, detectors, - motor, + motors, num_bkg=1, simu=False, traditional_sequence_flag=rot_first_flag, @@ -853,7 +853,7 @@ def fly_inner_scan(): # dark images yield from _close_shutter(simu=simu) print("\nshutter closed, taking dark images...") - yield from _take_dark_image(detectors, motor, num_dark=1, simu=simu) + yield from _take_dark_image(detectors, motors, num_dark=1, simu=simu) yield from bps.unstage(Andor) @@ -911,7 +911,7 @@ def dummy_scan( exposure_time=0.1, motor_z_out = out_z if not (out_z is None) else motor_z_ini motor_r_out = out_r if not (out_r is None) else motor_r_ini - motor = [zps.sx, zps.sy, zps.sz, zps.pi_r] + motors = [zps.sx, zps.sy, zps.sz, zps.pi_r] detectors = [Andor, ic3] offset_angle = -2 * rs @@ -930,7 +930,7 @@ def dummy_scan( exposure_time=0.1, yield from _set_rotation_speed(rs=rs) print("set rotation speed: {} deg/sec".format(rs)) - @stage_decorator(motor) + @stage_decorator(motors) @bpp.monitor_during_decorator([zps.pi_r]) @run_decorator(md=_md) def fly_inner_scan(): @@ -969,12 +969,12 @@ def radiographic_record(exp_t=0.1, period=0.1, t_span=10, stop=True, motor_z_out = out_z if not (out_z is None) else motor_z_ini motor_r_out = out_r if not (out_r is None) else motor_r_ini - motor = [zps.sx, zps.sy, zps.sz, zps.pi_r] + motors = [zps.sx, zps.sy, zps.sz, zps.pi_r] detectors = [Andor, ic3] _md = { "detectors": ["Andor"], -# "motors": [mot.name for mot in motor], +# "motors": [mot.name for mot in motors], "XEng": XEng.position, "ion_chamber": ic3.name, "plan_args": { @@ -2232,7 +2232,7 @@ def user_fly_scan( motor_z_out = out_z if out_z else motor_z_ini motor_r_out = out_r if out_r else motor_r_ini - motor = [zps.sx, zps.sy, zps.sz, zps.pi_r] + motors = [zps.sx, zps.sy, zps.sz, zps.pi_r] detectors = [Andor, ic3] offset_angle = -0.5 * rs @@ -2241,7 +2241,7 @@ def user_fly_scan( target_rot_angle = current_rot_angle + relative_rot_angle _md = { "detectors": ["Andor"], - "motors": [mot.name for mot in motor], + "motors": [mot.name for mot in motors], "XEng": XEng.position, "ion_chamber": ic3.name, "plan_args": { @@ -2284,7 +2284,7 @@ def user_fly_scan( yield from _set_rotation_speed(rs=rs) print("set rotation speed: {} deg/sec".format(rs)) - @stage_decorator(list(detectors) + motor) + @stage_decorator(list(detectors) + motors) @bpp.monitor_during_decorator([zps.pi_r]) @run_decorator(md=_md) def fly_inner_scan(): @@ -2293,7 +2293,7 @@ def fly_inner_scan(): yield from _set_andor_param( exposure_time=exposure_time, period=period, chunk_size=20 ) - yield from _take_dark_image(detectors, motor, num_dark=1, simu=simu) + yield from _take_dark_image(detectors, motors, num_dark=1, simu=simu) yield from bps.sleep(1) yield from _set_andor_param( exposure_time=exposure_time, period=period, chunk_size=chunk_size @@ -2306,7 +2306,7 @@ def fly_inner_scan(): status = yield from abs_set(zps.pi_r, target_rot_angle, wait=False) yield from bps.sleep(1) while not status.done: - yield from trigger_and_read(list(detectors) + motor) + yield from trigger_and_read(list(detectors) + motors) # bkg images print("\nTaking background images...") yield from _set_rotation_speed(rs=30) @@ -2324,7 +2324,7 @@ def fly_inner_scan(): motor_z_out, motor_r_out, detectors, - motor, + motors, num_bkg=1, simu=False, traditional_sequence_flag=traditional_sequence_flag, @@ -2368,7 +2368,7 @@ def user_fly_only( motor_z_ini = zps.sz.position motor_r_ini = zps.pi_r.position - motor = [zps.sx, zps.sy, zps.sz, zps.pi_r] + motors = [zps.sx, zps.sy, zps.sz, zps.pi_r] detectors = [Andor, ic3] # offset_angle = 0 #-0.5 * rs * np.sign(relative_rot_angle) @@ -2377,7 +2377,7 @@ def user_fly_only( target_rot_angle = end_rot_angle _md = { "detectors": ["Andor"], - "motors": [mot.name for mot in motor], + "motors": [mot.name for mot in motors], "XEng": XEng.position, "ion_chamber": ic3.name, "plan_args": { @@ -2415,14 +2415,14 @@ def user_fly_only( yield from _set_rotation_speed(rs=rs) print("set rotation speed: {} deg/sec".format(rs)) - @stage_decorator(list(detectors) + motor) + @stage_decorator(list(detectors) + motors) @bpp.monitor_during_decorator([zps.pi_r]) @run_decorator(md=_md) def fly_inner_scan(): yield from _open_shutter(simu=simu) status = yield from abs_set(zps.pi_r, target_rot_angle, wait=False) while not status.done: - yield from trigger_and_read(list(detectors) + motor) + yield from trigger_and_read(list(detectors) + motors) uid = yield from fly_inner_scan() yield from mv(Andor.cam.image_mode, 1) @@ -2456,7 +2456,7 @@ def user_dark_only(exposure_time=0.1, chunk_size=20, note="", simu=False, md=Non global ZONE_PLATE period = exposure_time # default to exposure time for backgrounds detectors = [Andor, ic3] - motor = [] + motors = [] _md = { "detectors": ["Andor"], @@ -2490,13 +2490,13 @@ def user_dark_only(exposure_time=0.1, chunk_size=20, note="", simu=False, md=Non exposure_time=exposure_time, period=period, chunk_size=chunk_size ) - @stage_decorator(list(detectors) + motor) + @stage_decorator(list(detectors) + motors) @run_decorator(md=_md) def inner_scan(): yield from _set_andor_param( exposure_time=exposure_time, period=period, chunk_size=chunk_size ) - yield from _take_dark_image(detectors, motor, num_dark=1, simu=simu) + yield from _take_dark_image(detectors, motors, num_dark=1, simu=simu) uid = yield from inner_scan() yield from mv(Andor.cam.image_mode, 1) @@ -2572,14 +2572,14 @@ def user_bkg_only( motor_z_out = out_z if out_z else motor_z_ini motor_r_out = out_r if out_r else motor_r_ini - motor = [zps.sx, zps.sy, zps.sz, zps.pi_r] + motors = [zps.sx, zps.sy, zps.sz, zps.pi_r] detectors = [Andor, ic3] current_rot_angle = zps.pi_r.position _md = { "detectors": ["Andor"], - "motors": [mot.name for mot in motor], + "motors": [mot.name for mot in motors], "XEng": XEng.position, "ion_chamber": ic3.name, "plan_args": { @@ -2614,7 +2614,7 @@ def user_bkg_only( # yield from _set_andor_param(exposure_time=exposure_time, period=period, chunk_size=chunk_size) - @stage_decorator(list(detectors) + motor) + @stage_decorator(list(detectors) + motors) @bpp.monitor_during_decorator([zps.pi_r]) @run_decorator(md=_md) def fly_inner_scan(): @@ -2628,7 +2628,7 @@ def fly_inner_scan(): motor_z_out, motor_r_out, detectors, - motor, + motors, num_bkg=1, simu=False, traditional_sequence_flag=traditional_sequence_flag, From 5e7341471a7cb33beff91485243d48aa6986461e Mon Sep 17 00:00:00 2001 From: Dan Allan Date: Thu, 13 Aug 2020 21:07:44 -0400 Subject: [PATCH 3/4] Fix typo in comment Co-authored-by: Maksim Rakitin --- startup/98-user_scan.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/startup/98-user_scan.py b/startup/98-user_scan.py index 5c11620..1b04df3 100755 --- a/startup/98-user_scan.py +++ b/startup/98-user_scan.py @@ -803,7 +803,7 @@ def fly_inner_scan(): yield from abs_set(Andor.cam.num_images, chunk_size, wait=True) # Manually stage the Andor. This creates a Resource document that - # continas the path to the HDF5 file where the detector writes. It also + # contains the path to the HDF5 file where the detector writes. It also # encodes the so-called 'frame_per_point' which here is what this plan # calls chunk_size. The chunk_size CANNOT BE CHANGED later in the scan # unless we unstage and re-stage the detector and generate a new @@ -3019,4 +3019,3 @@ def ming(): - From 015c135c11652f75d25b78615e80390d37bff95d Mon Sep 17 00:00:00 2001 From: FXI Operator Date: Mon, 24 Aug 2020 12:36:59 -0400 Subject: [PATCH 4/4] updated at 20200824 --- startup/10-area-detector.py | 85 ++- startup/11-txm_motor.py | 5 +- startup/40-scans.py | 262 ++++---- startup/42-scans_other.py | 37 +- startup/60-gen_pdf.py | 15 +- startup/91-functions.py | 315 ++++------ startup/92-run_function_at_start.py | 5 + startup/93-load_scan.py | 589 +++++++++++++++--- startup/94-tomo_recon.py | 4 +- startup/98-user_scan.py | 907 +++++++++++----------------- startup/99-umacro.py | 30 +- startup/calib_new.csv | 75 +-- 12 files changed, 1313 insertions(+), 1016 deletions(-) create mode 100755 startup/92-run_function_at_start.py mode change 100644 => 100755 startup/calib_new.csv diff --git a/startup/10-area-detector.py b/startup/10-area-detector.py index 4397640..f062ca1 100755 --- a/startup/10-area-detector.py +++ b/startup/10-area-detector.py @@ -1,30 +1,40 @@ -from ophyd import Component as Cpt -from ophyd.areadetector.filestore_mixins import FileStoreHDF5IterativeWrite +import itertools + +from ophyd import Component as Cpt, Signal +from ophyd.areadetector.filestore_mixins import ( + FileStoreHDF5IterativeWrite, + resource_factory, +) +from pathlib import PurePath from ophyd import EpicsSignal, AreaDetector from ophyd import ( ImagePlugin, - StatsPlugin, TransformPlugin, ROIPlugin, HDF5Plugin, ProcessPlugin, ) -from ophyd.areadetector.plugins import HDF5Plugin, ProcessPlugin -from ophyd.areadetector.filestore_mixins import FileStoreHDF5IterativeWrite -from ophyd.areadetector.trigger_mixins import ( - TriggerBase, - ADTriggerStatus, - SingleTrigger, -) -from ophyd import Component as Cpt, Device, EpicsSignal, EpicsSignalRO +from ophyd.areadetector.trigger_mixins import SingleTrigger + from ophyd.areadetector.cam import AreaDetectorCam from ophyd.areadetector.detectors import DetectorBase -from ophyd.device import Staged -import time as ttime from nslsii.ad33 import SingleTriggerV33, StatsPluginV33, CamV33Mixin +class ExternalFileReference(Signal): + """ + A pure software signal where a Device can stash a datum_id + """ + def __init__(self, *args, shape, **kwargs): + super().__init__(*args, **kwargs) + self.shape = shape + + def describe(self): + res = super().describe() + res[self.name].update(dict(external="FILESTORE:", dtype="array", shape=self.shape)) + return res + class AndorCam(CamV33Mixin, AreaDetectorCam): def __init__(self, *args, **kwargs): AreaDetectorCam.__init__(self, *args, **kwargs) @@ -43,6 +53,17 @@ def ensure_nonblocking(self): class HDF5PluginWithFileStore(HDF5Plugin, FileStoreHDF5IterativeWrite): # AD v2.2.0 (at least) does not have this. It is present in v1.9.1. file_number_sync = None + time_stamp = Cpt(ExternalFileReference, value="", kind="normal", shape=[]) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._ts_datum_factory = None + self._ts_resource_uid = "" + self._ts_counter = None + + def stage(self): + self._ts_counter = itertools.count() + return super().stage() def get_frames_per_point(self): return self.parent.cam.num_images.get() @@ -52,6 +73,41 @@ def make_filename(self): self._ret = super().make_filename() return self._ret + def _generate_resource(self, resource_kwargs): + # don't re-write the "normal" code path .... yet + super()._generate_resource(resource_kwargs) + fn = PurePath(self._fn).relative_to(self.reg_root) + + # Update the shape that describe() will report. + self.time_stamp.shape = [self.get_frames_per_point()] + + resource, self._ts_datum_factory = resource_factory( + spec="AD_HDF5_TS", + root=str(self.reg_root), + resource_path=str(fn), + resource_kwargs=resource_kwargs, + path_semantics=self.path_semantics, + ) + + self._ts_resource_uid = resource["uid"] + self._asset_docs_cache.append(("resource", resource)) + + def generate_datum(self, key, timestamp, datum_kwargs): + # again, don't re-work the normal code path... yet + ret = super().generate_datum(key, timestamp, datum_kwargs) + datum_kwargs = datum_kwargs or {} + datum_kwargs.update({'point_number': next(self._ts_counter)}) + # make the timestamp datum, in this case we know they match + datum = self._ts_datum_factory(datum_kwargs) + datum_id = datum["datum_id"] + + # stash so that we can collect later + self._asset_docs_cache.append(("datum", datum)) + # put in the soft-signal so it get auto-read later + self.time_stamp.put(datum_id) + # yes, just return one to avoid breaking the API + return ret + class AndorKlass(SingleTriggerV33, DetectorBase): cam = Cpt(AndorCam, "cam1:") @@ -249,10 +305,11 @@ def resume(self): Andor.read_attrs = ["hdf5", "stats1"] Andor.stats1.read_attrs = ["total"] # Andor.stats5.read_attrs = ['total'] -Andor.hdf5.read_attrs = [] +Andor.hdf5.read_attrs = ["time_stamp"] Andor.stage_sigs["cam.image_mode"] = 0 for k in ("image", "stats1", "trans1", "roi1", "proc1"): getattr(Andor, k).ensure_nonblocking() +Andor.hdf5.time_stamp.name = 'Andor_timestamps' vlm = Manta("XF:18IDB-BI{VLM:1}", name="vlm") diff --git a/startup/11-txm_motor.py b/startup/11-txm_motor.py index 1031902..eb46842 100755 --- a/startup/11-txm_motor.py +++ b/startup/11-txm_motor.py @@ -80,6 +80,9 @@ class TXM_SSA(Device): clens = Condenser("XF:18IDB-OP", name="clens") aper = Aperture("XF:18IDB-OP", name="aper") zp = Zoneplate("XF:18IDB-OP", name="zp") + +zp.wait_for_connection() + phase_ring = PhaseRing("XF:18IDB-OP", name="phase_ring") betr = BetrandLens("XF:18IDB-OP", name="betr") zps = TXMSampleStage("XF:18IDB-OP", name="zps") @@ -108,7 +111,7 @@ class TXM_SSA(Device): filter3 = EpicsSignal("XF:18IDB-UT{Fltr:3}Cmd:In-Cmd", name="filter3") filter4 = EpicsSignal("XF:18IDB-UT{Fltr:4}Cmd:In-Cmd", name="filter4") -filters = { +FILTERS = { "filter1": filter1, "filter2": filter2, "filter3": filter3, diff --git a/startup/40-scans.py b/startup/40-scans.py index 77fbd99..449b3a2 100755 --- a/startup/40-scans.py +++ b/startup/40-scans.py @@ -89,10 +89,10 @@ def _close_shutter(simu=False): # yield from mv(shutter, 'Close') i = 0 while not shutter_status.value: # if 1: closed; if 0: open - yield from abs_set(shutter_open, 1, wait=True) - yield from bps.sleep(2) + #yield from abs_set(shutter_open, 1, wait=True) + #yield from bps.sleep(2) yield from abs_set(shutter_close, 1, wait=True) - yield from bps.sleep(8) + yield from bps.sleep(3) i += 1 print(f"try closing again ...") if i > 20: @@ -111,7 +111,7 @@ def _open_shutter(simu=False): # yield from mv(shutter, 'Open') i = 0 while shutter_status.value: # if 1: closed; if 0: open - yield from abs_set(shutter_open, 1) + yield from abs_set(shutter_open, 1, wait=True) yield from bps.sleep(1) i += 1 if i > 5: @@ -132,6 +132,7 @@ def _set_andor_param(exposure_time=0.1, period=0.1, chunk_size=1): yield from abs_set(Andor.cam.image_mode, 0, wait=True) yield from abs_set(Andor.cam.num_images, chunk_size, wait=True) yield from abs_set(Andor.cam.acquire_time, exposure_time, wait=True) +# yield from abs_set(Andor.cam.acquire_period, period, wait=True) Andor.cam.acquire_period.put(period) @@ -139,18 +140,18 @@ def _set_rotation_speed(rs=1): yield from abs_set(zps.pi_r.velocity, rs) -def _take_image(detectors, motor, num): +def _take_image(detectors, motor, num, stream_name='primary'): if not (type(detectors) == list): detectors = list(detectors) if not (type(motor) == list): motor = list(motor) for i in range(num): - yield from trigger_and_read(detectors + motor) + yield from trigger_and_read(detectors + motor, name=stream_name) def _take_dark_image(detectors, motor, num_dark=1, simu=False): yield from _close_shutter(simu) - yield from _take_image(detectors, motor, num_dark) + yield from _take_image(detectors, motor, num_dark)#, stream_name='dark') def _take_bkg_image( @@ -167,7 +168,7 @@ def _take_bkg_image( yield from _move_sample_out( out_x, out_y, out_z, out_r, repeat=2, rot_first_flag=traditional_sequence_flag ) - yield from _take_image(detectors, motor, num_bkg) + yield from _take_image(detectors, motor, num_bkg)#, stream_name='flat') def _xanes_per_step(eng, detectors, motor, move_flag=1, move_clens_flag=1, info_flag=0): @@ -401,15 +402,15 @@ def xanes_scan( motor_r_ini = zps.pi_r.position if relative_move_flag: - motor_x_out = motor_x_ini + out_x if out_x else motor_x_ini - motor_y_out = motor_y_ini + out_y if out_y else motor_y_ini - motor_z_out = motor_z_ini + out_z if out_z else motor_z_ini - motor_r_out = motor_r_ini + out_r if out_r else motor_r_ini + motor_x_out = motor_x_ini + out_x if not (out_x is None) else motor_x_ini + motor_y_out = motor_y_ini + out_y if not (out_y is None) else motor_y_ini + motor_z_out = motor_z_ini + out_z if not (out_z is None) else motor_z_ini + motor_r_out = motor_r_ini + out_r if not (out_r is None) else motor_r_ini else: - motor_x_out = out_x if out_x else motor_x_ini - motor_y_out = out_y if out_y else motor_y_ini - motor_z_out = out_z if out_z else motor_z_ini - motor_r_out = out_r if out_r else motor_r_ini + motor_x_out = out_x if not (out_x is None) else motor_x_ini + motor_y_out = out_y if not (out_y is None) else motor_y_ini + motor_z_out = out_z if not (out_z is None) else motor_z_ini + motor_r_out = out_r if not (out_r is None) else motor_r_ini rs_ini = zps.pi_r.velocity.value motor = [motor_eng, zps.sx, zps.sy, zps.sz, zps.pi_r] @@ -580,15 +581,15 @@ def xanes_scan2( motor_r_ini = zps.pi_r.position if relative_move_flag: - motor_x_out = motor_x_ini + out_x if out_x else motor_x_ini - motor_y_out = motor_y_ini + out_y if out_y else motor_y_ini - motor_z_out = motor_z_ini + out_z if out_z else motor_z_ini - motor_r_out = motor_r_ini + out_r if out_r else motor_r_ini + motor_x_out = motor_x_ini + out_x if not (out_x is None) else motor_x_ini + motor_y_out = motor_y_ini + out_y if not (out_y is None) else motor_y_ini + motor_z_out = motor_z_ini + out_z if not (out_z is None) else motor_z_ini + motor_r_out = motor_r_ini + out_r if not (out_r is None) else motor_r_ini else: - motor_x_out = out_x if out_x else motor_x_ini - motor_y_out = out_y if out_y else motor_y_ini - motor_z_out = out_z if out_z else motor_z_ini - motor_r_out = out_r if out_r else motor_r_ini + motor_x_out = out_x if not (out_x is None) else motor_x_ini + motor_y_out = out_y if not (out_y is None) else motor_y_ini + motor_z_out = out_z if not (out_z is None) else motor_z_ini + motor_r_out = out_r if not (out_r is None) else motor_r_ini rs_ini = zps.pi_r.velocity.value @@ -652,7 +653,7 @@ def xanes_inner_scan(): for eng in eng_list: yield from _xanes_per_step( - eng, detectors, motor, move_flag=1, move_clens_flag=1, info_flag=0 + eng, detectors, motor, move_flag=1, move_clens_flag=0, info_flag=0 ) if len(flt): for filt in flt: @@ -768,15 +769,15 @@ def xanes_scan3( motor_r_ini = zps.pi_r.position if relative_move_flag: - motor_x_out = motor_x_ini + out_x if out_x else motor_x_ini - motor_y_out = motor_y_ini + out_y if out_y else motor_y_ini - motor_z_out = motor_z_ini + out_z if out_z else motor_z_ini - motor_r_out = motor_r_ini + out_r if out_r else motor_r_ini + motor_x_out = motor_x_ini + out_x if not (out_x is None) else motor_x_ini + motor_y_out = motor_y_ini + out_y if not (out_y is None) else motor_y_ini + motor_z_out = motor_z_ini + out_z if not (out_z is None) else motor_z_ini + motor_r_out = motor_r_ini + out_r if not (out_r is None) else motor_r_ini else: - motor_x_out = out_x if out_x else motor_x_ini - motor_y_out = out_y if out_y else motor_y_ini - motor_z_out = out_z if out_z else motor_z_ini - motor_r_out = out_r if out_r else motor_r_ini + motor_x_out = out_x if not (out_x is None) else motor_x_ini + motor_y_out = out_y if not (out_y is None) else motor_y_ini + motor_z_out = out_z if not (out_z is None) else motor_z_ini + motor_r_out = out_r if not (out_r is None) else motor_r_ini rs_ini = zps.pi_r.velocity.value @@ -889,7 +890,7 @@ def mv_stage(motor, pos): yield Msg("set", motor, pos, group=grp) yield Msg("wait", None, group=grp) - +''' def eng_scan( eng_list, eng_start=8.3, @@ -943,7 +944,6 @@ def eng_scan( for i in range(num): # yield from scan([ic3, ic4], XEng, eng_start/1000, eng_end/1000, steps) yield from eng_scan_delay( - eng_list, eng_start, eng_end, steps, @@ -952,8 +952,8 @@ def eng_scan( note="", ) h = db[-1] - y0 = np.array(list(h.data(ic3.name))) - y1 = np.array(list(h.data(ic4.name))) + y0 = np.array(list(h.data(detectors[0].name))) + y1 = np.array(list(h.data(detectors[1].name))) r = np.log(y0 / y1) if not len(eng_list): @@ -965,8 +965,8 @@ def eng_scan( r_dif = np.array([0] + list(np.diff(r))) ax2.plot(x, r_dif, ".-") - ax1.title.set_text("ratio of: {0}/{1}".format(ic3.name, ic4.name)) - ax2.title.set_text("differential of: {0}/{1}".format(ic3.name, ic4.name)) + ax1.title.set_text("ratio of: {0}/{1}".format(detectors[0].name, detectors[1].name)) + ax2.title.set_text("differential of: {0}/{1}".format(detectors[0].name, detectors[1].name)) fig.subplots_adjust(hspace=0.5) plt.show() txt_finish = '## "eng_scan()" finished' @@ -975,9 +975,9 @@ def eng_scan( spec[:, 0] = x spec[:, 1] = r np.savetxt(f"{elem}_spec.txt", spec) +''' - -def eng_scan_delay( +def eng_scan( start, stop=None, num=1, detectors=[ic3, ic4], delay_time=1, note="", md=None ): """ @@ -1215,6 +1215,7 @@ def eng_inner_scan(): def fly_scan( exposure_time=0.1, + start_angle = None, relative_rot_angle=180, period=0.15, chunk_size=20, @@ -1230,12 +1231,16 @@ def fly_scan( filters=[], rot_back_velo=30, md=None, + binning=[1, 1] ): """ Inputs: ------- exposure_time: float, in unit of sec + start_angle: float + starting angle + relative_rot_angle: float, total rotation angles start from current rotary stage (zps.pi_r) position @@ -1273,21 +1278,25 @@ def fly_scan( """ global ZONE_PLATE + motor_x_ini = zps.sx.position motor_y_ini = zps.sy.position motor_z_ini = zps.sz.position motor_r_ini = zps.pi_r.position + if not (start_angle is None): + yield from mv(zps.pi_r, start_angle) + if relative_move_flag: - motor_x_out = motor_x_ini + out_x if out_x else motor_x_ini - motor_y_out = motor_y_ini + out_y if out_y else motor_y_ini - motor_z_out = motor_z_ini + out_z if out_z else motor_z_ini - motor_r_out = motor_r_ini + out_r if out_r else motor_r_ini + motor_x_out = motor_x_ini + out_x if not (out_x is None) else motor_x_ini + motor_y_out = motor_y_ini + out_y if not (out_y is None) else motor_y_ini + motor_z_out = motor_z_ini + out_z if not (out_z is None) else motor_z_ini + motor_r_out = motor_r_ini + out_r if not (out_r is None) else motor_r_ini else: - motor_x_out = out_x if out_x else motor_x_ini - motor_y_out = out_y if out_y else motor_y_ini - motor_z_out = out_z if out_z else motor_z_ini - motor_r_out = out_r if out_r else motor_r_ini + motor_x_out = out_x if not (out_x is None) else motor_x_ini + motor_y_out = out_y if not (out_y is None) else motor_y_ini + motor_z_out = out_z if not (out_z is None) else motor_z_ini + motor_r_out = out_r if not (out_r is None) else motor_r_ini motor = [zps.sx, zps.sy, zps.sz, zps.pi_r] @@ -1303,6 +1312,7 @@ def fly_scan( "ion_chamber": ic3.name, "plan_args": { "exposure_time": exposure_time, + "start_angle": start_angle, "relative_rot_angle": relative_rot_angle, "period": period, "chunk_size": chunk_size, @@ -1337,6 +1347,9 @@ def fly_scan( else: _md["hints"].setdefault("dimensions", dimensions) + yield from mv(Andor.cam.acquire, 0) + yield from mv(Andor.cam.bin_y, binning[0], + Andor.cam.bin_x, binning[1]) yield from _set_andor_param( exposure_time=exposure_time, period=period, chunk_size=chunk_size ) @@ -1775,15 +1788,15 @@ def raster_2D_scan( motor_r_ini = zps.pi_r.position if relative_move_flag: - motor_x_out = motor_x_ini + out_x if out_x else motor_x_ini - motor_y_out = motor_y_ini + out_y if out_y else motor_y_ini - motor_z_out = motor_z_ini + out_z if out_z else motor_z_ini - motor_r_out = motor_r_ini + out_r if out_r else motor_r_ini + motor_x_out = motor_x_ini + out_x if not (out_x is None) else motor_x_ini + motor_y_out = motor_y_ini + out_y if not (out_y is None) else motor_y_ini + motor_z_out = motor_z_ini + out_z if not (out_z is None) else motor_z_ini + motor_r_out = motor_r_ini + out_r if not (out_r is None) else motor_r_ini else: - motor_x_out = out_x if out_x else motor_x_ini - motor_y_out = out_y if out_y else motor_y_ini - motor_z_out = out_z if out_z else motor_z_ini - motor_r_out = out_r if out_r else motor_r_ini + motor_x_out = out_x if not (out_x is None) else motor_x_ini + motor_y_out = out_y if not (out_y is None) else motor_y_ini + motor_z_out = out_z if not (out_z is None) else motor_z_ini + motor_r_out = out_r if not (out_r is None) else motor_r_ini img_sizeX = np.int(img_sizeX) img_sizeY = np.int(img_sizeY) @@ -1980,15 +1993,15 @@ def raster_2D_scan2( motor_r_ini = zps.pi_r.position if relative_move_flag: - motor_x_out = motor_x_ini + out_x if out_x else motor_x_ini - motor_y_out = motor_y_ini + out_y if out_y else motor_y_ini - motor_z_out = motor_z_ini + out_z if out_z else motor_z_ini - motor_r_out = motor_r_ini + out_r if out_r else motor_r_ini + motor_x_out = motor_x_ini + out_x if not (out_x is None) else motor_x_ini + motor_y_out = motor_y_ini + out_y if not (out_y is None) else motor_y_ini + motor_z_out = motor_z_ini + out_z if not (out_z is None) else motor_z_ini + motor_r_out = motor_r_ini + out_r if not (out_r is None) else motor_r_ini else: - motor_x_out = out_x if out_x else motor_x_ini - motor_y_out = out_y if out_y else motor_y_ini - motor_z_out = out_z if out_z else motor_z_ini - motor_r_out = out_r if out_r else motor_r_ini + motor_x_out = out_x if not (out_x is None) else motor_x_ini + motor_y_out = out_y if not (out_y is None) else motor_y_ini + motor_z_out = out_z if not (out_z is None) else motor_z_ini + motor_r_out = out_r if not (out_r is None) else motor_r_ini img_sizeX = np.int(img_sizeX) img_sizeY = np.int(img_sizeY) @@ -2184,6 +2197,7 @@ def multipos_2D_xanes_scan2( relative_move_flag=True, note="", md=None, + binning=[1, 1] ): """ Different from multipos_2D_xanes_scan. In the current scan, it take image at all locations and then move out sample to take background image. @@ -2257,6 +2271,9 @@ def multipos_2D_xanes_scan2( insert_text(txt) detectors = [Andor, ic3, ic4] period = max(0.05, exposure_time) + yield from mv(Andor.cam.acquire, 0) + yield from mv(Andor.cam.bin_y, binning[0], + Andor.cam.bin_x, binning[1]) yield from _set_andor_param(exposure_time, period=period, chunk_size=chunk_size) eng_ini = XEng.position @@ -2267,15 +2284,15 @@ def multipos_2D_xanes_scan2( motor_r_ini = zps.pi_r.position if relative_move_flag: - motor_x_out = motor_x_ini + out_x if out_x else motor_x_ini - motor_y_out = motor_y_ini + out_y if out_y else motor_y_ini - motor_z_out = motor_z_ini + out_z if out_z else motor_z_ini - motor_r_out = motor_r_ini + out_r if out_r else motor_r_ini + motor_x_out = motor_x_ini + out_x if not (out_x is None) else motor_x_ini + motor_y_out = motor_y_ini + out_y if not (out_y is None) else motor_y_ini + motor_z_out = motor_z_ini + out_z if not (out_z is None) else motor_z_ini + motor_r_out = motor_r_ini + out_r if not (out_r is None) else motor_r_ini else: - motor_x_out = out_x if out_x else motor_x_ini - motor_y_out = out_y if out_y else motor_y_ini - motor_z_out = out_z if out_z else motor_z_ini - motor_r_out = out_r if out_r else motor_r_ini + motor_x_out = out_x if not (out_x is None) else motor_x_ini + motor_y_out = out_y if not (out_y is None) else motor_y_ini + motor_z_out = out_z if not (out_z is None) else motor_z_ini + motor_r_out = out_r if not (out_r is None) else motor_r_ini motor = [XEng, zps.sx, zps.sy, zps.sz, zps.pi_r] @@ -2387,8 +2404,9 @@ def inner_scan(): # close shutter and sleep yield from _close_shutter(simu) # sleep - print(f"\nsleep for {sleep_time} seconds ...") - yield from bps.sleep(sleep_time) + if rep < repeat_num: + print(f"\nsleep for {sleep_time} seconds ...") + yield from bps.sleep(sleep_time) yield from mv( zps.sx, x_list[0], zps.sy, y_list[0], zps.sz, z_list[0], zps.pi_r, r_list[0] @@ -2489,15 +2507,15 @@ def multipos_2D_xanes_scan3( motor_r_ini = zps.pi_r.position if relative_move_flag: - motor_x_out = motor_x_ini + out_x if out_x else motor_x_ini - motor_y_out = motor_y_inil + out_y if out_y else motor_y_ini - motor_z_out = motor_z_ini + out_z if out_z else motor_z_ini - motor_r_out = motor_r_ini + out_r if out_r else motor_r_ini + motor_x_out = motor_x_ini + out_x if not (out_x is None) else motor_x_ini + motor_y_out = motor_y_ini + out_y if not (out_y is None) else motor_y_ini + motor_z_out = motor_z_ini + out_z if not (out_z is None) else motor_z_ini + motor_r_out = motor_r_ini + out_r if not (out_r is None) else motor_r_ini else: - motor_x_out = out_x if out_x else motor_x_ini - motor_y_out = out_y if out_y else motor_y_ini - motor_z_out = out_z if out_z else motor_z_ini - motor_r_out = out_r if out_r else motor_r_ini + motor_x_out = out_x if not (out_x is None) else motor_x_ini + motor_y_out = out_y if not (out_y is None) else motor_y_ini + motor_z_out = out_z if not (out_z is None) else motor_z_ini + motor_r_out = out_r if not (out_r is None) else motor_r_ini motor = [XEng, zps.sx, zps.sy, zps.sz, zps.pi_r] @@ -2644,15 +2662,15 @@ def raster_2D_xanes2( motor_r_ini = zps.pi_r.position if relative_move_flag: - motor_x_out = motor_x_ini + out_x if out_x else motor_x_ini - motor_y_out = motor_y_ini + out_y if out_y else motor_y_ini - motor_z_out = motor_z_ini + out_z if out_z else motor_z_ini - motor_r_out = motor_r_ini + out_r if out_r else motor_r_ini + motor_x_out = motor_x_ini + out_x if not (out_x is None) else motor_x_ini + motor_y_out = motor_y_ini + out_y if not (out_y is None) else motor_y_ini + motor_z_out = motor_z_ini + out_z if not (out_z is None) else motor_z_ini + motor_r_out = motor_r_ini + out_r if not (out_r is None) else motor_r_ini else: - motor_x_out = out_x if out_x else motor_x_ini - motor_y_out = out_y if out_y else motor_y_ini - motor_z_out = out_z if out_z else motor_z_ini - motor_r_out = out_r if out_r else motor_r_ini + motor_x_out = out_x if not (out_x is None) else motor_x_ini + motor_y_out = out_y if not (out_y is None) else motor_y_ini + motor_z_out = out_z if not (out_z is None) else motor_z_ini + motor_r_out = out_r if not (out_r is None) else motor_r_ini x_list, y_list, z_list, r_list = [], [], [], [] for ii in np.arange(x_range[0], x_range[1] + 1): @@ -2834,16 +2852,17 @@ def inner_scan(): y_ini = zps.sy.position z_ini = zps.sz.position r_ini = zps.pi_r.position + if relative_move_flag: - x_target = x_ini + out_x if out_x else x_ini - y_target = y_ini + out_y if out_y else y_ini - z_target = z_ini + out_z if out_z else z_ini - r_target = r_ini + out_r if out_r else r_ini + x_target = x_ini + out_x if not (out_x is None) else x_ini + y_target = y_ini + out_y if not (out_y is None) else y_ini + z_target = z_ini + out_z if not (out_z is None) else z_ini + r_target = r_ini + out_r if not (out_r is None) else r_ini else: - x_target = out_x if out_x else x_ini - y_target = out_y if out_y else y_ini - z_target = out_z if out_z else z_ini - r_target = out_r if out_r else r_ini + x_target = out_x if not (out_x is None) else x_ini + y_target = out_y if not (out_y is None) else y_ini + z_target = out_z if not (out_z is None) else z_ini + r_target = out_r if not (out_r is None) else r_ini yield from trigger_and_read( list([Andor, ic3]) + [zps.sx, zps.sy, zps.sz, zps.pi_r] ) @@ -2866,8 +2885,10 @@ def inner_scan(): def xanes_3D( eng_list, exposure_time=0.05, + start_angle = None, relative_rot_angle=185, period=0.05, + chunk_size=20, out_x=0, out_y=0, out_z=0, @@ -2875,11 +2896,15 @@ def xanes_3D( rs=2, simu=False, relative_move_flag=1, - traditional_sequence_flag=1, + rot_first_flag=1, note="", + binning = [2, 2] ): txt = "start 3D xanes scan, containing following fly_scan:\n" insert_text(txt) + yield from mv(Andor.cam.acquire, 0) + yield from mv(Andor.cam.bin_y, binning[0], + Andor.cam.bin_x, binning[1]) for eng in eng_list: yield from move_zp_ccd(eng, move_flag=1) my_note = note + f"_energy={eng}" @@ -2888,16 +2913,19 @@ def xanes_3D( # yield from fly_scan(exposure_time, relative_rot_angle=relative_rot_angle, period=period, out_x=out_x, out_y=out_y, out_z=out_z, out_r= out_r, rs=rs, note=my_note, simu=simu, relative_move_flag=relative_move_flag, traditional_sequence_flag=traditional_sequence_flag) yield from fly_scan( exposure_time, + start_angle=start_angle, relative_rot_angle=relative_rot_angle, period=period, + chunk_size = chunk_size, out_x=out_x, out_y=out_y, out_z=out_z, out_r=out_r, rs=rs, + relative_move_flag=relative_move_flag, note=my_note, simu=simu, - relative_move_flag=relative_move_flag, + rot_first_flag=rot_first_flag, ) yield from bps.sleep(1) yield from mv(Andor.cam.image_mode, 1) @@ -2916,6 +2944,7 @@ def xanes_3D( def fly_scan_repeat( exposure_time=0.03, + start_angle = None, relative_rot_angle=185, period=0.05, chunk_size=20, @@ -2943,6 +2972,7 @@ def fly_scan_repeat( for i in range(repeat): yield from fly_scan( exposure_time=exposure_time, + start_angle = start_angle, relative_rot_angle=relative_rot_angle, period=period, chunk_size=chunk_size, @@ -2980,6 +3010,7 @@ def fly_scan_repeat( ) yield from fly_scan( exposure_time=exposure_time, + start_angle=start_angle, relative_rot_angle=relative_rot_angle, period=period, chunk_size=chunk_size, @@ -3012,6 +3043,7 @@ def multi_pos_xanes_3D( y_list, z_list, r_list, + start_angle = None, exposure_time=0.05, relative_rot_angle=185, period=0.05, @@ -3025,6 +3057,7 @@ def multi_pos_xanes_3D( traditional_sequence_flag=1, note="", sleep_time=0, + binning = [2, 2], repeat=1, ): n = len(x_list) @@ -3045,18 +3078,21 @@ def multi_pos_xanes_3D( print(f"{txt}\n##########################\n\n\n\n") yield from xanes_3D( eng_list, - exposure_time, - relative_rot_angle, - period, - out_x, - out_y, - out_z, - out_r, - rs, - simu, - relative_move_flag, - traditional_sequence_flag, - note, + exposure_time=exposure_time, + start_angle =start_angle, + relative_rot_angle=relative_rot_angle, + period=period, + out_x=out_x, + out_y=out_y, + out_z=out_z, + out_r=out_r, + rs=rs, + simu=simu, + relative_move_flag=relative_move_flag, + rot_first_flag=traditional_sequence_flag, + note=note, + binning = [2, 2], ) print(f"sleep for {sleep_time} sec\n\n\n\n") yield from bps.sleep(sleep_time) + diff --git a/startup/42-scans_other.py b/startup/42-scans_other.py index 26b1fcc..bdee188 100755 --- a/startup/42-scans_other.py +++ b/startup/42-scans_other.py @@ -196,10 +196,10 @@ def z_scan( @stage_decorator(list(detectors) + [motor]) @run_decorator(md=_md) def inner_scan(): -# yield from abs_set(shutter_open, 1, wait=True) -# yield from bps.sleep(1) -# yield from abs_set(shutter_open, 1) -# yield from bps.sleep(1) + # yield from abs_set(shutter_open, 1, wait=True) + # yield from bps.sleep(1) + # yield from abs_set(shutter_open, 1) + # yield from bps.sleep(1) yield from _open_shutter(simu=simu) for x in my_var: yield from mv(motor, x) @@ -211,10 +211,10 @@ def inner_scan(): yield from bps.sleep(0.5) yield from trigger_and_read(list(detectors) + [motor]) # dark images -# yield from abs_set(shutter_close, 1, wait=True) -# yield from bps.sleep(1) -# yield from abs_set(shutter_close, 1) -# yield from bps.sleep(1) + # yield from abs_set(shutter_close, 1, wait=True) + # yield from bps.sleep(1) + # yield from abs_set(shutter_close, 1) + # yield from bps.sleep(1) yield from _close_shutter(simu=simu) yield from trigger_and_read(list(detectors) + [motor]) # move back zone_plate and sample y @@ -226,7 +226,8 @@ def inner_scan(): yield from mv(Andor.cam.image_mode, 1) uid = yield from inner_scan() - + yield from mv(Andor.cam.image_mode, 1) + yield from _close_shutter(simu=False) txt = get_scan_parameter() insert_text(txt) print(txt) @@ -347,7 +348,8 @@ def z_inner_scan(): # yield from abs_set(shutter_open, 1, wait=True) yield from z_inner_scan() - + yield from mv(Andor.cam.image_mode, 1) + yield from _close_shutter(simu=False) txt = get_scan_parameter() insert_text(txt) print(txt) @@ -569,7 +571,7 @@ def load_cell_scan( for bender_pos in pzt_cm_bender_pos_list: yield from mv(pzt_cm.setpos, bender_pos) - yield from bps.sleep(1) + yield from bps.sleep(5) load_cell_force = pzt_cm_loadcell.value fig = plt.figure() ax1 = fig.add_subplot(211) @@ -1003,7 +1005,7 @@ def knife_edge_scan_for_condensor( import matplotlib.pylab as plt import numpy as np from numpy import polyfit, poly1d - from scipy.optimize import curve_fit + from scipy.optimize import curve_fit, least_squares from scipy.special import erf from scipy.signal import gaussian @@ -1034,6 +1036,8 @@ def erfunc(x, mFL, a, b): def gauss(x, *p): A, mu, sigma = p return A * np.exp(-((x - mu) ** 2) / (2.0 * sigma ** 2)) + +# def fit_gauss() f = h5py.File(fn, "r") img = f["/entry/data/data"][:] @@ -1048,7 +1052,7 @@ def gauss(x, *p): for ii in range(zpt): (l,) = ax0.plot( cur[ii * ypt : (ii + 1) * ypt], - color=(0.1 * ii, np.mod(0.2 * ii, 1), np.mod(0.3 * ii, 1)), +# color=(0.1 * ii, np.mod(0.2 * ii, 1), np.mod(0.3 * ii, 1)), ) line0.append(l) line0[ii].set_label("{0}".format(ii)) @@ -1059,7 +1063,7 @@ def gauss(x, *p): for ii in range(zpt): (l,) = ax1.plot( np.gradient(np.log10(cur[ii * ypt : (ii + 1) * ypt])), - color=(0.1 * ii, np.mod(0.2 * ii, 1), np.mod(0.3 * ii, 1)), +# color=(0.1 * ii, np.mod(0.2 * ii, 1), np.mod(0.3 * ii, 1)), ) line1.append(l) line1[ii].set_label("{0}".format(ii)) @@ -1075,11 +1079,14 @@ def gauss(x, *p): params, extras = curve_fit( gauss, y, np.gradient(np.log10(cur[ii * ypt : (ii + 1) * ypt])), p0 ) +# params, extras = least_squares( +# gauss, y, jac='3-points', np.gradient(np.log10(cur[ii * ypt : (ii + 1) * ypt])), p0 +# ) wz.append(params[2]) (l,) = ax2.plot( yf, gauss(yf, *params), - color=(0.1 * ii, np.mod(0.2 * ii, 1), np.mod(0.3 * ii, 1)), +# color=(0.1 * ii, np.mod(0.2 * ii, 1), np.mod(0.3 * ii, 1)), ) line2.append(l) diff --git a/startup/60-gen_pdf.py b/startup/60-gen_pdf.py index ca37fcd..5e32731 100755 --- a/startup/60-gen_pdf.py +++ b/startup/60-gen_pdf.py @@ -24,7 +24,8 @@ def reset_pdf(): PDF_ARGS[ "fn_log" ] = f'/NSLS2/xf18id1/DATA/FXI_log/TXM_log_test_{PDF_ARGS["year"]}{PDF_ARGS["month"]}{PDF_ARGS["day"]}.pdf' - PDF_ARGS["temp_folder"] = "/home/xf18id/.ipython/profile_collection/startup/temp" + #PDF_ARGS["temp_folder"] = "/home/xf18id/.ipython/profile_collection/startup/temp" + PDF_ARGS["temp_folder"] = "/NSLS2/xf18id1/DATA/FXI_log/temp" PDF_ARGS["temp_img_folder"] = PDF_ARGS["temp_folder"] + "/img" PDF_ARGS["fn_tmp"] = PDF_ARGS["temp_folder"] + "/tmp.pdf" PDF_ARGS["fn_tmp_txt"] = PDF_ARGS["temp_folder"] + "/current_log.txt" @@ -161,7 +162,7 @@ def insert_pic(fn="", ratio=0.3): ) PDF_ARGS["Cursor_x"] = 0.6 * inch PDF_ARGS["Cursor_y"] -= inch / 2 - insert_text(fn) + insert_text('insert pic:'+fn) # PDF_ARGS['tmp_flag'] += 1 except: @@ -189,6 +190,7 @@ def insert_screen_shot(ratio=0.6): cmd = f"import {fn}" os.system(cmd) insert_pic(fn, ratio) + insert_text(fn) # if flag==2: # current monitor screen @@ -230,7 +232,10 @@ def merge_log(): for line in fp: if line[0] == "\n": print(f"tmp_txt={tmp_txt}") - insert_text(tmp_txt, 0) + if 'insert pic' in tmp_txt.split(':')[0]: + insert_pic(tmp_txt.split(':')[1]) + else: + insert_text(tmp_txt, 0) tmp_txt = "" else: tmp_txt += line @@ -245,8 +250,8 @@ def merge_log(): reset_pdf() except: print("merge fails... need manual check...") - except: - pass + except Exception as err: + print(err) def merge_pdf(fn1, fn2, fout): diff --git a/startup/91-functions.py b/startup/91-functions.py index 9710879..eda832d 100755 --- a/startup/91-functions.py +++ b/startup/91-functions.py @@ -7,6 +7,52 @@ from scipy.signal import medfilt2d +def check_latest_scan_id(init_guess=60000, search_size=100): + sid_from_md = RE.md['scan_id'] + if len(list(db(scan_id=sid_from_md))) > 0: + sid_i = max(db[-1].start['scan_id'], sid_from_md, init_guess) + else: # current RE.md['scan_id'] is an empty scan, e.g., someone set RE.md['scan_id'] mistakely + sid_i = max(db[-1].start['scan_id'], init_guess) + sid = sid_i + n = len(list(db(scan_id=sid))) + if len(list(db(scan_id=sid))) == 1: + for i in range(1, 11): + if len(list(db(scan_id=sid+i))) == 1: + break + if i == 10: + return print(f'\nThe latest scan_id is {sid}, set RE.md["scan_id"]={sid}') + while n > 0: + sid_i = sid + sid += search_size + n = len(list(db(scan_id=sid))) + print(sid) + sid_n = sid + sid = int((sid_i + sid_n)/2) + print(f'sid_i = {sid_i}, sid_n = {sid_n}') + while 1: + print(f'sid_i = {sid_i}, sid_n = {sid_n} --> sid = {sid}') + n = len(list(db(scan_id=sid))) + if n > 0: + sid_i = sid + else: # n=0: scan_id is empty + sid_n = sid + sid = int((sid_i + sid_n)/2) + # print(f'sid_i = {sid_i}, sid_n = {sid_n} --> sid = {sid}') + if sid_n - sid_i <= 1: + break + tmp = [] + for i in range(10): # check following 10 scans if any scan_id has not be used ever + tmp.append(len(list(db(scan_id=sid+i)))) + tmp_len_equal_1 = np.where(np.array(tmp) == 1)[0] + if len(tmp_len_equal_1): + sid = sid + tmp_len_equal_1[-1] + sid = int(sid) + while not (len(list(db(scan_id=sid))) == 1 and len(list(db(scan_id=sid+1))) == 0): + sid += 1 + RE.md['scan_id'] = sid + return print(f'\nThe latest scan_id is {sid}, set RE.md["scan_id"]={sid}') + + def change_hdf5_source(cam, roi_name): yield from bps.mov(cam.hdf5.nd_array_port, roi_name) yield from bps.abs_set(cam.cam.acquire, 1) @@ -27,7 +73,7 @@ def cal_global_mag(x1, y1, x2, y2, nominal_dist=10000): def record_calib_pos_new(n): - global GLOBAL_MAG + global GLOBAL_MAG, CALIBER # CALIBER[f'chi2_pos{n}'] = pzt_dcm_chi2.pos.value CALIBER[f"chi2_pos{n}"] = dcm.chi2.position @@ -56,9 +102,8 @@ def record_calib_pos_new(n): pp = pprint.PrettyPrinter(indent=4) pp.pprint(tmp) df = pd.DataFrame.from_dict(CALIBER, orient="index") - df.to_csv( - "/home/xf18id/.ipython/profile_collection/startup/calib_new.csv", sep="\t" - ) + df.to_csv("/NSLS2/xf18id1/DATA/FXI_log/calib_new.csv") + #df.to_csv("/home/xf18id/.ipython/profile_collection/startup/calib_new.csv", sep="\t") print( f'calib_pos{n} recored: current Magnification = GLOBAL_MAG = {CALIBER[f"mag{n}"]}' ) @@ -66,57 +111,75 @@ def record_calib_pos_new(n): def remove_caliber_pos(n): global CALIBER_FLAG, CURRENT_MAG, CALIBER + df = pd.DataFrame.from_dict(CALIBER, orient="index") + df.to_csv("/NSLS2/xf18id1/DATA/FXI_log/calib_backup.csv") + CALIBER_backup = CALIBER.copy() try: - del CALIBER[f"chi2_pos{n}"] - del CALIBER[f"XEng_pos{n}"] - del CALIBER[f"zp_x_pos{n}"] - del CALIBER[f"zp_y_pos{n}"] - del CALIBER[f"th2_motor_pos{n}"] - del CALIBER[f"clens_x_pos{n}"] - del CALIBER[f"clens_y1_pos{n}"] - del CALIBER[f"clens_y2_pos{n}"] - del CALIBER[f"clens_p_pos{n}"] - del CALIBER[f"DetU_y_pos{n}"] - del CALIBER[f"DetU_x_pos{n}"] - del CALIBER[f"aper_x_pos{n}"] - del CALIBER[f"aper_y_pos{n}"] - del CURRENT_MAG[str(n)] + for k in CALIBER_backup.keys(): + if k[-1] == str(n): + del CALIBER[k] df = pd.DataFrame.from_dict(CALIBER, orient="index") - df.to_csv( - "/home/xf18id/.ipython/profile_collection/startup/calib_new.csv", sep="\t" - ) + #df.to_csv("/home/xf18id/.ipython/profile_collection/startup/calib_new.csv", sep="\t") + df.to_csv("/NSLS2/xf18id1/DATA/FXI_log/calib_new.csv") except: + CALIBER = CALIBER.copy() print(f"fails to remove CALIBER postion {n}, or it does not exist") - pp = pprint.PrettyPrinter(indent=4) - pp.pprint(CALIBER) - - -def print_caliber(): + print('CALIBER not changed') pp = pprint.PrettyPrinter(indent=4) pp.pprint(CALIBER) -def read_calib_file_new(): - fn = "/home/xf18id/.ipython/profile_collection/startup/calib_new.csv" - - df = pd.read_csv(fn, index_col=0, sep="\t") +def print_caliber(print_eng_only=1, pos=-1): + if print_eng_only: + for k in CALIBER.keys(): + if 'XEng' in k: + print(f'{k}: {CALIBER[k]:2.5f} keV') + print('If want to display full list of motor position, use "print_caliber(0, pos=1)"') + print('e.g., print_caliber(0, pos=-1) will display all recorded position in detail') + print('e.g., print_caliber(0, pos=1) will display will position 1 only') + + else: + if pos == -1: + pp = pprint.PrettyPrinter(indent=4) + pp.pprint(CALIBER) + else: + tmp = {} + for k in CALIBER.keys(): + if k[-1] == str(pos): + tmp[k] = CALIBER[k] + print(f'{k:>20s}: {CALIBER[k]:4.8f}') + #pp = pprint.PrettyPrinter(indent=4) + #pp.pprint(tmp) + +def read_calib_file_new(return_flag=0): + #fn = "/home/xf18id/.ipython/profile_collection/startup/calib_new.csv" + fn = "/NSLS2/xf18id1/DATA/FXI_log/calib_new.csv" + df = pd.read_csv(fn, index_col=0) d = df.to_dict("split") d = dict(zip(d["index"], d["data"])) for k in d.keys(): CALIBER[k] = np.float(d[k][0]) - pp = pprint.PrettyPrinter(indent=4) - pp.pprint(CALIBER) + + # pp = pprint.PrettyPrinter(indent=4) + # pp.pprint(CALIBER) + print('Energy caliberated at: ') + print_caliber() # except: # print(f'fails to read calibriation file') # CALIBER = {} - + if return_flag: + return CALIBER def move_zp_ccd(eng_new, move_flag=1, info_flag=1, move_clens_flag=0, move_det_flag=0): """ move the zone_plate and ccd to the user-defined energy with constant magnification use the function as: - move_zp_ccd_with_const_mag(eng_new=8.0, move_flag=1): + move_zp_ccd_with_const_mag(eng_new=8.0, move_flag=1) + Note: + in the above commend, it will use two energy calibration points to calculate the motor + position of XEng=8.0 keV. + specfically, one of the calibration points is > 8keV, the other one is < 8keV Inputs: ------- @@ -149,9 +212,25 @@ def move_zp_ccd(eng_new, move_flag=1, info_flag=1, move_clens_flag=0, move_det_f t = find_nearest(eng_new, ENG_val) eng1 = ENG_val.pop(t) id1 = ENG_idx.pop(t) - t = find_nearest(eng_new, ENG_val) - eng2 = ENG_val.pop(t) - id2 = ENG_idx.pop(t) + + + ENG_val_copy = np.array(ENG_val.copy()) + ENG_idx_copy = np.array(ENG_idx.copy()) + if eng_new >= eng1: + idx = ENG_val_copy > eng_new + else: + idx = ENG_val_copy < eng_new + + ENG_val_copy = ENG_val_copy[idx] + ENG_idx_copy = ENG_idx_copy[idx] + if len(ENG_val_copy): + t = find_nearest(eng_new, ENG_val_copy) + eng2 = ENG_val_copy[t] + id2 = ENG_idx_copy[t] + else: + t = find_nearest(eng_new, ENG_val) + eng2 = ENG_val[t] + id2 = ENG_idx[t] mag1 = CALIBER[f"mag{id1}"] mag2 = CALIBER[f"mag{id2}"] @@ -445,162 +524,6 @@ def move_zp_ccd(eng_new, move_flag=1, info_flag=1, move_clens_flag=0, move_det_f ################################ - -""" -def record_calib_pos1(): - global CALIBER_FLAG, CURRENT_MAG_1, CURRENT_MAG_2 - #CALIBER['th2_pos1'] = pzt_dcm_th2.pos.value - CALIBER['chi2_pos1'] = pzt_dcm_chi2.pos.value - CALIBER['XEng_pos1'] = XEng.position - CALIBER['zp_x_pos1'] = zp.x.position - CALIBER['zp_y_pos1'] = zp.y.position - CALIBER['th2_motor_pos1'] = th2_motor.position - CALIBER['clens_x_pos1'] = clens.x.position - CALIBER['clens_y1_pos1'] = clens.y1.position - CALIBER['clens_y2_pos1'] = clens.y2.position - CALIBER['clens_p_pos1'] = clens.p.position - CALIBER['DetU_x_pos1'] = DetU.x.position - CALIBER['DetU_y_pos1'] = DetU.y.position - CALIBER['aper_x_pos1'] = aper.x.position - CALIBER['aper_y_pos1'] = aper.y.position - - #print(f'pzt_dcm_th2_{CALIBER["XEng_pos1"]:2.4f}\t: {CALIBER["th2_pos1"]:2.4f}') - print(f'pzt_dcm_chi2_{CALIBER["XEng_pos1"]:2.4f} keV\t: {CALIBER["chi2_pos1"]:2.4f}') - print(f'zp_x_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["zp_x_pos1"]:2.4f}') - print(f'zp_y_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["zp_y_pos1"]:2.4f}') - print(f'th2_motor_{CALIBER["XEng_pos1"]:2.4f} keV\t: {CALIBER["th2_motor_pos1"]:2.6f}') - print(f'clens_x_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["clens_x_pos1"]:2.4f}') - print(f'clens_y1_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["clens_y1_pos1"]:2.4f}') - print(f'clens_y2_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["clens_y2_pos1"]:2.4f}') - print(f'clens_p_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["clens_p_pos1"]:2.4f}') - print(f'DetU_y_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["DetU_y_pos1"]:2.4f}') - print(f'aper_x_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["aper_x_pos1"]:2.4f}') - print(f'aper_y_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["aper_y_pos1"]:2.4f}') - df = pd.DataFrame.from_dict(CALIBER, orient='index') - df.to_csv('/home/xf18id/.ipython/profile_collection/startup/calib.csv', sep='\t') - CURRENT_MAG_1 = (DetU.z.position / zp.z.position - 1) * GLOBAL_VLM_MAG - if np.abs(CURRENT_MAG_1 - CURRENT_MAG_2) > 0.1: - print('MAGNIFICATION between two calibration points does not match!!') - print(f'MAGNIFICATION_1 = {CURRENT_MAG_1}\nMAGNIFICATION_2 = {CURRENT_MAG_2}') - CALIBER_FLAG = 0 - else: - - CALIBER_FLAG = 1 - GLOBAL_MAG = np.round(CURRENT_MAG_1 * 100) / 100. - print(f'calib_pos1 recored: current Magnification = {CURRENT_MAG_1}') - - -def record_calib_pos2(): - global CALIBER_FLAG, CURRENT_MAG_1, CURRENT_MAG_2 - #CALIBER['th2_pos2'] = pzt_dcm_th2.pos.value - CALIBER['chi2_pos2'] = pzt_dcm_chi2.pos.value - CALIBER['XEng_pos2'] = XEng.position - CALIBER['zp_x_pos2'] = zp.x.position - CALIBER['zp_y_pos2'] = zp.y.position - CALIBER['th2_motor_pos2'] = th2_motor.position - CALIBER['clens_x_pos2'] = clens.x.position - CALIBER['clens_y1_pos2'] = clens.y1.position - CALIBER['clens_y2_pos2'] = clens.y2.position - CALIBER['clens_p_pos2'] = clens.p.position - CALIBER['DetU_y_pos2'] = DetU.y.position - CALIBER['DetU_x_pos2'] = DetU.x.position - CALIBER['aper_x_pos2'] = aper.x.position - CALIBER['aper_y_pos2'] = aper.y.position - #print(f'pzt_dcm_th2_{CALIBER["XEng_pos2"]:2.4f}\t: {CALIBER["th2_pos2"]:2.4f}') - print(f'pzt_dcm_chi2_{CALIBER["XEng_pos2"]:2.4f} keV\t: {CALIBER["chi2_pos2"]:2.4f}') - print(f'zp_x_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["zp_x_pos2"]:2.4f}') - print(f'zp_y_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["zp_y_pos2"]:2.4f}') - print(f'th2_motor_{CALIBER["XEng_pos2"]:2.4f} keV\t: {CALIBER["th2_motor_pos2"]:2.6f}') - print(f'clens_p_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["clens_p_pos2"]:2.4f}') - print(f'clens_x_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["clens_x_pos2"]:2.4f}') - print(f'clens_y1_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["clens_y1_pos2"]:2.4f}') - print(f'clens_y2_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["clens_y2_pos2"]:2.4f}') - print(f'DetU_y_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["DetU_y_pos2"]:2.4f}') - print(f'aper_x_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["aper_x_pos2"]:2.4f}') - print(f'aper_y_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["aper_y_pos2"]:2.4f}') - df = pd.DataFrame.from_dict(CALIBER, orient='index') - df.to_csv('/home/xf18id/.ipython/profile_collection/startup/calib.csv', sep='\t') - CURRENT_MAG_2 = (DetU.z.position / zp.z.position - 1) * GLOBAL_VLM_MAG - if np.abs(CURRENT_MAG_1 - CURRENT_MAG_2) > 0.1: - print('MAGNIFICATION between two calibration points does not match!!') - print(f'MAGNIFICATION_1 = {CURRENT_MAG_1}\nMAGNIFICATION_2 = {CURRENT_MAG_2}') - CALIBER_FLAG = 0 - else: - - CALIBER_FLAG = 1 - - GLOBAL_MAG = np.round(CURRENT_MAG_2 * 100) / 100. - print(f'calib_pos2 recored: current Magnification = {CURRENT_MAG_2}') - - -def read_calib_file(): - fn = '/home/xf18id/.ipython/profile_collection/startup/calib.csv' - try: - df = pd.read_csv(fn, index_col=0, sep='\t') - d = df.to_dict("split") - d = dict(zip(d["index"], d["data"])) - #CALIBER['th2_pos1'] = np.float(d['th2_pos1'][0]) - CALIBER['chi2_pos1'] = np.float(d['chi2_pos1'][0]) - CALIBER['XEng_pos1'] = np.float(d['XEng_pos1'][0]) - CALIBER['zp_x_pos1'] = np.float(d['zp_x_pos1'][0]) - CALIBER['zp_y_pos1'] = np.float(d['zp_y_pos1'][0]) - CALIBER['th2_motor_pos1'] = np.float(d['th2_motor_pos1'][0]) - CALIBER['clens_x_pos1'] = np.float(d['clens_x_pos1'][0]) - CALIBER['clens_y1_pos1'] = np.float(d['clens_y1_pos1'][0]) - CALIBER['clens_y2_pos1'] = np.float(d['clens_y2_pos1'][0]) - CALIBER['clens_p_pos1'] = np.float(d['clens_p_pos1'][0]) - CALIBER['DetU_x_pos1'] = np.float(d['DetU_x_pos1'][0]) - CALIBER['DetU_y_pos1'] = np.float(d['DetU_y_pos1'][0]) - CALIBER['aper_x_pos1'] = np.float(d['aper_x_pos1'][0]) - CALIBER['aper_y_pos1'] = np.float(d['aper_y_pos1'][0]) - - #CALIBER['th2_pos2'] = np.float(d['th2_pos2'][0]) - CALIBER['chi2_pos2'] = np.float(d['chi2_pos2'][0]) - CALIBER['XEng_pos2'] = np.float(d['XEng_pos2'][0]) - CALIBER['zp_x_pos2'] = np.float(d['zp_x_pos2'][0]) - CALIBER['zp_y_pos2'] = np.float(d['zp_y_pos2'][0]) - CALIBER['th2_motor_pos2'] = np.float(d['th2_motor_pos2'][0]) - CALIBER['clens_x_pos2'] = np.float(d['clens_x_pos2'][0]) - CALIBER['clens_y1_pos2'] = np.float(d['clens_y1_pos2'][0]) - CALIBER['clens_y2_pos2'] = np.float(d['clens_y2_pos2'][0]) - CALIBER['clens_p_pos2'] = np.float(d['clens_p_pos2'][0]) - CALIBER['DetU_x_pos2'] = np.float(d['DetU_x_pos2'][0]) - CALIBER['DetU_y_pos2'] = np.float(d['DetU_y_pos2'][0]) - CALIBER['aper_x_pos2'] = np.float(d['aper_x_pos2'][0]) - CALIBER['aper_y_pos2'] = np.float(d['aper_y_pos2'][0]) - - #print(f'pzt_dcm_th2_{CALIBER["XEng_pos1"]:2.4f}\t: {CALIBER["th2_pos1"]:2.4f}') - print(f'pzt_dcm_chi2_{CALIBER["XEng_pos1"]:2.4f} keV\t: {CALIBER["chi2_pos1"]:2.4f}') - print(f'zp_x_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["zp_x_pos1"]:2.4f}') - print(f'zp_y_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["zp_y_pos1"]:2.4f}') - print(f'th2_motor_{CALIBER["XEng_pos1"]:2.4f} keV\t: {CALIBER["th2_motor_pos1"]:2.6f}') - print(f'clens_x_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["clens_x_pos1"]:2.4f}') - print(f'clens_y1_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["clens_y1_pos1"]:2.4f}') - print(f'clens_y2_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["clens_y2_pos1"]:2.4f}') - print(f'clens_p_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["clens_p_pos1"]:2.4f}') - print(f'DetU_x_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["DetU_x_pos1"]:2.4f}') - print(f'DetU_y_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["DetU_y_pos1"]:2.4f}') - print(f'aper_x_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["aper_x_pos1"]:2.4f}') - print(f'aper_y_{CALIBER["XEng_pos1"]:2.4f} keV\t\t: {CALIBER["aper_y_pos1"]:2.4f}') - print('\n') - #print(f'pzt_dcm_th2_{CALIBER["XEng_pos2"]:2.4f}\t: {CALIBER["th2_pos2"]:2.4f}') - print(f'pzt_dcm_chi2_{CALIBER["XEng_pos2"]:2.4f} keV\t: {CALIBER["chi2_pos2"]:2.4f}') - print(f'zp_x_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["zp_x_pos2"]:2.4f}') - print(f'zp_y_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["zp_y_pos2"]:2.4f}') - print(f'th2_motor_{CALIBER["XEng_pos2"]:2.4f} keV\t: {CALIBER["th2_motor_pos2"]:2.6f}') - print(f'clens_x_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["clens_x_pos2"]:2.4f}') - print(f'clens_y1_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["clens_y1_pos2"]:2.4f}') - print(f'clens_y2_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["clens_y2_pos2"]:2.4f}') - print(f'clens_p_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["clens_p_pos2"]:2.4f}') - print(f'DetU_x_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["DetU_x_pos2"]:2.4f}') - print(f'DetU_y_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["DetU_y_pos2"]:2.4f}') - print(f'aper_x_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["aper_x_pos2"]:2.4f}') - print(f'aper_y_{CALIBER["XEng_pos2"]:2.4f} keV\t\t: {CALIBER["aper_y_pos2"]:2.4f}') - except: - print(f'\nreading calibration file: {fn} fails...\n Please optimize optics at two energy points, and using record_calib_pos1() and record_calib_pos2() after optimizing each energy points ') -""" - - def show_global_para(): print(f"GLOBAL_MAG = {GLOBAL_MAG} X") # total magnification print(f"GLOBAL_VLM_MAG = {GLOBAL_VLM_MAG} X") # vlm magnification @@ -645,9 +568,13 @@ def new_user(): PI_name = input("PI's name:") PI_name = PI_name.replace(" ", "_").upper() + if len(PI_name) == 0: + cwd = os.getcwd() + print(f"\nstay at current directory: {cwd}\n") + return if PI_name[0] == "*": cwd = os.getcwd() - print(f"stay at current directory: {cwd}\n") + print(f"\nstay at current directory: {cwd}\n") return if PI_name[:4] == "COMM": PI_name = "FXI_commission" diff --git a/startup/92-run_function_at_start.py b/startup/92-run_function_at_start.py new file mode 100755 index 0000000..8ce848a --- /dev/null +++ b/startup/92-run_function_at_start.py @@ -0,0 +1,5 @@ +new_user() +show_global_para() +run_pdf() +read_calib_file_new() # read file from: /NSLS2/xf18id1/DATA/FXI_log/calib_new.csv +#check_latest_scan_id(init_guess=60000, search_size=100) diff --git a/startup/93-load_scan.py b/startup/93-load_scan.py index 91b1064..7563f99 100755 --- a/startup/93-load_scan.py +++ b/startup/93-load_scan.py @@ -18,14 +18,17 @@ def write_lakeshore_to_file(h, fname): break -def export_scan(scan_id, scan_id_end=None, binning=4): - """ +def export_scan(scan_id, scan_id_end=None, binning=4, date_end_by=None, fpath=None): + ''' e.g. load_scan([0001, 0002]) - """ + ''' if scan_id_end is None: - for item in scan_id: + if isinstance(scan_id, int): + scan_id = [scan_id] + for item in scan_id: try: - export_single_scan(int(item), binning) + #export_single_scan(int(item), binning) + custom_export(int(item), binning, date_end_by=date_end_by, fpath=fpath) except Exception as ex: template = "An exception of type {0} occurred. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) @@ -33,9 +36,10 @@ def export_scan(scan_id, scan_id_end=None, binning=4): continue db.reg.clear_process_cache() else: - for i in range(scan_id, scan_id_end + 1): + for i in range(scan_id, scan_id_end+1): try: - export_single_scan(int(i), binning) + #export_single_scan(int(i), binning) + custom_export(int(i), binning, date_end_by=date_end_by, fpath=fpath) except Exception as ex: template = "An exception of type {0} occurred. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) @@ -44,7 +48,25 @@ def export_scan(scan_id, scan_id_end=None, binning=4): db.reg.clear_process_cache() -def export_single_scan(scan_id=-1, binning=4): +def custom_export(scan_id, binning=4, date_end_by=None, fpath=None): + ''' + date_end_by: string, e.g., '2020-01-20' + ''' + tmp = list(db(scan_id = scan_id)) + n = len(tmp) + if date_end_by is None: + export_single_scan(scan_id, binning) + else: + for sid in tmp: + uid = sid.start['uid'] + timestamp = sid.start['time'] + ts = pd.to_datetime(timestamp, unit='s').tz_localize('US/Eastern') + date_end = covert_date_to_datetime(date_end_by) + if ts < date_end: + export_single_scan(uid, binning) + break + +def export_single_scan(scan_id=-1, binning=4, fpath=None): h = db[scan_id] scan_id = h.start["scan_id"] scan_type = h.start["plan_name"] @@ -52,60 +74,69 @@ def export_single_scan(scan_id=-1, binning=4): if scan_type == "tomo_scan": print("exporting tomo scan: #{}".format(scan_id)) - export_tomo_scan(h) + export_tomo_scan(h, fpath) print("tomo scan: #{} loading finished".format(scan_id)) elif scan_type == "fly_scan": print("exporting fly scan: #{}".format(scan_id)) - export_fly_scan(h) + export_fly_scan(h, fpath) print("fly scan: #{} loading finished".format(scan_id)) + elif scan_type == "fly_scan2": + print("exporting fly scan2: #{}".format(scan_id)) + export_fly_scan2(h, fpath) + print("fly scan2: #{} loading finished".format(scan_id)) elif scan_type == "xanes_scan" or scan_type == "xanes_scan2": print("exporting xanes scan: #{}".format(scan_id)) - export_xanes_scan(h) + export_xanes_scan(h, fpath) print("xanes scan: #{} loading finished".format(scan_id)) elif scan_type == "z_scan": print("exporting z_scan: #{}".format(scan_id)) - export_z_scan(h) + export_z_scan(h, fpath) elif scan_type == "z_scan2": print("exporting z_scan2: #{}".format(scan_id)) - export_z_scan2(h) + export_z_scan2(h, fpath) elif scan_type == "z_scan3": print("exporting z_scan3: #{}".format(scan_id)) - export_z_scan2(h) + export_z_scan2(h, fpath) elif scan_type == "test_scan": print("exporting test_scan: #{}".format(scan_id)) - export_test_scan(h) + export_test_scan(h, fpath) elif scan_type == "multipos_count": print(f"exporting multipos_count: #{scan_id}") - export_multipos_count(h) + export_multipos_count(h, fpath) elif scan_type == "grid2D_rel": print("exporting grid2D_rel: #{}".format(scan_id)) - export_grid2D_rel(h) + export_grid2D_rel(h, fpath) elif scan_type == "raster_2D": print("exporting raster_2D: #{}".format(scan_id)) export_raster_2D(h, binning) elif scan_type == "raster_2D_2": print("exporting raster_2D_2: #{}".format(scan_id)) - export_raster_2D(h, binning) + export_raster_2D(h, binning, fpath) elif scan_type == "count" or scan_type == "delay_count": print("exporting count: #{}".format(scan_id)) - export_count_img(h) + export_count_img(h, fpath) elif scan_type == "multipos_2D_xanes_scan2": print("exporting multipos_2D_xanes_scan2: #{}".format(scan_id)) - export_multipos_2D_xanes_scan2(h) + export_multipos_2D_xanes_scan2(h, fpath) elif scan_type == "multipos_2D_xanes_scan3": print("exporting multipos_2D_xanes_scan3: #{}".format(scan_id)) - export_multipos_2D_xanes_scan3(h) + export_multipos_2D_xanes_scan3(h, fpath) elif scan_type == "delay_scan": print("exporting delay_scan #{}".format(scan_id)) - export_delay_scan(h) - elif scan_type == "user_fly_only": + export_delay_scan(h, fpath) + elif scan_type in ("user_fly_only", "dmea_fly_only"): print("exporting user_fly_only #{}".format(scan_id)) - export_user_fly_only(h) + export_user_fly_only(h, fpath) else: print("Un-recognized scan type ......") -def export_tomo_scan(h): +def export_tomo_scan(h, fpath=None): + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' scan_type = "tomo_scan" scan_id = h.start["scan_id"] try: @@ -130,7 +161,7 @@ def export_tomo_scan(h): # img_bkg_avg = np.mean(img_bkg, axis=0).reshape(1, s[1], s[2]) img_angle = np.linspace(angle_i, angle_e, angle_n) - fname = scan_type + "_id_" + str(scan_id) + ".h5" + fname = fpath + scan_type + "_id_" + str(scan_id) + ".h5" with h5py.File(fname, "w") as hf: hf.create_dataset("scan_id", data=scan_id) hf.create_dataset("X_eng", data=x_eng) @@ -148,7 +179,12 @@ def export_tomo_scan(h): del img_bkg -def export_fly_scan(h): +def export_fly_scan(h, fpath=None): + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' uid = h.start["uid"] note = h.start["note"] scan_type = "fly_scan" @@ -158,6 +194,10 @@ def export_fly_scan(h): y_pos = h.table("baseline")["zps_sy"][1] z_pos = h.table("baseline")["zps_sz"][1] r_pos = h.table("baseline")["zps_pi_r"][1] + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M try: x_eng = h.start["XEng"] @@ -224,10 +264,12 @@ def export_fly_scan(h): mot_pos_interp = np.interp(img_time, mot_time, mot_pos) pos2 = mot_pos_interp.argmax() + 1 - img_angle = mot_pos_interp[: pos2 - chunk_size] # rotation angles - img_tomo = imgs[: pos2 - chunk_size] # tomo images + #img_angle = mot_pos_interp[: pos2 - chunk_size] # rotation angles + img_angle = mot_pos_interp[: pos2] + #img_tomo = imgs[: pos2 - chunk_size] # tomo images + img_tomo = imgs[: pos2] - fname = scan_type + "_id_" + str(scan_id) + ".h5" + fname = fpath + scan_type + "_id_" + str(scan_id) + ".h5" with h5py.File(fname, "w") as hf: hf.create_dataset("note", data=str(note)) @@ -245,6 +287,8 @@ def export_fly_scan(h): hf.create_dataset("y_ini", data=y_pos) hf.create_dataset("z_ini", data=z_pos) hf.create_dataset("r_ini", data=r_pos) + hf.create_dataset("Magnification", data=M) + hf.create_dataset("Pixel Size", data=str(str(pxl_sz)+'nm')) try: write_lakeshore_to_file(h, fname) @@ -256,8 +300,137 @@ def export_fly_scan(h): del img_bkg del imgs +def export_fly_scan2(h, fpath=None): + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' + uid = h.start["uid"] + note = h.start["note"] + scan_type = "fly_scan2" + scan_id = h.start["scan_id"] + scan_time = h.start["time"] + x_pos = h.table("baseline")["zps_sx"][1] + y_pos = h.table("baseline")["zps_sy"][1] + z_pos = h.table("baseline")["zps_sz"][1] + r_pos = h.table("baseline")["zps_pi_r"][1] + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M + + try: + x_eng = h.start["XEng"] + except: + x_eng = h.start["x_ray_energy"] + chunk_size = h.start["chunk_size"] + # sanity check: make sure we remembered the right stream name + assert "zps_pi_r_monitor" in h.stream_names + pos = h.table("zps_pi_r_monitor") +# imgs = list(h.data("Andor_image")) + img_dark = np.array(list(h.data("Andor_image"))[-1][:]) + img_bkg = np.array(list(h.data("Andor_image"))[-2][:]) + s = img_dark.shape + img_dark_avg = np.mean(img_dark, axis=0).reshape(1, s[1], s[2]) + img_bkg_avg = np.mean(img_bkg, axis=0).reshape(1, s[1], s[2]) + + imgs = np.array(list(h.data("Andor_image"))[:-2]) + s1 = imgs.shape + imgs = imgs.reshape([s1[0] * s1[1], s1[2], s1[3]]) + + with db.reg.handler_context({"AD_HDF5": AreaDetectorHDF5TimestampHandler}): + chunked_timestamps = list(h.data("Andor_image")) + + chunked_timestamps = chunked_timestamps[:-2] + raw_timestamps = [] + for chunk in chunked_timestamps: + raw_timestamps.extend(chunk.tolist()) + + timestamps = convert_AD_timestamps(pd.Series(raw_timestamps)) + pos["time"] = pos["time"].dt.tz_localize("US/Eastern") + + img_day, img_hour = ( + timestamps.dt.day, + timestamps.dt.hour, + ) + img_min, img_sec, img_msec = ( + timestamps.dt.minute, + timestamps.dt.second, + timestamps.dt.microsecond, + ) + img_time = ( + img_day * 86400 + img_hour * 3600 + img_min * 60 + img_sec + img_msec * 1e-6 + ) + img_time = np.array(img_time) + + mot_day, mot_hour = ( + pos["time"].dt.day, + pos["time"].dt.hour, + ) + mot_min, mot_sec, mot_msec = ( + pos["time"].dt.minute, + pos["time"].dt.second, + pos["time"].dt.microsecond, + ) + mot_time = ( + mot_day * 86400 + mot_hour * 3600 + mot_min * 60 + mot_sec + mot_msec * 1e-6 + ) + mot_time = np.array(mot_time) + + mot_pos = np.array(pos["zps_pi_r"]) + offset = np.min([np.min(img_time), np.min(mot_time)]) + img_time -= offset + mot_time -= offset + mot_pos_interp = np.interp(img_time, mot_time, mot_pos) + + pos2 = mot_pos_interp.argmax() + 1 + #img_angle = mot_pos_interp[: pos2 - chunk_size] # rotation angles + img_angle = mot_pos_interp[:pos2] + #img_tomo = imgs[: pos2 - chunk_size] # tomo images + img_tomo = imgs[:pos2] + + fname = fpath + scan_type + "_id_" + str(scan_id) + ".h5" + + with h5py.File(fname, "w") as hf: + hf.create_dataset("note", data=str(note)) + hf.create_dataset("uid", data=uid) + hf.create_dataset("scan_id", data=int(scan_id)) + hf.create_dataset("scan_time", data=scan_time) + hf.create_dataset("X_eng", data=x_eng) + hf.create_dataset("img_bkg", data=np.array(img_bkg, dtype=np.uint16)) + hf.create_dataset("img_dark", data=np.array(img_dark, dtype=np.uint16)) + hf.create_dataset("img_bkg_avg", data=np.array(img_bkg_avg, dtype=np.float32)) + hf.create_dataset("img_dark_avg", data=np.array(img_dark_avg, dtype=np.float32)) + hf.create_dataset("img_tomo", data=np.array(img_tomo, dtype=np.uint16)) + hf.create_dataset("angle", data=img_angle) + hf.create_dataset("x_ini", data=x_pos) + hf.create_dataset("y_ini", data=y_pos) + hf.create_dataset("z_ini", data=z_pos) + hf.create_dataset("r_ini", data=r_pos) + hf.create_dataset("Magnification", data=M) + hf.create_dataset("Pixel Size", data=str(str(pxl_sz)+'nm')) + + try: + write_lakeshore_to_file(h, fname) + except: + print("fails to write lakeshore info into {fname}") -def export_xanes_scan(h): + del img_tomo + del img_dark + del img_bkg + del imgs + +def export_xanes_scan(h, fpath=None): + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M scan_type = h.start["plan_name"] # scan_type = 'xanes_scan' uid = h.start["uid"] @@ -303,7 +476,7 @@ def export_xanes_scan(h): img_xanes_norm[np.isinf(img_xanes_norm)] = 0 img_bkg = np.array(img_bkg, dtype=np.float32) # img_xanes_norm = np.array(img_xanes_norm, dtype=np.float32) - fname = scan_type + "_id_" + str(scan_id) + ".h5" + fname = fpath + scan_type + "_id_" + str(scan_id) + ".h5" with h5py.File(fname, "w") as hf: hf.create_dataset("uid", data=uid) hf.create_dataset("scan_id", data=scan_id) @@ -313,6 +486,8 @@ def export_xanes_scan(h): hf.create_dataset("img_bkg", data=np.array(img_bkg_avg, dtype=np.float32)) hf.create_dataset("img_dark", data=np.array(img_dark_avg, dtype=np.float32)) hf.create_dataset("img_xanes", data=np.array(img_xanes_norm, dtype=np.float32)) + hf.create_dataset("Magnification", data=M) + hf.create_dataset("Pixel Size", data=str(pxl_sz)+'nm') try: write_lakeshore_to_file(h, fname) @@ -323,7 +498,16 @@ def export_xanes_scan(h): del img_bkg_avg, imgs, img_xanes_norm -def export_z_scan(h): +def export_z_scan(h, fpath=None): + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M scan_type = h.start["plan_name"] scan_id = h.start["scan_id"] uid = h.start["uid"] @@ -342,7 +526,7 @@ def export_z_scan(h): img_norm[np.isnan(img_norm)] = 0 img_norm[np.isinf(img_norm)] = 0 # fn = h.start['plan_args']['fn'] - fname = scan_type + "_id_" + str(scan_id) + ".h5" + fname = fpath + scan_type + "_id_" + str(scan_id) + ".h5" with h5py.File(fname, "w") as hf: hf.create_dataset("uid", data=uid) hf.create_dataset("scan_id", data=scan_id) @@ -352,6 +536,8 @@ def export_z_scan(h): hf.create_dataset("img_dark", data=img_dark) hf.create_dataset("img", data=img_zscan) hf.create_dataset("img_norm", data=img_norm) + hf.create_dataset("Magnification", data=M) + hf.create_dataset("Pixel Size", data=str(pxl_sz)+'nm') try: write_lakeshore_to_file(h, fname) @@ -361,7 +547,16 @@ def export_z_scan(h): del img, img_zscan, img_bkg, img_dark, img_norm -def export_z_scan2(h): +def export_z_scan2(h, fpath=None): + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M scan_type = h.start["plan_name"] scan_id = h.start["scan_id"] uid = h.start["uid"] @@ -385,7 +580,7 @@ def export_z_scan2(h): img_norm[np.isnan(img_norm)] = 0 img_norm[np.isinf(img_norm)] = 0 - fname = scan_type + "_id_" + str(scan_id) + ".h5" + fname = fpath + scan_type + "_id_" + str(scan_id) + ".h5" with h5py.File(fname, "w") as hf: hf.create_dataset("uid", data=uid) hf.create_dataset("scan_id", data=scan_id) @@ -395,6 +590,8 @@ def export_z_scan2(h): hf.create_dataset("img_dark", data=img_dark) hf.create_dataset("img", data=img_zscan) hf.create_dataset("img_norm", data=np.array(img_norm, dtype=np.float32)) + hf.create_dataset("Magnification", data=M) + hf.create_dataset("Pixel Size", data=str(pxl_sz)+'nm') try: write_lakeshore_to_file(h, fname) @@ -404,7 +601,16 @@ def export_z_scan2(h): del img, img_zscan, img_bkg, img_dark, img_norm -def export_test_scan(h): +def export_test_scan(h, fpath=None): + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M import tifffile scan_type = h.start["plan_name"] @@ -426,8 +632,8 @@ def export_test_scan(h): img_norm[np.isnan(img_norm)] = 0 img_norm[np.isinf(img_norm)] = 0 # fn = h.start['plan_args']['fn'] - fname = scan_type + "_id_" + str(scan_id) + ".h5" - fname_tif = scan_type + "_id_" + str(scan_id) + ".tif" + fname = fpath + scan_type + "_id_" + str(scan_id) + ".h5" + fname_tif = fpath + scan_type + "_id_" + str(scan_id) + ".tif" with h5py.File(fname, "w") as hf: hf.create_dataset("uid", data=uid) hf.create_dataset("scan_id", data=scan_id) @@ -437,6 +643,8 @@ def export_test_scan(h): hf.create_dataset("img_dark", data=img_dark) hf.create_dataset("img", data=np.array(img_test, dtype=np.float32)) hf.create_dataset("img_norm", data=np.array(img_norm, dtype=np.float32)) + hf.create_dataset("Magnification", data=M) + hf.create_dataset("Pixel Size", data=str(pxl_sz)+'nm') # tifffile.imsave(fname_tif, img_norm) try: @@ -447,26 +655,48 @@ def export_test_scan(h): del img, img_test, img_bkg, img_dark, img_norm -def export_count_img(h): +def export_count_img(h, fpath=None): """ load images (e.g. RE(count([Andor], 10)) ) and save to .h5 file """ + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' + try: + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M + except: + M = 0 + pxl_sz = 0 + print('fails to calculate magnification and pxl size') + uid = h.start["uid"] det = h.start["detectors"][0] img = get_img(h, det) scan_id = h.start["scan_id"] - fn = "count_id_" + str(scan_id) + ".h5" + fn = fpath + "count_id_" + str(scan_id) + ".h5" with h5py.File(fn, "w") as hf: hf.create_dataset("img", data=img.astype(np.float32)) hf.create_dataset("uid", data=uid) hf.create_dataset("scan_id", data=scan_id) + hf.create_dataset("Magnification", data=M) + hf.create_dataset("Pixel Size", data=str(pxl_sz)+'nm') try: - write_lakeshore_to_file(h, fname) + write_lakeshore_to_file(h, fn) except: print("fails to write lakeshore info into {fname}") -def export_delay_scan(h): +def export_delay_scan(h, fpath=None): + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' det = h.start["detectors"][0] scan_type = h.start["plan_name"] scan_id = h.start["scan_id"] @@ -477,9 +707,13 @@ def export_delay_scan(h): mot_start = h.start["plan_args"]["start"] mot_stop = h.start["plan_args"]["stop"] mot_steps = h.start["plan_args"]["steps"] + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M if det == "detA1" or det == "Andor": img = get_img(h, det) - fname = scan_type + "_id_" + str(scan_id) + ".h5" + fname = fpath + scan_type + "_id_" + str(scan_id) + ".h5" with h5py.File(fname, "w") as hf: hf.create_dataset("img", data=np.array(img, dtype=np.float32)) hf.create_dataset("uid", data=uid) @@ -490,6 +724,8 @@ def export_delay_scan(h): hf.create_dataset("stop", data=mot_stop) hf.create_dataset("steps", data=mot_steps) hf.create_dataset("motor", data=mot_name) + hf.create_dataset("Magnification", data=M) + hf.create_dataset("Pixel Size", data=str(pxl_sz)+'nm') try: write_lakeshore_to_file(h, fname) except: @@ -498,13 +734,22 @@ def export_delay_scan(h): print("no image stored in this scan") -def export_multipos_count(h): +def export_multipos_count(h, fpath=None): + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' scan_type = h.start["plan_name"] scan_id = h.start["scan_id"] uid = h.start["uid"] num_dark = h.start["num_dark_images"] num_of_position = h.start["num_of_position"] note = h.start["note"] + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M img_raw = list(h.data("Andor_image")) img_dark = np.squeeze(np.array(img_raw[:num_dark])) @@ -524,12 +769,14 @@ def export_multipos_count(h): tmp_img = np.array(img_raw[index + i * 2]) tmp_bkg = np.array(img_raw[index + i * 2 + 1]) img_group[i, j] = (tmp_img - img_dark_avg) / (tmp_bkg - img_dark_avg) - fn = os.getcwd() + "/" - fname = fn + scan_type + "_id_" + str(scan_id) + ".h5" + #fn = os.getcwd() + "/" + fname = fpath + scan_type + "_id_" + str(scan_id) + ".h5" with h5py.File(fname, "w") as hf: hf.create_dataset("uid", data=uid) hf.create_dataset("scan_id", data=scan_id) hf.create_dataset("note", data=str(note)) + hf.create_dataset("Magnification", data=M) + hf.create_dataset("Pixel Size", data=str(pxl_sz)+'nm') for i in range(num_of_position): hf.create_dataset(f"img_pos{i+1}", data=np.squeeze(img_group[i])) try: @@ -538,7 +785,16 @@ def export_multipos_count(h): print("fails to write lakeshore info into {fname}") -def export_grid2D_rel(h): +def export_grid2D_rel(h, fpath=None): + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M uid = h.start["uid"] note = h.start["note"] scan_type = "grid2D_rel" @@ -550,12 +806,13 @@ def export_grid2D_rel(h): img = np.squeeze(np.array(list(h.data("Andor_image")))) fname = scan_type + "_id_" + str(scan_id) - cwd = os.getcwd() + #cwd = os.getcwd() + cwd = fpath try: - os.mkdir(cwd + f"/{fname}") + os.mkdir(cwd + f"{fname}") except: - print(cwd + f"/{name} existed") - fout = cwd + f"/{fname}" + print(cwd + f"{name} existed") + fout = cwd + f"{fname}" for i in range(num1): for j in range(num2): fname_tif = fout + f"_({ij}).tif" @@ -563,10 +820,14 @@ def export_grid2D_rel(h): img.save(fname_tif) -def export_raster_2D_2(h, binning=4): +def export_raster_2D_2(h, binning=4, fpath=None): import tifffile from skimage import io - + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' uid = h.start["uid"] note = h.start["note"] scan_type = "grid2D_rel" @@ -580,6 +841,10 @@ def export_raster_2D_2(h, binning=4): img_sizeX = h.start["plan_args"]["img_sizeX"] img_sizeY = h.start["plan_args"]["img_sizeY"] pix = h.start["plan_args"]["pxl"] + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M img_raw = np.squeeze(np.array(list(h.data("Andor_image")))) img_dark_avg = np.mean(img_raw[:num_dark], axis=0, keepdims=True) @@ -628,17 +893,18 @@ def export_raster_2D_2(h, binning=4): img_patch_bin = bin_ndarray( img_patch, new_shape=(1, int(s[1] / binning), int(s[2] / binning)) ) - fout_h5 = f"raster2D_scan_{scan_id}_binning_{binning}.h5" - fout_tiff = f"raster2D_scan_{scan_id}_binning_{binning}.tiff" - fout_txt = f"raster2D_scan_{scan_id}_cord.txt" + fout_h5 = fpath + f"raster2D_scan_{scan_id}_binning_{binning}.h5" + fout_tiff = fpath + f"raster2D_scan_{scan_id}_binning_{binning}.tiff" + fout_txt = fpath + f"raster2D_scan_{scan_id}_cord.txt" print(f"{pos_file_for_print}") io.imsave(fout_tiff, np.array(img_patch_bin[0], dtype=np.float32)) with open(f"{fout_txt}", "w+") as f: f.writelines(pos_file) # tifffile.imsave(fout_tiff, np.array(img_patch_bin, dtype=np.float32)) num_img = int(x_num) * int(y_num) - cwd = os.getcwd() - new_dir = f"{cwd}/raster_scan_{scan_id}" + #cwd = os.getcwd() + #new_dir = f"{cwd}/raster_scan_{scan_id}" + new_dir = fpath + f"raster_scan_{scan_id}" if not os.path.exists(new_dir): os.mkdir(new_dir) """ @@ -656,14 +922,21 @@ def export_raster_2D_2(h, binning=4): hf.create_dataset("img_dark", data=np.array(img_dark_avg, np.float32)) hf.create_dataset("img_bkg", data=np.array(img_bkg_avg, np.float32)) hf.create_dataset("XEng", data=x_eng) + hf.create_dataset("Magnification", data=M) + hf.create_dataset("Pixel Size", data=str(pxl_sz)+'nm') try: write_lakeshore_to_file(h, fn_h5_save) except: print(f"fails to write lakeshore info into {fn_h5_save}") -def export_raster_2D(h, binning=4): +def export_raster_2D(h, binning=4, fpath=None): import tifffile + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' uid = h.start["uid"] note = h.start["note"] @@ -678,6 +951,10 @@ def export_raster_2D(h, binning=4): img_sizeX = h.start["plan_args"]["img_sizeX"] img_sizeY = h.start["plan_args"]["img_sizeY"] pix = h.start["plan_args"]["pxl"] + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M img_raw = np.squeeze(np.array(list(h.data("Andor_image")))) img_dark_avg = np.mean(img_raw[:num_dark], axis=0, keepdims=True) @@ -715,16 +992,17 @@ def export_raster_2D(h, binning=4): img_patch_bin = bin_ndarray( img_patch, new_shape=(1, int(s[1] / binning), int(s[2] / binning)) ) - fout_h5 = f"raster2D_scan_{scan_id}_binning_{binning}.h5" - fout_tiff = f"raster2D_scan_{scan_id}_binning_{binning}.tiff" - fout_txt = f"raster2D_scan_{scan_id}_cord.txt" + fout_h5 = fpath + f"raster2D_scan_{scan_id}_binning_{binning}.h5" + fout_tiff = fpath + f"raster2D_scan_{scan_id}_binning_{binning}.tiff" + fout_txt = fpath + f"raster2D_scan_{scan_id}_cord.txt" print(f"{pos_file_for_print}") with open(f"{fout_txt}", "w+") as f: f.writelines(pos_file) tifffile.imsave(fout_tiff, np.array(img_patch_bin, dtype=np.float32)) num_img = int(x_num) * int(y_num) - cwd = os.getcwd() - new_dir = f"{cwd}/raster_scan_{scan_id}" + #cwd = os.getcwd() + #new_dir = f"{cwd}/raster_scan_{scan_id}" + new_dir = fpath + f"raster_scan_{scan_id}" if not os.path.exists(new_dir): os.mkdir(new_dir) """ @@ -742,6 +1020,8 @@ def export_raster_2D(h, binning=4): hf.create_dataset("img_dark", data=np.array(img_dark_avg, np.float32)) hf.create_dataset("img_bkg", data=np.array(img_bkg_avg, np.float32)) hf.create_dataset("XEng", data=x_eng) + hf.create_dataset("Magnification", data=M) + hf.create_dataset("Pixel Size", data=str(pxl_sz)+'nm') try: write_lakeshore_to_file(h, fn_h5_save) except: @@ -805,7 +1085,12 @@ def export_multipos_2D_xanes_scan2(h): """ -def export_multipos_2D_xanes_scan2(h): +def export_multipos_2D_xanes_scan2(h, fpath=None): + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' scan_type = h.start["plan_name"] uid = h.start["uid"] note = h.start["note"] @@ -817,6 +1102,10 @@ def export_multipos_2D_xanes_scan2(h): chunk_size = h.start["num_bkg_images"] num_eng = h.start["num_eng"] num_pos = h.start["num_pos"] + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M try: repeat_num = h.start["plan_args"]["repeat_num"] except: @@ -850,7 +1139,8 @@ def export_multipos_2D_xanes_scan2(h): img_bkg[i] - img_dark ) # save data - fn = os.getcwd() + "/" + #fn = os.getcwd() + "/" + fn = fpath for j in range(num_pos): fname = ( f"{fn}{scan_type}_id_{scan_id}_repeat_{repeat:02d}_pos_{j:02d}.h5" @@ -871,6 +1161,8 @@ def export_multipos_2D_xanes_scan2(h): hf.create_dataset( "img_xanes", data=np.array(img_xanes[j], dtype=np.float32) ) + hf.create_dataset("Magnification", data=M) + hf.create_dataset("Pixel Size", data=str(pxl_sz)+'nm') try: write_lakeshore_to_file(h, fname) except: @@ -883,7 +1175,16 @@ def export_multipos_2D_xanes_scan2(h): del imgs -def export_multipos_2D_xanes_scan3(h): +def export_multipos_2D_xanes_scan3(h, fpath=None): + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M scan_type = h.start["plan_name"] uid = h.start["uid"] note = h.start["note"] @@ -917,7 +1218,8 @@ def export_multipos_2D_xanes_scan3(h): for j in range(num_pos): img_xanes[j, i] = (img_xanes[j, i] - img_dark) / (img_bkg[i] - img_dark) # save data - fn = os.getcwd() + "/" + #fn = os.getcwd() + "/" + fn = fpath for j in range(num_pos): fname = f"{fn}{scan_type}_id_{scan_id}_pos_{j}.h5" with h5py.File(fname, "w") as hf: @@ -929,8 +1231,9 @@ def export_multipos_2D_xanes_scan3(h): hf.create_dataset("img_bkg", data=np.array(img_bkg, dtype=np.float32)) hf.create_dataset("img_dark", data=np.array(img_dark, dtype=np.float32)) hf.create_dataset( - "img_xanes", data=np.array(img_xanes[j], dtype=np.float32) - ) + "img_xanes", data=np.array(img_xanes[j], dtype=np.float32)) + hf.create_dataset("Magnification", data=M) + hf.create_dataset("Pixel Size", data=str(pxl_sz)+'nm') try: write_lakeshore_to_file(h, fname) @@ -942,10 +1245,15 @@ def export_multipos_2D_xanes_scan3(h): del imgs -def export_user_fly_only(h): +def export_user_fly_only(h, fpath=None): + if fpath is None: + fpath = './' + else: + if not fpath[-1] == '/': + fpath += '/' uid = h.start["uid"] note = h.start["note"] - scan_type = "user_fly_only" + scan_type = h.start["plan_name"] scan_id = h.start["scan_id"] scan_time = h.start["time"] dark_scan_id = h.start["plan_args"]["dark_scan_id"] @@ -959,13 +1267,13 @@ def export_user_fly_only(h): x_eng = h.start["XEng"] except: x_eng = h.start["x_ray_energy"] - chunk_size = h.start["chunk_size"] # sanity check: make sure we remembered the right stream name assert "zps_pi_r_monitor" in h.stream_names pos = h.table("zps_pi_r_monitor") imgs = np.array(list(h.data("Andor_image"))) s1 = imgs.shape + chunk_size = s1[1] imgs = imgs.reshape(-1, s1[2], s1[3]) # load darks and bkgs @@ -1023,7 +1331,7 @@ def export_user_fly_only(h): img_angle = mot_pos_interp[: pos2 - chunk_size] # rotation angles img_tomo = imgs[: pos2 - chunk_size] # tomo images - fname = "fly_scan_id_" + str(scan_id) + ".h5" + fname = fpath + "fly_scan_id_" + str(scan_id) + ".h5" with h5py.File(fname, "w") as hf: hf.create_dataset("note", data=str(note)) @@ -1051,3 +1359,134 @@ def export_user_fly_only(h): del img_dark del img_bkg del imgs + + +def export_scan_change_expo_time(h, fpath=None, save_range_x=[], save_range_y=[]): + from skimage import io + if fpath is None: + fpath = os.getcwd() + if not fpath[-1] == '/': + fpath += '/' + scan_id = h.start["scan_id"] + fpath += f'scan_{scan_id}/' + fpath_t1 = fpath + 't1/' + fpath_t2 = fpath + 't2/' + os.makedirs(fpath, exist_ok=True, mode=0o777) + os.makedirs(fpath_t1, exist_ok=True, mode=0o777) + os.makedirs(fpath_t2, exist_ok=True, mode=0o777) + + zp_z_pos = h.table("baseline")["zp_z"][1] + DetU_z_pos = h.table("baseline")["DetU_z"][1] + M = (DetU_z_pos/zp_z_pos - 1)*10. + pxl_sz = 6500./M + scan_type = h.start["plan_name"] + uid = h.start["uid"] + note = h.start['plan_args']["note"] + + scan_time = h.start["time"] + x_eng = h.start["x_ray_energy"] + t1 = h.start['plan_args']['t1'] + t2 = h.start['plan_args']['t2'] + + img_sizeX = h.start['plan_args']['img_sizeX'] + img_sizeY = h.start['plan_args']['img_sizeY'] + pxl = h.start['plan_args']['pxl'] + step_x = img_sizeX * pxl + step_y = img_sizeY * pxl + + x_range = h.start['plan_args']['x_range'] + y_range = h.start['plan_args']['y_range'] + + imgs = list(h.data("Andor_image")) + s = imgs[0].shape + + if len(save_range_x)==0: + save_range_x = [0, s[0]] + if len(save_range_y)==0: + save_range_y = [0, s[1]] + + img_dark_t1 = np.median(np.array(imgs[:5]), axis=0) + img_dark_t2 = np.median(np.array(imgs[5:10]), axis=0) + imgs = imgs[10:] + + nx = np.abs(x_range[1] - x_range[0] +1) + ny = np.abs(y_range[1] - y_range[0] +1) + pos_x = np.zeros(nx * ny) + pos_y = pos_x.copy() + + idx = 0 + + for ii in range(nx): + if not ii%100: + print(f'nx = {ii}') + for jj in range(ny): + if not jj%10: + print(f'ny = {jj}') + pos_x[idx] = ii * step_x + pos_y[idx] = jj * step_y + idx += 1 + id_c = ii * ny * (5 + 5 + 2) + jj * (5 + 5 + 2) + img_t1 = imgs[id_c] + img_t2 = imgs[id_c + 1] + img_bkg_t1 = imgs[(id_c+2):(id_c+7)] + img_bkg_t1 = np.median(img_bkg_t1, axis=0) + img_bkg_t2 = imgs[(id_c+7):(id_c+12)] + img_bkg_t2 = np.median(img_bkg_t2, axis=0) + + img_t1_n = (img_t1 - img_dark_t1) / (img_bkg_t1 - img_dark_t1) + img_t2_n = (img_t2 - img_dark_t2) / (img_bkg_t2 - img_dark_t2) + + fsave_t1 = fpath_t1 + f'img_t1_{idx:05d}.tiff' + fsave_t2 = fpath_t2 + f'img_t2_{idx:05d}.tiff' + + im1 = img_t1_n[0, save_range_x[0]:save_range_x[1], save_range_y[0]:save_range_y[1]] + im2 = img_t2_n[0, save_range_x[0]:save_range_x[1], save_range_y[0]:save_range_y[1]] + io.imsave(fsave_t1, im1.astype(np.float32)) + io.imsave(fsave_t2, im2.astype(np.float32)) + with h5py.File(fpath, 'w') as hf: + hf.create_dataset('scan_id', data = scan_id) + hf.create_dataset('scan_type', data = scan_type) + hf.create_dataset('uid', data = uid) + hf.create_dataset('pxl_sz', data = pxl_sz) + hf.create_dataset('note', data = note) + hf.create_dataset('XEng', data = x_eng) + hf.create_dataset('pos_x', data = pos_x) + hf.create_dataset('pos_y', data = pos_y) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/startup/94-tomo_recon.py b/startup/94-tomo_recon.py index 9b80089..1b30e64 100755 --- a/startup/94-tomo_recon.py +++ b/startup/94-tomo_recon.py @@ -12,9 +12,9 @@ def find_rot(fn, thresh=0.05, method=1): sr = StackReg(StackReg.TRANSLATION) f = h5py.File(fn, "r") - angle = np.array(list(f["angle"])) + ang = np.array(list(f["angle"])) img_bkg = np.squeeze(np.array(f["img_bkg_avg"])) - if np.abs(angle[0]) < np.abs(angle[0] - 90): # e.g, rotate from 0 - 180 deg + if np.abs(ang[0]) < np.abs(ang[0] - 90): # e.g, rotate from 0 - 180 deg tmp = np.abs(ang - ang[0] - 180).argmin() else: # e.g.,rotate from -90 - 90 deg tmp = np.abs(ang - np.abs(ang[0])).argmin() diff --git a/startup/98-user_scan.py b/startup/98-user_scan.py index 1b04df3..ee31840 100755 --- a/startup/98-user_scan.py +++ b/startup/98-user_scan.py @@ -56,10 +56,10 @@ def send_email(subject, def select_filters(flts=[]): yield from _close_shutter(simu=False) - for key, item in FILTERS.items(): + for key, item in filters.items(): yield from mv(item, 0) for ii in flts: - yield from mv(FILTERS["filter" + str(ii)], 1) + yield from mv(filters["filter" + str(ii)], 1) def user_scan( @@ -268,7 +268,7 @@ def user_fly_scan( motor_r_out = motor_r_ini + out_r """ motor_r_ini = zps.pi_r.position - motors = [zps.sx, zps.sy, zps.sz, zps.pi_r, zps.pi_x] + motor = [zps.sx, zps.sy, zps.sz, zps.pi_r, zps.pi_x] detectors = [Andor, ic3] offset_angle = -2.0 * rs @@ -277,7 +277,7 @@ def user_fly_scan( # target_rot_angle = current_rot_angle + relative_rot_angle _md = { "detectors": ["Andor"], - "motors": [mot.name for mot in motors], + "motors": [mot.name for mot in motor], "XEng": XEng.position, "ion_chamber": ic3.name, "plan_args": { @@ -312,13 +312,13 @@ def user_fly_scan( print("set rotation speed: {} deg/sec".format(rs)) - @stage_decorator(list(detectors) + motors) + @stage_decorator(list(detectors) + motor) @bpp.monitor_during_decorator([zps.pi_r]) @run_decorator(md=_md) def inner_scan(): # close shutter, dark images: numer=chunk_size (e.g.20) print("\nshutter closed, taking dark images...") - yield from _take_dark_image(detectors, motors, num_dark=1, simu=simu) + yield from _take_dark_image(detectors, motor, num_dark=1, simu=simu) yield from mv(zps.pi_x, 0) yield from mv(zps.pi_r, -50) @@ -330,7 +330,7 @@ def inner_scan(): status = yield from abs_set(zps.pi_r, 50, wait=False) yield from bps.sleep(2) while not status.done: - yield from trigger_and_read(list(detectors) + motors) + yield from trigger_and_read(list(detectors) + motor) # bkg images print("\nTaking background images...") yield from _set_rotation_speed(rs=30) @@ -338,7 +338,7 @@ def inner_scan(): yield from mv(zps.pi_x, 12) yield from mv(zps.pi_r, 70) - yield from trigger_and_read(list(detectors) + motors) + yield from trigger_and_read(list(detectors) + motor) yield from _close_shutter(simu=simu) yield from mv(zps.pi_r, 0) @@ -516,528 +516,233 @@ def multi_pos_3D_xanes( ) insert_text(f"finished 3D xanes scan for {note_pos}") -def mk_eng_list(elem): - if elem.split("_")[-1] == "wl": - eng_list = np.genfromtxt( - "/NSLS2/xf18id1/SW/xanes_ref/" - + elem.split("_")[0] - + "/eng_list_" - + elem.split("_")[0] - + "_s_xanes_standard_21pnt.txt") - elif elem.split("_")[-1] == "101": - eng_list = np.genfromtxt( - "/NSLS2/xf18id1/SW/xanes_ref/" - + elem.split("_")[0] - + "/eng_list_" - + elem.split("_")[0] - + "_xanes_standard_101pnt.txt") - elif elem.split("_")[-1] == "63": - eng_list = np.genfromtxt( - "/NSLS2/xf18id1/SW/xanes_ref/" - + elem.split("_")[0] - + "/eng_list_" - + elem.split("_")[0] - + "_xanes_standard_63pnt.txt") - return eng_list - -def sort_in_pos(in_pos_list): - x_list = [] - y_list = [] - z_list = [] - r_list = [] - for ii in range(len(in_pos_list)): - if in_pos_list[ii][0] is None: - x_list.append(zps.sx.position) - else: - x_list.append(in_pos_list[ii][0]) - - if in_pos_list[ii][1] is None: - y_list.append(zps.sy.position) - else: - y_list.append(in_pos_list[ii][1]) - - if in_pos_list[ii][2] is None: - z_list.append(zps.sz.position) - else: - z_list.append(in_pos_list[ii][2]) - - if in_pos_list[ii][3] is None: - r_list.append(zps.pi_r.position) - else: - r_list.append(in_pos_list[ii][3]) - - return (x_list, y_list, z_list, r_list) - -def multi_edge_xanes( - elements=["Ni_wl"], - scan_type = '3D', - filters={"Ni_filters": [1, 2, 3]}, - exposure_time={"Ni_exp": 0.05}, - relative_rot_angle=185, - rs=1, - in_pos_list = [[0, 0, 0, 0]], - out_pos=[0, 0, 0, 0], - note="", - relative_move_flag=0, - binning = [2, 2], - simu=False): - - x_list, y_list, z_list, r_list = sort_in_pos(in_pos_list) - for elem in elements: - for key in filters.keys(): - if elem.split("_")[0] == key.split("_")[0]: - yield from select_filters(filters[key]) - break - else: - yield from select_filters([]) - for key in exposure_time.keys(): - if elem.split("_")[0] == key.split("_")[0]: - exposure = exposure_time[key] - print(elem, exposure) - break - else: - exposure = 0.05 - print('use default exposure time 0.05s') - eng_list = mk_eng_list(elem) - if scan_type == '2D': - yield from multipos_2D_xanes_scan2(eng_list, - x_list, - y_list, - z_list, - r_list, - out_x=out_pos[0], - out_y=out_pos[1], - out_z=out_pos[2], - out_r=out_pos[3], - exposure_time=exposure, - chunk_size=5, - simu=simu, - relative_move_flag=relative_move_flag, - note=note, - md=None, - sleep_time=0, - binning = [2, 2], - repeat_num=1) - elif scan_type == '3D': - yield from multi_pos_xanes_3D(eng_list, - x_list, - y_list, - z_list, - r_list, - exposure_time=exposure, - relative_rot_angle=relative_rot_angle, - rs=rs, - out_x=out_pos[0], - out_y=out_pos[1], - out_z=out_pos[2], - out_r=out_pos[3], - note=note, - simu=simu, - relative_move_flag=relative_move_flag, - traditional_sequence_flag=1, - sleep_time=0, - binning = [2, 2], - repeat=1) - else: - print('wrong scan type') - return - - -def fly_scan2( - exposure_time=0.1, - start_angle = None, - relative_rot_angle=180, - period=0.15, - chunk_size=20, - out_x=None, - out_y=2000, - out_z=None, - out_r=None, - rs=1, - note="", - simu=False, - relative_move_flag=1, - rot_first_flag=1, - filters=[], - rot_back_velo=30, - md=None, - binning=[1, 1] -): - """ - Inputs: - ------- - exposure_time: float, in unit of sec - - start_angle: float - starting angle - - relative_rot_angle: float, - total rotation angles start from current rotary stage (zps.pi_r) position - - period: float, in unit of sec - period of taking images, "period" should >= "exposure_time" - - chunk_size: int, default setting is 20 - number of images taken for each trigger of Andor camera - - out_x: float, default is 0 - relative movement of sample in "x" direction using zps.sx to move out sample (in unit of um) - NOTE: BE CAUSION THAT IT WILL ROTATE SAMPLE BY "out_r" FIRST, AND THEN MOVE X, Y, Z - - out_y: float, default is 0 - relative movement of sample in "y" direction using zps.sy to move out sample (in unit of um) - NOTE: BE CAUSION THAT IT WILL ROTATE SAMPLE BY "out_r" FIRST, AND THEN MOVE X, Y, Z - - out_z: float, default is 0 - relative movement of sample in "z" direction using zps.sz to move out sample (in unit of um) - NOTE: BE CAUSION THAT IT WILL ROTATE SAMPLE BY "out_r" FIRST, AND THEN MOVE X, Y, Z - - out_r: float, default is 0 - relative movement of sample by rotating "out_r" degrees, using zps.pi_r to move out sample - NOTE: BE CAUSION THAT IT WILL ROTATE SAMPLE BY "out_r" FIRST, AND THEN MOVE X, Y, Z - - rs: float, default is 1 - rotation speed in unit of deg/sec - - note: string - adding note to the scan - - simu: Bool, default is False - True: will simulate closing/open shutter without really closing/opening - False: will really close/open shutter - - """ - global ZONE_PLATE - - motor_x_ini = zps.sx.position - motor_y_ini = zps.sy.position - motor_z_ini = zps.sz.position - motor_r_ini = zps.pi_r.position - - if not (start_angle is None): - yield from mv(zps.pi_r, start_angle) - - if relative_move_flag: - motor_x_out = motor_x_ini + out_x if not (out_x is None) else motor_x_ini - motor_y_out = motor_y_ini + out_y if not (out_y is None) else motor_y_ini - motor_z_out = motor_z_ini + out_z if not (out_z is None) else motor_z_ini - motor_r_out = motor_r_ini + out_r if not (out_r is None) else motor_r_ini - else: - motor_x_out = out_x if not (out_x is None) else motor_x_ini - motor_y_out = out_y if not (out_y is None) else motor_y_ini - motor_z_out = out_z if not (out_z is None) else motor_z_ini - motor_r_out = out_r if not (out_r is None) else motor_r_ini - - motors = [zps.sx, zps.sy, zps.sz, zps.pi_r] - detectors = [Andor, ic3] - offset_angle = -2 * rs - current_rot_angle = zps.pi_r.position - - target_rot_angle = current_rot_angle + relative_rot_angle - _md = { - "detectors": ["Andor"], - "motors": [mot.name for mot in motors], - "XEng": XEng.position, - "ion_chamber": ic3.name, - "plan_args": { - "exposure_time": exposure_time, - "start_angle": start_angle, - "relative_rot_angle": relative_rot_angle, - "period": period, - "chunk_size": chunk_size, - "out_x": out_x, - "out_y": out_y, - "out_z": out_z, - "out_r": out_r, - "rs": rs, - "relative_move_flag": relative_move_flag, - "rot_first_flag": rot_first_flag, - "filters": [filt.name for filt in filters] if filters else "None", - "note": note if note else "None", - "zone_plate": ZONE_PLATE, - }, - "plan_name": "fly_scan2", - "num_bkg_images": 20, - "num_dark_images": 20, - "chunk_size": chunk_size, - "plan_pattern": "linspace", - "plan_pattern_module": "numpy", - "hints": {}, - "operator": "FXI", - "note": note if note else "None", - "zone_plate": ZONE_PLATE, - #'motor_pos': wh_pos(print_on_screen=0), - } - _md.update(md or {}) - try: - dimensions = [(zps.pi_r.hints["fields"], "primary")] - except (AttributeError, KeyError): - pass - else: - _md["hints"].setdefault("dimensions", dimensions) - - yield from mv(Andor.cam.acquire, 0) - yield from mv(Andor.cam.bin_y, binning[0], - Andor.cam.bin_x, binning[1]) - yield from abs_set(Andor.cam.acquire_time, exposure_time, wait=True) -# yield from abs_set(Andor.cam.acquire_period, period, wait=True) - Andor.cam.acquire_period.put(period) - -# yield from _set_andor_param( -# exposure_time=exposure_time, period=period, chunk_size=chunk_size -# ) - yield from _set_rotation_speed(rs=rs) - print("set rotation speed: {} deg/sec".format(rs)) - - # We manually stage the Andor detector below. See there for why.... - # Stage everything else here in the usual way. - @stage_decorator([ic3] + motors]) - @bpp.monitor_during_decorator([zps.pi_r]) - @run_decorator(md=_md) - def fly_inner_scan(): - # set filters - for flt in filters: - yield from mv(flt, 1) - yield from mv(flt, 1) - yield from abs_set(Andor.cam.num_images, chunk_size, wait=True) - - # Manually stage the Andor. This creates a Resource document that - # contains the path to the HDF5 file where the detector writes. It also - # encodes the so-called 'frame_per_point' which here is what this plan - # calls chunk_size. The chunk_size CANNOT BE CHANGED later in the scan - # unless we unstage and re-stage the detector and generate a new - # Resource document. - - # This approach imposes some unfortunate overhead (closing the HDF5 - # file, opening a new one, going through all the steps to set the Area - # Detector's filepath PV, etc.). A better approach has been sketched - # in https://github.com/bluesky/area-detector-handlers/pull/11. It - # allows a single HDF5 file to contain multiple chunk_sizes. - - yield from bps.stage(Andor) - yield from bps.sleep(1) - - # open shutter, tomo_images - yield from _open_shutter(simu=simu) - print("\nshutter opened, taking tomo images...") - yield from mv(zps.pi_r, current_rot_angle + offset_angle) - status = yield from abs_set(zps.pi_r, target_rot_angle, wait=False) - yield from bps.sleep(2) - while not status.done: - yield from trigger_and_read(list(detectors) + motors) - - # bkg images - print("\nTaking background images...") - yield from _set_rotation_speed(rs=rot_back_velo) - yield from abs_set(Andor.cam.num_images, 20, wait=True) - - # Now that the new chunk_size has been set (20) create a new Resource - # document by unstage and re-staging the detector. - yield from bps.unstage(Andor) - yield from bps.stage(Andor) - - yield from bps.sleep(1) - yield from _take_bkg_image( - motor_x_out, - motor_y_out, - motor_z_out, - motor_r_out, - detectors, - motors, - num_bkg=1, - simu=False, - traditional_sequence_flag=rot_first_flag, - ) - - # dark images - yield from _close_shutter(simu=simu) - print("\nshutter closed, taking dark images...") - yield from _take_dark_image(detectors, motors, num_dark=1, simu=simu) - - yield from bps.unstage(Andor) - - # restore fliters - yield from _move_sample_in( - motor_x_ini, - motor_y_ini, - motor_z_ini, - motor_r_ini, - trans_first_flag=rot_first_flag, - ) - for flt in filters: - yield from mv(flt, 0) - - yield from fly_inner_scan() - yield from mv(Andor.cam.image_mode, 1) - print("scan finished") - txt = get_scan_parameter(print_flag=0) - insert_text(txt) - print(txt) - -def dummy_scan( exposure_time=0.1, - start_angle = None, - relative_rot_angle=180, - period=0.15, - out_x=None, - out_y=2000, - out_z=None, - out_r=None, - rs=1, - note="", - simu=False, - relative_move_flag=1, - rot_first_flag=1, - filters=[], - rot_back_velo=30, - repeat=1): - - motor_x_ini = zps.sx.position - motor_y_ini = zps.sy.position - motor_z_ini = zps.sz.position - motor_r_ini = zps.pi_r.position - - if not (start_angle is None): - yield from mv(zps.pi_r, start_angle) - - if relative_move_flag: - motor_x_out = motor_x_ini + out_x if not (out_x is None) else motor_x_ini - motor_y_out = motor_y_ini + out_y if not (out_y is None) else motor_y_ini - motor_z_out = motor_z_ini + out_z if not (out_z is None) else motor_z_ini - motor_r_out = motor_r_ini + out_r if not (out_r is None) else motor_r_ini - else: - motor_x_out = out_x if not (out_x is None) else motor_x_ini - motor_y_out = out_y if not (out_y is None) else motor_y_ini - motor_z_out = out_z if not (out_z is None) else motor_z_ini - motor_r_out = out_r if not (out_r is None) else motor_r_ini - - motors = [zps.sx, zps.sy, zps.sz, zps.pi_r] - - detectors = [Andor, ic3] - offset_angle = -2 * rs - current_rot_angle = zps.pi_r.position - - target_rot_angle = current_rot_angle + relative_rot_angle - _md={'dummy scan':'dummy scan'} - - yield from mv(Andor.cam.acquire, 0) - yield from _set_andor_param( - exposure_time=exposure_time, period=period - ) - yield from mv(Andor.cam.image_mode, 1) - yield from mv(Andor.cam.acquire, 1) - - yield from _set_rotation_speed(rs=rs) - print("set rotation speed: {} deg/sec".format(rs)) - - @stage_decorator(motors) - @bpp.monitor_during_decorator([zps.pi_r]) - @run_decorator(md=_md) - def fly_inner_scan(): - # open shutter, tomo_images - yield from _open_shutter(simu=simu) - print("\nshutter opened, taking tomo images...") - yield from mv(zps.pi_r, current_rot_angle + offset_angle) - status = yield from abs_set(zps.pi_r, target_rot_angle, wait=False) - while not status.done: - yield from bps.sleep(1) - status = yield from abs_set(zps.pi_r, current_rot_angle + offset_angle, wait=False) - while not status.done: - yield from bps.sleep(1) - for ii in range(repeat): - yield from fly_inner_scan() - yield from _set_rotation_speed(rs=rot_back_velo) - print("dummy scan finished") - -def radiographic_record(exp_t=0.1, period=0.1, t_span=10, stop=True, - out_x=None, out_y=None, out_z=None, out_r=None, - filters=[], md={}, note="", simu=False, - rot_first_flag=1, relative_move_flag=1): - motor_x_ini = zps.sx.position - motor_y_ini = zps.sy.position - motor_z_ini = zps.sz.position - motor_r_ini = zps.pi_r.position - - if relative_move_flag: - motor_x_out = motor_x_ini + out_x if not (out_x is None) else motor_x_ini - motor_y_out = motor_y_ini + out_y if not (out_y is None) else motor_y_ini - motor_z_out = motor_z_ini + out_z if not (out_z is None) else motor_z_ini - motor_r_out = motor_r_ini + out_r if not (out_r is None) else motor_r_ini - else: - motor_x_out = out_x if not (out_x is None) else motor_x_ini - motor_y_out = out_y if not (out_y is None) else motor_y_ini - motor_z_out = out_z if not (out_z is None) else motor_z_ini - motor_r_out = out_r if not (out_r is None) else motor_r_ini +# def multi_pos_2D_and_3D_xanes(elements=['Ni'], sam_in_pos_list_2D=[[[0, 0, 0, 0],]], sam_out_pos_list_2D=[[[0, 0, 0, 0],]], sam_in_pos_list_3D=[[[0, 0, 0, 0],]], sam_out_pos_list_3D=[[[0, 0, 0, 0],]], exposure_time=[0.05], relative_rot_angle=182, relative_move_flag=False, rs=1, note=''): +# sam_in_pos_list_2D = np.asarray(sam_in_pos_list_2D) +# sam_out_pos_list_2D = np.asarray(sam_out_pos_list_2D) +# sam_in_pos_list_3D = np.asarray(sam_in_pos_list_3D) +# sam_out_pos_list_3D = np.asarray(sam_out_pos_list_3D) +# exposure_time = np.asarray(exposure_time) +# if exposure_time.shape[0] == 1: +# exposure_time = np.ones(len(elements))*exposure_time[0] +# elif len(elements) != exposure_time.shape[0]: +# # to do in bs manner +# pass +# +# eng_list = [] +# for ii in elements: +# eng_list.append(list(np.genfromtxt('/NSLS2/xf18id1/SW/xanes_ref/'+ii+'/eng_list_'+ii+'_xanes_standard.txt'))) +# +# for ii in range(sam_in_pos_list_2D.shape[0]): +# for jj in range(len(elements)): +# x_list = [sam_in_pos_list_2D[ii, :, 0]] +# y_list = [sam_in_pos_list_2D[ii, :, 1]] +# z_list = [sam_in_pos_list_2D[ii, :, 2]] +# r_list = [sam_in_pos_list_2D[ii, :, 3]] +# out_x = sam_out_pos_list_2D[ii, :, 0] +# out_y = sam_out_pos_list_2D[ii, :, 1] +# out_z = sam_out_pos_list_2D[ii, :, 2] +# out_r = sam_out_pos_list_2D[ii, :, 3] +# yield from multipos_2D_xanes_scan2(eng_list[jj], x_list, y_list, z_list, r_list, +# out_x=out_x, out_y=out_y, out_z=out_z, out_r=out_r, +# exposure_time=exposure_time[jj], chunk_size=5, +# simu=False, relative_move_flag=relative_move_flag, note=note, md=None, sleep_time=0, repeat_num=1) +# +# for ii in range(sam_in_pos_list_3D.shape[0]): +# for jj in range(len(elements)): +# x_list = [sam_in_pos_list_3D[ii, :, 0]] +# y_list = [sam_in_pos_list_3D[ii, :, 1]] +# z_list = [sam_in_pos_list_3D[ii, :, 2]] +# r_list = [sam_in_pos_list_3D[ii, :, 3]] +# out_x = sam_out_pos_list_3D[ii, :, 0] +# out_y = sam_out_pos_list_3D[ii, :, 1] +# out_z = sam_out_pos_list_3D[ii, :, 2] +# out_r = sam_out_pos_list_3D[ii, :, 3] +# yield from multi_pos_3D_xanes(eng_list[jj], x_list, y_list, z_list, r_list, +# exposure_time=exposure_time[jj], relative_rot_angle=relative_rot_angle, rs=rs, +# out_x=out_x, out_y=out_y, out_z=out_z, out_r=out_r, note=note, simu=False, +# relative_move_flag=relative_move_flag, traditional_sequence_flag=1, sleep_time=0, repeat=1) + + +# def multi_pos_2D_xanes_and_3D_tomo(elements=['Ni'], sam_in_pos_list_2D=[[[0, 0, 0, 0]]], sam_out_pos_list_2D=[[[0, 0, 0, 0]]], sam_in_pos_list_3D=[[[0, 0, 0, 0]]], sam_out_pos_list_3D=[[[0, 0, 0, 0]]], +# exposure_time_2D=[0.05], exposure_time_3D=[0.05], relative_rot_angle=182, rs=1, eng_3D=[8.4], note='', relative_move_flag=False): +# sam_in_pos_list_2D = np.asarray(sam_in_pos_list_2D) +# sam_out_pos_list_2D = np.asarray(sam_out_pos_list_2D) +# sam_in_pos_list_3D = np.asarray(sam_in_pos_list_3D) +# sam_out_pos_list_3D = np.asarray(sam_out_pos_list_3D) +# exposure_time_2D = np.asarray(exposure_time_2D) +# exposure_time_3D = np.asarray(exposure_time_3D) +# if exposure_time_2D.shape[0] == 1: +# exposure_time_2D = np.ones(len(elements))*exposure_time_2D[0] +# elif len(elements) != exposure_time_2D.shape[0]: +# # to do in bs manner +# pass +# +# if exposure_time_3D.shape[0] == 1: +# exposure_time_3D = np.ones(len(elements))*exposure_time_3D[0] +# elif len(elements) != exposure_time_3D.shape[0]: +# # to do in bs manner +# pass +# +# eng_list = [] +# for ii in elements: +# eng_list.append(list(np.genfromtxt('/NSLS2/xf18id1/SW/xanes_ref/'+ii+'/eng_list_'+ii+'_xanes_standard.txt'))) +# +# for ii in range(sam_in_pos_list_2D.shape[0]): +# for jj in range(len(elements)): +# x_list = sam_in_pos_list_2D[ii, :, 0] +# y_list = sam_in_pos_list_2D[ii, :, 1] +# z_list = sam_in_pos_list_2D[ii, :, 2] +# r_list = sam_in_pos_list_2D[ii, :, 3] +# out_x = sam_out_pos_list_2D[ii, 0] +# out_y = sam_out_pos_list_2D[ii, 1] +# out_z = sam_out_pos_list_2D[ii, 2] +# out_r = sam_out_pos_list_2D[ii, 3] +# print(x_list) +# print(y_list) +# print(z_list) +# print(r_list) +# print(out_x) +# print(out_y) +# print(out_z) +# print(out_r) +# yield from multipos_2D_xanes_scan2(eng_list[jj], x_list, y_list, z_list, r_list, +# out_x=out_x, out_y=out_y, out_z=out_z, out_r=out_r, +# exposure_time=exposure_time_2D[jj], chunk_size=5, +# simu=False, relative_move_flag=relative_move_flag, note=note, md=None, sleep_time=0, repeat_num=1) +# +# for ii in range(sam_in_pos_list_3D.shape[0]): +# for jj in range(len(elements)): +# x_list = sam_in_pos_list_3D[ii, :, 0] +# y_list = sam_in_pos_list_3D[ii, :, 1] +# z_list = sam_in_pos_list_3D[ii, :, 2] +# r_list = sam_in_pos_list_3D[ii, :, 3] +# out_x = sam_out_pos_list_3D[ii, 0] +# out_y = sam_out_pos_list_3D[ii, 1] +# out_z = sam_out_pos_list_3D[ii, 2] +# out_r = sam_out_pos_list_3D[ii, 3] +# yield from multi_pos_xanes_3D(eng_3D, x_list, y_list, z_list, r_list, +# exposure_time=exposure_time_3D[jj], relative_rot_angle=relative_rot_angle, rs=rs, +# out_x=out_x, out_y=out_y, out_z=out_z, out_r=out_r, note=note, simu=False, +# relative_move_flag=relative_move_flag, traditional_sequence_flag=1, sleep_time=0, repeat=1) + + +############ old routine: 2D routine works but 3D routine has some bugs -- start +# def multi_pos_2D_and_3D_xanes(elements=['Ni_short'], filters=[[1, 2, 3]], sam_in_pos_list_2D=[[[0, 0, 0, 0]]], sam_out_pos_list_2D=[[[0, 0, 0, 0]]], sam_in_pos_list_3D=[[[0, 0, 0, 0]]], sam_out_pos_list_3D=[[[0, 0, 0, 0]]], +# exposure_time_2D=[0.05], exposure_time_3D=[0.05], relative_rot_angle=182, rs=1, sleep_time=0, repeat_num=1, note='', relative_move_flag=0, simu=False): +# """ +# pos_list layer structure: 1st layer -> energy +# 2nd layer -> multiple positions at the given energy +# 3rd layer -> individual postion in the multiple poistion list +# """ +# for kk in range(repeat_num): +# sam_in_pos_list_2D = np.asarray(sam_in_pos_list_2D) +# sam_out_pos_list_2D = np.asarray(sam_out_pos_list_2D) +# sam_in_pos_list_3D = np.asarray(sam_in_pos_list_3D) +# sam_out_pos_list_3D = np.asarray(sam_out_pos_list_3D) +# exposure_time_2D = np.asarray(exposure_time_2D) +# exposure_time_3D = np.asarray(exposure_time_3D) +# if exposure_time_2D.shape[0] == 1: +# exposure_time_2D = np.ones(len(elements))*exposure_time_2D[0] +# elif len(elements) != exposure_time_2D.shape[0]: +# # to do in bs manner +# pass +# +# if exposure_time_3D.shape[0] == 1: +# exposure_time_3D = np.ones(len(elements))*exposure_time_3D[0] +# elif len(elements) != exposure_time_3D.shape[0]: +# # to do in bs manner +# pass +# +# eng_list = [] +# for ii in elements: +# if ii.split('_')[1] == 'wl': +# eng_list.append(list(np.genfromtxt('/NSLS2/xf18id1/SW/xanes_ref/'+ii.split('_')[0]+'/eng_list_'+ii.split('_')[0]+'_s_xanes_standard_21pnt.txt'))) +# elif ii.split('_')[1] == '101': +# eng_list.append(list(np.genfromtxt('/NSLS2/xf18id1/SW/xanes_ref/'+ii+'/eng_list_'+ii+'_xanes_standard_101pnt.txt'))) +# elif ii.split('_')[1] == '63': +# eng_list.append(list(np.genfromtxt('/NSLS2/xf18id1/SW/xanes_ref/'+ii+'/eng_list_'+ii+'_xanes_standard_63pnt.txt'))) +# +# eng_list = np.array(eng_list) +# +# if sam_in_pos_list_2D.size != 0: +# for ii in range(sam_in_pos_list_2D.shape[0]): +# for jj in range(len(elements)): +# if filters[jj]: +# select_filters(filters[jj]) +## yield from _close_shutter(simu=simu) +## yield from mv(filter1, 0) +## yield from mv(filter2, 0) +## yield from mv(filter3, 0) +## yield from mv(filter4, 0) +## for flt in filters[jj]: +## if flt == 'filter1': +## yield from mv(filter1, 1) +## elif flt == 'filter2': +## yield from mv(filter2, 1) +## elif flt == 'filter3': +## yield from mv(filter3, 1) +## elif flt == 'filter4': +## yield from mv(filter4, 1) +# x_list = sam_in_pos_list_2D[ii, :, 0] +# y_list = sam_in_pos_list_2D[ii, :, 1] +# z_list = sam_in_pos_list_2D[ii, :, 2] +# r_list = sam_in_pos_list_2D[ii, :, 3] +# out_x = sam_out_pos_list_2D[ii, :, 0] +# out_y = sam_out_pos_list_2D[ii, :, 1] +# out_z = sam_out_pos_list_2D[ii, :, 2] +# out_r = sam_out_pos_list_2D[ii, :, 3] +# print(x_list) +# print(y_list) +# print(z_list) +# print(r_list) +# print(out_x) +# print(out_y) +# print(out_z) +# print(out_r) +# yield from multipos_2D_xanes_scan2(eng_list[jj], x_list, y_list, z_list, r_list, +# out_x=out_x, out_y=out_y, out_z=out_z, out_r=out_r, +# exposure_time=exposure_time_2D[jj], chunk_size=5, +# simu=simu, relative_move_flag=relative_move_flag, note=note, md=None, sleep_time=0, repeat_num=1) +# +# if sam_in_pos_list_3D.size != 0: +# for ii in range(sam_in_pos_list_3D.shape[0]): +# for jj in range(len(elements)): +# if filters[jj]: +# select_filters(filters[jj]) +## yield from _close_shutter(simu=simu) +## yield from mv(filter1, 0) +## yield from mv(filter2, 0) +## yield from mv(filter3, 0) +## yield from mv(filter4, 0) +## for flt in filters[jj]: +## if flt == 'filter1': +## yield from mv(filter1, 1) +## elif flt == 'filter2': +## yield from mv(filter2, 1) +## elif flt == 'filter3': +## yield from mv(filter3, 1) +## elif flt == 'filter4': +## yield from mv(filter4, 1) +# x_list = sam_in_pos_list_3D[ii, :, 0] +# y_list = sam_in_pos_list_3D[ii, :, 1] +# z_list = sam_in_pos_list_3D[ii, :, 2] +# r_list = sam_in_pos_list_3D[ii, :, 3] +# out_x = sam_out_pos_list_3D[ii, :, 0] +# out_y = sam_out_pos_list_3D[ii, :, 1] +# out_z = sam_out_pos_list_3D[ii, :, 2] +# out_r = sam_out_pos_list_3D[ii, :, 3] +# print(x_list, out_x, out_y, out_z, out_r) +# yield from multi_pos_xanes_3D(eng_list[jj], x_list, y_list, z_list, r_list, +# exposure_time=exposure_time_3D[jj], relative_rot_angle=relative_rot_angle, rs=rs, +# out_x=out_x, out_y=out_y, out_z=out_z, out_r=out_r, note=note, simu=simu, +# relative_move_flag=relative_move_flag, traditional_sequence_flag=1, sleep_time=0, repeat=1) +# if kk != (repeat_num-1): +# print(f'We are in multi_pos_2D_and_3D_xanes cycle # {kk}; we are going to sleep for {sleep_time} seconds ...') +# yield from bps.sleep(sleep_time) +############ old routine: 2D routine works but 3D routine has some bugs -- end - motors = [zps.sx, zps.sy, zps.sz, zps.pi_r] - - detectors = [Andor, ic3] - _md = { - "detectors": ["Andor"], -# "motors": [mot.name for mot in motors], - "XEng": XEng.position, - "ion_chamber": ic3.name, - "plan_args": { - "exposure_time": exp_t, - "period": period, - "out_x": out_x, - "out_y": out_y, - "out_z": out_z, - "out_r": out_r, - "time_span": t_span, - "filters": [filt.name for filt in filters] if filters else "None", - "note": note if note else "None", - "zone_plate": ZONE_PLATE, - }, - "plan_name": "radiographic_record", - "num_bkg_images": 20, - "num_dark_images": 20, - "plan_pattern": "linspace", - "plan_pattern_module": "numpy", - "hints": {}, - "operator": "FXI", - "note": note if note else "None", - "zone_plate": ZONE_PLATE - } - _md.update(md or {}) - yield from mv(Andor.cam.acquire, 0) - yield from _set_andor_param( - exposure_time=exp_t, period=period - ) - yield from mv(Andor.cam.image_mode, 0) - - @stage_decorator(list(detectors)) -# @bpp.monitor_during_decorator([Andor.cam.num_images_counter]) - @run_decorator(md=_md) - def rad_record_inner(): - yield from _open_shutter(simu=simu) - for flt in filters: - yield from mv(flt, 1) - yield from mv(flt, 1) - yield from bps.sleep(1) - - yield from mv(Andor.cam.num_images, int(t_span/period)) - yield from trigger_and_read([Andor]) - - yield from mv(zps.sx, motor_x_out, - zps.sy, motor_y_out, - zps.sz, motor_z_out, - zps.pi_r, motor_r_out) - yield from mv(Andor.cam.num_images,20) - yield from trigger_and_read([Andor]) - yield from _close_shutter(simu=simu) - yield from mv(zps.sx, motor_x_ini, - zps.sy, motor_y_ini, - zps.sz, motor_z_ini, - zps.pi_r, motor_r_ini) - yield from trigger_and_read([Andor]) - yield from mv(Andor.cam.image_mode, 1) - for flt in filters: - yield from mv(flt, 0) - - yield from rad_record_inner() - def multi_pos_2D_and_3D_xanes( elements=["Ni_wl"], filters={"Ni_filters": [1, 2, 3]}, @@ -1083,6 +788,7 @@ def multi_pos_2D_and_3D_xanes( xanes2D[elem+'_2D']['out_pos_defined'] & xanes2D[elem+'_2D']['exposure_defined']): print(elem+' 2D scan setup is not correct. Quit.') + sys.exit() for elem in elements: ### if there is a filter combination is defined for the element for key, item in sam_in_pos_list_3D.items(): @@ -1108,6 +814,7 @@ def multi_pos_2D_and_3D_xanes( xanes3D[elem+'_3D']['out_pos_defined'] & xanes3D[elem+'_3D']['exposure_defined']): print(elem+' 3D scan setup is not correct. Quit.') + sys.exit() for elem2D in xanes2D: x_list_2D = [] y_list_2D = [] @@ -2232,7 +1939,7 @@ def user_fly_scan( motor_z_out = out_z if out_z else motor_z_ini motor_r_out = out_r if out_r else motor_r_ini - motors = [zps.sx, zps.sy, zps.sz, zps.pi_r] + motor = [zps.sx, zps.sy, zps.sz, zps.pi_r] detectors = [Andor, ic3] offset_angle = -0.5 * rs @@ -2241,7 +1948,7 @@ def user_fly_scan( target_rot_angle = current_rot_angle + relative_rot_angle _md = { "detectors": ["Andor"], - "motors": [mot.name for mot in motors], + "motors": [mot.name for mot in motor], "XEng": XEng.position, "ion_chamber": ic3.name, "plan_args": { @@ -2284,7 +1991,7 @@ def user_fly_scan( yield from _set_rotation_speed(rs=rs) print("set rotation speed: {} deg/sec".format(rs)) - @stage_decorator(list(detectors) + motors) + @stage_decorator(list(detectors) + motor) @bpp.monitor_during_decorator([zps.pi_r]) @run_decorator(md=_md) def fly_inner_scan(): @@ -2293,7 +2000,7 @@ def fly_inner_scan(): yield from _set_andor_param( exposure_time=exposure_time, period=period, chunk_size=20 ) - yield from _take_dark_image(detectors, motors, num_dark=1, simu=simu) + yield from _take_dark_image(detectors, motor, num_dark=1, simu=simu) yield from bps.sleep(1) yield from _set_andor_param( exposure_time=exposure_time, period=period, chunk_size=chunk_size @@ -2306,7 +2013,7 @@ def fly_inner_scan(): status = yield from abs_set(zps.pi_r, target_rot_angle, wait=False) yield from bps.sleep(1) while not status.done: - yield from trigger_and_read(list(detectors) + motors) + yield from trigger_and_read(list(detectors) + motor) # bkg images print("\nTaking background images...") yield from _set_rotation_speed(rs=30) @@ -2324,7 +2031,7 @@ def fly_inner_scan(): motor_z_out, motor_r_out, detectors, - motors, + motor, num_bkg=1, simu=False, traditional_sequence_flag=traditional_sequence_flag, @@ -2368,7 +2075,7 @@ def user_fly_only( motor_z_ini = zps.sz.position motor_r_ini = zps.pi_r.position - motors = [zps.sx, zps.sy, zps.sz, zps.pi_r] + motor = [zps.sx, zps.sy, zps.sz, zps.pi_r] detectors = [Andor, ic3] # offset_angle = 0 #-0.5 * rs * np.sign(relative_rot_angle) @@ -2377,7 +2084,7 @@ def user_fly_only( target_rot_angle = end_rot_angle _md = { "detectors": ["Andor"], - "motors": [mot.name for mot in motors], + "motors": [mot.name for mot in motor], "XEng": XEng.position, "ion_chamber": ic3.name, "plan_args": { @@ -2415,14 +2122,14 @@ def user_fly_only( yield from _set_rotation_speed(rs=rs) print("set rotation speed: {} deg/sec".format(rs)) - @stage_decorator(list(detectors) + motors) + @stage_decorator(list(detectors) + motor) @bpp.monitor_during_decorator([zps.pi_r]) @run_decorator(md=_md) def fly_inner_scan(): yield from _open_shutter(simu=simu) status = yield from abs_set(zps.pi_r, target_rot_angle, wait=False) while not status.done: - yield from trigger_and_read(list(detectors) + motors) + yield from trigger_and_read(list(detectors) + motor) uid = yield from fly_inner_scan() yield from mv(Andor.cam.image_mode, 1) @@ -2456,7 +2163,7 @@ def user_dark_only(exposure_time=0.1, chunk_size=20, note="", simu=False, md=Non global ZONE_PLATE period = exposure_time # default to exposure time for backgrounds detectors = [Andor, ic3] - motors = [] + motor = [] _md = { "detectors": ["Andor"], @@ -2490,13 +2197,13 @@ def user_dark_only(exposure_time=0.1, chunk_size=20, note="", simu=False, md=Non exposure_time=exposure_time, period=period, chunk_size=chunk_size ) - @stage_decorator(list(detectors) + motors) + @stage_decorator(list(detectors) + motor) @run_decorator(md=_md) def inner_scan(): yield from _set_andor_param( exposure_time=exposure_time, period=period, chunk_size=chunk_size ) - yield from _take_dark_image(detectors, motors, num_dark=1, simu=simu) + yield from _take_dark_image(detectors, motor, num_dark=1, simu=simu) uid = yield from inner_scan() yield from mv(Andor.cam.image_mode, 1) @@ -2572,14 +2279,14 @@ def user_bkg_only( motor_z_out = out_z if out_z else motor_z_ini motor_r_out = out_r if out_r else motor_r_ini - motors = [zps.sx, zps.sy, zps.sz, zps.pi_r] + motor = [zps.sx, zps.sy, zps.sz, zps.pi_r] detectors = [Andor, ic3] current_rot_angle = zps.pi_r.position _md = { "detectors": ["Andor"], - "motors": [mot.name for mot in motors], + "motors": [mot.name for mot in motor], "XEng": XEng.position, "ion_chamber": ic3.name, "plan_args": { @@ -2614,7 +2321,7 @@ def user_bkg_only( # yield from _set_andor_param(exposure_time=exposure_time, period=period, chunk_size=chunk_size) - @stage_decorator(list(detectors) + motors) + @stage_decorator(list(detectors) + motor) @bpp.monitor_during_decorator([zps.pi_r]) @run_decorator(md=_md) def fly_inner_scan(): @@ -2628,7 +2335,7 @@ def fly_inner_scan(): motor_z_out, motor_r_out, detectors, - motors, + motor, num_bkg=1, simu=False, traditional_sequence_flag=traditional_sequence_flag, @@ -3014,7 +2721,119 @@ def ming(): +def scan_change_expo_time(x_range, y_range, t1, t2, out_x=None, out_y=None, out_z=None, out_r=None, img_sizeX=2560, img_sizeY=2160, pxl=20, relative_move_flag=1, note='', simu=False, sleep_time=0, md=None): + ''' + take image + ''' + motor_x_ini = zps.sx.position + motor_y_ini = zps.sy.position + motor_z_ini = zps.sz.position + motor_r_ini = zps.pi_r.position + + detectors = [Andor, ic3] + + if relative_move_flag: + motor_x_out = motor_x_ini + out_x if out_x else motor_x_ini + motor_y_out = motor_y_ini + out_y if out_y else motor_y_ini + motor_z_out = motor_z_ini + out_z if out_z else motor_z_ini + motor_r_out = motor_r_ini + out_r if out_r else motor_r_ini + else: + motor_x_out = out_x if out_x else motor_x_ini + motor_y_out = out_y if out_y else motor_y_ini + motor_z_out = out_z if out_z else motor_z_ini + motor_r_out = out_r if out_r else motor_r_ini + motor_eng = XEng + motor = [motor_eng, zps.sx, zps.sy, zps.sz, zps.pi_r] + + _md = { + "detectors": [det.name for det in detectors], + "x_ray_energy": XEng.position, + "plan_args": { + "x_range": x_range, + "y_range": y_range, + "t1": t1, + "t2": t2, + "out_x": out_x, + "out_y": out_y, + "out_z": out_z, + "out_r": out_r, + "img_sizeX": img_sizeX, + "img_sizeY": img_sizeY, + "pxl": pxl, + "relative_move_flag": relative_move_flag, + "note": note if note else "None", + "sleep_time": sleep_time, + }, + "plan_name": "scan_change_expo_time", + "hints": {}, + "operator": "FXI", + "zone_plate": ZONE_PLATE, + } + _md.update(md or {}) + try: + dimensions = [(motor.hints["fields"], "primary")] + except (AttributeError, KeyError): + pass + else: + _md["hints"].setdefault("dimensions", dimensions) + + @stage_decorator(list(detectors) + motor) + @run_decorator(md=_md) + def inner(): + # take dark image + print(f"take 5 dark image with exposure = {t1}") + yield from _set_andor_param(exposure_time=t1, period=t1, chunk_size=1) + yield from _take_dark_image(detectors, motor, num_dark=5, simu=simu) + print(f"take 5 dark image with exposure = {t2}") + yield from _set_andor_param(exposure_time=t2, period=t2, chunk_size=1) + yield from _take_dark_image(detectors, motor, num_dark=5, simu=simu) + + print("open shutter ...") + yield from _open_shutter(simu) + for ii in np.arange(x_range[0], x_range[1] + 1): + for jj in np.arange(y_range[0], y_range[1] + 1): + yield from mv(zps.sx, motor_x_ini + ii * img_sizeX * pxl * 1.0 / 1000) + yield from mv(zps.sy, motor_y_ini + jj * img_sizeY * pxl * 1.0 / 1000) + yield from bps.sleep(0.1) + print(f'set exposure time = {t1}') + yield from _set_andor_param(exposure_time=t1, period=t1, chunk_size=1) + yield from bps.sleep(sleep_time) + yield from _take_image(detectors, motor, 1) + print(f'set exposure time = {t2}') + yield from _set_andor_param(exposure_time=t2, period=t2, chunk_size=1) + yield from bps.sleep(sleep_time) + yield from _take_image(detectors, motor, 1) + print(f'take bkg image with exposure time = {t1}') + yield from _set_andor_param(exposure_time=t1, period=t1, chunk_size=1) + yield from bps.sleep(sleep_time) + yield from _take_bkg_image(motor_x_out, motor_y_out, motor_z_out, motor_r_out, + detectors, motor, num_bkg=5, simu=simu) + print(f'take bkg image with exposure time = {t2}') + yield from _set_andor_param(exposure_time=t2, period=t2, chunk_size=1) + yield from bps.sleep(sleep_time) + yield from _take_bkg_image(motor_x_out, motor_y_out, motor_z_out, motor_r_out, + detectors, motor, num_bkg=5, simu=simu) + + yield from _move_sample_in(motor_x_ini, motor_y_ini, motor_z_ini, motor_r_ini, + repeat=1, trans_first_flag=0) + + print("closing shutter") + yield from _close_shutter(simu) + yield from inner() + txt = get_scan_parameter() + insert_text(txt) + print(txt) + + + + + + + + + + diff --git a/startup/99-umacro.py b/startup/99-umacro.py index b38d2b5..dc6bb95 100755 --- a/startup/99-umacro.py +++ b/startup/99-umacro.py @@ -1,9 +1,8 @@ -new_user() -show_global_para() -run_pdf() -# read_calib_file() -read_calib_file_new() - +# new_user() +# show_global_para() +# run_pdf() +# read_calib_file_new() +# check_latest_scan_id(init_guess=60000, search_size=100) ################################### @@ -432,6 +431,16 @@ def fan_scan( "/NSLS2/xf18id1/SW/xanes_ref/Cu/eng_list_Cu_s_xanes_standard_21pnt.txt" ) +Zn_eng_list_101pnt = np.genfromtxt( + "/NSLS2/xf18id1/SW/xanes_ref/Zn/eng_list_Zn_xanes_standard_101pnt.txt" +) +Zn_eng_list_63pnt = np.genfromtxt( + "/NSLS2/xf18id1/SW/xanes_ref/Zn/eng_list_Zn_xanes_standard_63pnt.txt" +) +Zn_eng_list_wl = np.genfromtxt( + "/NSLS2/xf18id1/SW/xanes_ref/Zn/eng_list_Zn_s_xanes_standard_21pnt.txt" +) + # def scan_3D_2D_overnight(n): # @@ -471,3 +480,12 @@ def fan_scan( # RE(bps.sleep(600)) # print('sleep for 600sec') ############################### + +def mono_scan_repeatibility_test(pzt_cm_bender_pos_list, pbsl_y_pos_list, + eng_start, eng_end, steps, + delay_time=0.5, repeat=1): + for ii in range(repeat): + yield from load_cell_scan(pzt_cm_bender_pos_list, + pbsl_y_pos_list, 1, + eng_start, eng_end, steps, + delay_time=delay_time) diff --git a/startup/calib_new.csv b/startup/calib_new.csv old mode 100644 new mode 100755 index 347b0cd..30d0a56 --- a/startup/calib_new.csv +++ b/startup/calib_new.csv @@ -1,50 +1,31 @@ 0 -txm_x_pos1 0.22529499999998892 -mag1 328.25 -txm_x_pos2 0.22529499999998892 -mag2 328.25 -txm_x_pos3 0.22529499999998892 -mag3 328.25 -txm_x_pos4 0.005444999999989264 -mag4 324.99 -txm_x_pos5 0.004894999999989214 -mag5 324.99 -chi2_pos1 -0.134919032204 -XEng_pos1 8.400006542242968 -zp_x_pos1 208.64799999999968 -zp_y_pos1 61.000999999999976 -th2_motor_pos1 -0.1248380177 -clens_x_pos1 220.0 -clens_y1_pos1 54.98000000000002 -clens_y2_pos1 55.0 -clens_p_pos1 2.9960000000000946 +chi2_pos1 -0.136108780588 +XEng_pos1 7.999999394769286 +zp_x_pos1 -9.094947017729282e-13 +zp_y_pos1 0.0 +th2_motor_pos1 -0.125574072184 +clens_x_pos1 -0.005000000000109139 +clens_y1_pos1 -5.211999999999989 +clens_y2_pos1 -5.233000000000175 +clens_p_pos1 0.004000000000019099 DetU_y_pos1 0.20000000000000928 -DetU_x_pos1 0.2995312500000047 -aper_x_pos1 218.14999999999964 -aper_y_pos1 54.0 -chi2_pos2 -0.135310396804 -XEng_pos2 7.999999394769286 -zp_x_pos2 223.25099999999975 -zp_y_pos2 61.13099999999997 -th2_motor_pos2 -0.12493598178599999 -clens_x_pos2 220.0 -clens_y1_pos2 54.98000000000002 -clens_y2_pos2 55.0 -clens_p_pos2 2.994000000000028 +DetU_x_pos1 0.39953125000000433 +aper_x_pos1 0.001999999999497959 +aper_y_pos1 0.0 +txm_x_pos1 0.5034949999999894 +mag1 325.0 +chi2_pos2 -0.135302569512 +XEng_pos2 8.80004636416042 +zp_x_pos2 -30.998000000000957 +zp_y_pos2 0.00100000000009004 +th2_motor_pos2 -0.125401973114 +clens_x_pos2 0.0039999999999054126 +clens_y1_pos2 -5.2849999999998545 +clens_y2_pos2 -5.177000000000135 +clens_p_pos2 0.0009999999999763531 DetU_y_pos2 0.20000000000000928 -DetU_x_pos2 0.2995312500000047 -aper_x_pos2 214.14799999999968 -aper_y_pos2 59.0 -chi2_pos3 -0.135643056714 -XEng_pos3 6.999998890261454 -zp_x_pos3 262.1529999999998 -zp_y_pos3 62.988 -th2_motor_pos3 -0.125293418316 -clens_x_pos3 218.0 -clens_y1_pos3 54.98000000000002 -clens_y2_pos3 55.0 -clens_p_pos3 3.8940000000000055 -DetU_y_pos3 0.20000000000000928 -DetU_x_pos3 0.2995312500000047 -aper_x_pos3 222.14999999999964 -aper_y_pos3 60.996000000000095 +DetU_x_pos2 0.39953125000000433 +aper_x_pos2 -0.0020000000004074536 +aper_y_pos2 0.0 +txm_x_pos2 0.5034949999999894 +mag2 325.0