|
40 | 40 | import sys |
41 | 41 | import time |
42 | 42 |
|
43 | | -from bluesky import preprocessors as bpp |
| 43 | +from bluesky import plans as bp |
44 | 44 | from bluesky import plan_stubs as bps |
| 45 | +from bluesky import preprocessors as bpp |
45 | 46 | from bluesky.callbacks.fitting import PeakStats |
46 | 47 | from ophyd import Device, Component, Signal, DeviceStatus, EpicsSignal |
| 48 | +from ophyd.scaler import ScalerCH, ScalerChannel |
47 | 49 | from ophyd.status import Status |
48 | 50 |
|
49 | 51 | from . import utils as APS_utils |
@@ -252,125 +254,128 @@ def _internal(blocking_function, *args, **kwargs): |
252 | 254 | return status |
253 | 255 |
|
254 | 256 |
|
255 | | -def lineup( |
256 | | - counter, axis, minus, plus, npts, |
257 | | - time_s=0.1, peak_factor=4, width_factor=0.8, |
258 | | - _md={}): |
259 | | - """ |
260 | | - lineup and center a given axis, relative to current position |
| 257 | +# TODO: the lineup() plan needs access to the BestEffortCallbacks().peaks object. |
| 258 | +# 2019-12-03,prj: removing until we can get to that object (if it even exists) from here |
| 259 | +#----- |
| 260 | +# def lineup( |
| 261 | +# counter, axis, minus, plus, npts, |
| 262 | +# time_s=0.1, peak_factor=4, width_factor=0.8, |
| 263 | +# _md={}): |
| 264 | +# """ |
| 265 | +# lineup and center a given axis, relative to current position |
261 | 266 |
|
262 | | - PARAMETERS |
| 267 | +# PARAMETERS |
263 | 268 |
|
264 | | - counter : object |
265 | | - instance of ophyd.Signal (or subclass such as ophyd.scaler.ScalerChannel) |
266 | | - dependent measurement to be maximized |
| 269 | +# counter : object |
| 270 | +# instance of ophyd.Signal (or subclass such as ophyd.scaler.ScalerChannel) |
| 271 | +# dependent measurement to be maximized |
267 | 272 |
|
268 | | - axis : movable object |
269 | | - instance of ophyd.Signal (or subclass such as EpicsMotor) |
270 | | - independent axis to use for alignment |
| 273 | +# axis : movable object |
| 274 | +# instance of ophyd.Signal (or subclass such as EpicsMotor) |
| 275 | +# independent axis to use for alignment |
271 | 276 |
|
272 | | - minus : float |
273 | | - first point of scan at this offset from starting position |
| 277 | +# minus : float |
| 278 | +# first point of scan at this offset from starting position |
274 | 279 |
|
275 | | - plus : float |
276 | | - last point of scan at this offset from starting position |
| 280 | +# plus : float |
| 281 | +# last point of scan at this offset from starting position |
277 | 282 |
|
278 | | - npts : int |
279 | | - number of data points in the scan |
| 283 | +# npts : int |
| 284 | +# number of data points in the scan |
280 | 285 |
|
281 | | - time_s : float (default: 0.1) |
282 | | - count time per step (if counter is ScalerChannel object) |
| 286 | +# time_s : float (default: 0.1) |
| 287 | +# count time per step (if counter is ScalerChannel object) |
283 | 288 |
|
284 | | - peak_factor : float (default: 4) |
285 | | - maximum must be greater than 'peak_factor'*minimum |
| 289 | +# peak_factor : float (default: 4) |
| 290 | +# maximum must be greater than 'peak_factor'*minimum |
286 | 291 |
|
287 | | - width_factor : float (default: 0.8) |
288 | | - fwhm must be less than 'width_factor'*plot_range |
289 | | -
|
290 | | - EXAMPLE: |
291 | | -
|
292 | | - RE(lineup(diode, foemirror.theta, -30, 30, 30, 1.0)) |
293 | | - """ |
294 | | - # first, determine if counter is part of a ScalerCH device |
295 | | - scaler = None |
296 | | - obj = counter.parent |
297 | | - if isinstance(counter.parent, ScalerChannel): |
298 | | - if hasattr(obj, "parent") and obj.parent is not None: |
299 | | - obj = obj.parent |
300 | | - if hasattr(obj, "parent") and isinstance(obj.parent, ScalerCH): |
301 | | - scaler = obj.parent |
302 | | - |
303 | | - if scaler is not None: |
304 | | - old_sigs = scaler.stage_sigs |
305 | | - scaler.stage_sigs["preset_time"] = time_s |
306 | | - scaler.select_channels([counter.name]) |
307 | | - |
308 | | - if hasattr(axis, "position"): |
309 | | - old_position = axis.position |
310 | | - else: |
311 | | - old_position = axis.value |
312 | | - |
313 | | - def peak_analysis(): |
314 | | - aligned = False |
315 | | - if counter.name in bec.peaks["cen"]: |
316 | | - table = pyRestTable.Table() |
317 | | - table.labels = ("key", "value") |
318 | | - table.addRow(("axis", axis.name)) |
319 | | - table.addRow(("detector", counter.name)) |
320 | | - table.addRow(("starting position", old_position)) |
321 | | - for key in bec.peaks.ATTRS: |
322 | | - table.addRow((key, bec.peaks[key][counter.name])) |
323 | | - logger.info(f"alignment scan results:\n{table}") |
324 | | - |
325 | | - lo = bec.peaks["min"][counter.name][-1] # [-1] means detector |
326 | | - hi = bec.peaks["max"][counter.name][-1] # [0] means axis |
327 | | - fwhm = bec.peaks["fwhm"][counter.name] |
328 | | - final = bec.peaks["cen"][counter.name] |
329 | | - |
330 | | - ps = list(bec._peak_stats.values())[0][counter.name] # PeakStats object |
331 | | - # get the X data range as received by PeakStats |
332 | | - x_range = abs(max(ps.x_data) - min(ps.x_data)) |
333 | | - |
334 | | - if final is None: |
335 | | - logger.error(f"centroid is None") |
336 | | - final = old_position |
337 | | - elif fwhm is None: |
338 | | - logger.error(f"FWHM is None") |
339 | | - final = old_position |
340 | | - elif hi < peak_factor*lo: |
341 | | - logger.error(f"no clear peak: {hi} < {peak_factor}*{lo}") |
342 | | - final = old_position |
343 | | - elif fwhm > width_factor*x_range: |
344 | | - logger.error(f"FWHM too large: {fwhm} > {width_factor}*{x_range}") |
345 | | - final = old_position |
346 | | - else: |
347 | | - aligned = True |
| 292 | +# width_factor : float (default: 0.8) |
| 293 | +# fwhm must be less than 'width_factor'*plot_range |
| 294 | + |
| 295 | +# EXAMPLE: |
| 296 | + |
| 297 | +# RE(lineup(diode, foemirror.theta, -30, 30, 30, 1.0)) |
| 298 | +# """ |
| 299 | +# # first, determine if counter is part of a ScalerCH device |
| 300 | +# scaler = None |
| 301 | +# obj = counter.parent |
| 302 | +# if isinstance(counter.parent, ScalerChannel): |
| 303 | +# if hasattr(obj, "parent") and obj.parent is not None: |
| 304 | +# obj = obj.parent |
| 305 | +# if hasattr(obj, "parent") and isinstance(obj.parent, ScalerCH): |
| 306 | +# scaler = obj.parent |
| 307 | + |
| 308 | +# if scaler is not None: |
| 309 | +# old_sigs = scaler.stage_sigs |
| 310 | +# scaler.stage_sigs["preset_time"] = time_s |
| 311 | +# scaler.select_channels([counter.name]) |
| 312 | + |
| 313 | +# if hasattr(axis, "position"): |
| 314 | +# old_position = axis.position |
| 315 | +# else: |
| 316 | +# old_position = axis.value |
| 317 | + |
| 318 | +# def peak_analysis(): |
| 319 | +# aligned = False |
| 320 | +# if counter.name in bec.peaks["cen"]: |
| 321 | +# table = pyRestTable.Table() |
| 322 | +# table.labels = ("key", "value") |
| 323 | +# table.addRow(("axis", axis.name)) |
| 324 | +# table.addRow(("detector", counter.name)) |
| 325 | +# table.addRow(("starting position", old_position)) |
| 326 | +# for key in bec.peaks.ATTRS: |
| 327 | +# table.addRow((key, bec.peaks[key][counter.name])) |
| 328 | +# logger.info(f"alignment scan results:\n{table}") |
| 329 | + |
| 330 | +# lo = bec.peaks["min"][counter.name][-1] # [-1] means detector |
| 331 | +# hi = bec.peaks["max"][counter.name][-1] # [0] means axis |
| 332 | +# fwhm = bec.peaks["fwhm"][counter.name] |
| 333 | +# final = bec.peaks["cen"][counter.name] |
| 334 | + |
| 335 | +# ps = list(bec._peak_stats.values())[0][counter.name] # PeakStats object |
| 336 | +# # get the X data range as received by PeakStats |
| 337 | +# x_range = abs(max(ps.x_data) - min(ps.x_data)) |
| 338 | + |
| 339 | +# if final is None: |
| 340 | +# logger.error(f"centroid is None") |
| 341 | +# final = old_position |
| 342 | +# elif fwhm is None: |
| 343 | +# logger.error(f"FWHM is None") |
| 344 | +# final = old_position |
| 345 | +# elif hi < peak_factor*lo: |
| 346 | +# logger.error(f"no clear peak: {hi} < {peak_factor}*{lo}") |
| 347 | +# final = old_position |
| 348 | +# elif fwhm > width_factor*x_range: |
| 349 | +# logger.error(f"FWHM too large: {fwhm} > {width_factor}*{x_range}") |
| 350 | +# final = old_position |
| 351 | +# else: |
| 352 | +# aligned = True |
348 | 353 |
|
349 | | - logger.info(f"moving {axis.name} to {final} (aligned: {aligned})") |
350 | | - yield from bps.mv(axis, final) |
351 | | - else: |
352 | | - logger.error("no statistical analysis of scan peak!") |
353 | | - yield from bps.null() |
354 | | - |
355 | | - # too sneaky? We're modifying this structure locally |
356 | | - bec.peaks.aligned = aligned |
357 | | - bec.peaks.ATTRS = ('com', 'cen', 'max', 'min', 'fwhm') |
358 | | - |
359 | | - md = dict(_md) |
360 | | - md["purpose"] = "alignment" |
361 | | - yield from bp.rel_scan([counter], axis, minus, plus, npts, md=md) |
362 | | - yield from peak_analysis() |
363 | | - |
364 | | - if bec.peaks.aligned: |
365 | | - # again, tweak axis to maximize |
366 | | - md["purpose"] = "alignment - fine" |
367 | | - fwhm = bec.peaks["fwhm"][counter.name] |
368 | | - yield from bp.rel_scan([counter], axis, -fwhm, fwhm, npts, md=md) |
369 | | - yield from peak_analysis() |
370 | | - |
371 | | - if scaler is not None: |
372 | | - scaler.select_channels() |
373 | | - scaler.stage_sigs = old_sigs |
| 354 | +# logger.info(f"moving {axis.name} to {final} (aligned: {aligned})") |
| 355 | +# yield from bps.mv(axis, final) |
| 356 | +# else: |
| 357 | +# logger.error("no statistical analysis of scan peak!") |
| 358 | +# yield from bps.null() |
| 359 | + |
| 360 | +# # too sneaky? We're modifying this structure locally |
| 361 | +# bec.peaks.aligned = aligned |
| 362 | +# bec.peaks.ATTRS = ('com', 'cen', 'max', 'min', 'fwhm') |
| 363 | + |
| 364 | +# md = dict(_md) |
| 365 | +# md["purpose"] = "alignment" |
| 366 | +# yield from bp.rel_scan([counter], axis, minus, plus, npts, md=md) |
| 367 | +# yield from peak_analysis() |
| 368 | + |
| 369 | +# if bec.peaks.aligned: |
| 370 | +# # again, tweak axis to maximize |
| 371 | +# md["purpose"] = "alignment - fine" |
| 372 | +# fwhm = bec.peaks["fwhm"][counter.name] |
| 373 | +# yield from bp.rel_scan([counter], axis, -fwhm, fwhm, npts, md=md) |
| 374 | +# yield from peak_analysis() |
| 375 | + |
| 376 | +# if scaler is not None: |
| 377 | +# scaler.select_channels() |
| 378 | +# scaler.stage_sigs = old_sigs |
374 | 379 |
|
375 | 380 |
|
376 | 381 | def nscan(detectors, *motor_sets, num=11, per_step=None, md=None): |
|
0 commit comments