BCDA-APS / bluesky_training

Bluesky training, including instrument package
https://bcda-aps.github.io/bluesky_training/
Other
11 stars 0 forks source link

notebook: images, darks, & flats needs to be updated #81

Closed prjemian closed 1 year ago

prjemian commented 1 year ago

Note there are errors in the notebook for images, darks, & flats. It needs to be updated.

for reference:

prjemian commented 1 year ago

Asked @MarkRivers for assistance. These are from his responses:

... just refreshed my memory of how it works for me in tomoscan, which does correctly save the darks, flats, and projections into different datasets.

Step 1. Database with 3 records that define the possible locations in the file, '/exchange/data', '/exchange/data_dark', and '/exchange/data_white'. It also defines a record (HDF5Location) that contains the currently selected destination. https://github.com/tomography/tomoscan/blob/4a954d25874849bd00a4b2e622c05ab571600259/tomoScanApp/Db/tomoScan.template#L267

Step 2. Detector attributes file that contains an attribute called HDF5FrameLocation that gets its value from the HDF5Location record. https://github.com/CARS-UChicago/GSECARS-EPICS/blob/d4c0e9aabbf215b06c75426eea28dec47cc949c1/iocBoot/ioc13bmd_pg1/tomoDetectorAttributes.xml#L127

Step 3. HDF5 XML layout file that defines the global 'detector_data_destination' with the ndattribute= HDF5FrameLocation. That tells the HDF5 plugin that NDAttribute selects the frame location. https://github.com/CARS-UChicago/GSECARS-EPICS/blob/d4c0e9aabbf215b06c75426eea28dec47cc949c1/iocBoot/ioc13bmd_pg1/tomoLayout.xml#L3

Step 4. Python code that copies the appropriate location into the HDFLocation record when collecting dark fields, flat fields, and projections respectively. https://github.com/tomography/tomoscan/blob/4a954d25874849bd00a4b2e622c05ab571600259/tomoscan/tomoscan.py#L762 https://github.com/tomography/tomoscan/blob/4a954d25874849bd00a4b2e622c05ab571600259/tomoscan/tomoscan.py#L791 https://github.com/tomography/tomoscan/blob/4a954d25874849bd00a4b2e622c05ab571600259/tomoscan/tomoscan.py#L817

prjemian commented 1 year ago

@MarkRivers added

I looked at your code briefly and it seems OK, so it is probably something simply being overlooked.

One way to debug this is to run diagnostics on the IOC while it is running. dbpr, caget, asynSetTraceMask, and asynReport could all help figure out where the problem is.

prjemian commented 1 year ago

@MarkRivers added:

This IOC command will print out detailed information about the driver, including all of the information about the last NDArray it created. That NDArray information includes the values of all NDAttributes.

asynReport 20 SIM1
...
NDAttribute, address=0x55d1c40:
  name=Gettysburg
  description=Start of Gettysburg address
  source type=3
  source type string=NDAttrSourceFunct
  source=myAttrFunct1
  dataType=NDAttrString
  value=Four score and seven years ago our fathers
  functAttribute
    functParam=GETTYSBURG
    pFunction=0x69fb40
    functionPvt=0x55d20b0

You could use that to see if the NDAttribute that should contain the destination dataset is correct.

prjemian commented 1 year ago

Look for HDF5Location in the TomoScan docs.

It uses a database that provides a HDF5Location PV.

prjemian commented 1 year ago

@MarkRivers Thanks for the links to your code. I believe my notebook must have skipped some step so I rebuilt it and have a working notebook. Next, it needs the text to make it into documentation.

One thing I learned is that:

NOTE: Very important that you set the attributes file in the cam, and not the hdf1 plugin!

prjemian commented 1 year ago

ophyd code to acquire (simple) with area detector:

from ophyd.status import Status

def acquire(det, frame_type, nframes):
    acquisition = Status()

    def responder(**kwargs):
        """Called when subscribed signal changes."""
        if kwargs.get("value") in (0, "Idle") and not acquisition.done:
            acquisition.set_finished()

    det.cam.frame_type.put(frame_type)
    det.cam.num_images.put(nframes)
    det.cam.acquire.put(1)
    det.cam.detector_state.subscribe(responder)
    acquisition.wait()
    det.cam.detector_state.unsubscribe(responder)

acquire(adsimdet, DARK, 1)
acquire(adsimdet, IMAGE, 5)
acquire(adsimdet, WHITE, 2)
acquire(adsimdet, DARK, 1)