Skip to content

Map a battery cell with a mesh scan

Raster the cell point by point and replay the raster while it charges, so that medved can fold the patterns into a movie of maps. The helper names every point after the BM01 mesh contract and writes the mesh.json marker medved recognises the dataset by.

from bm01macros import Mesh

m = Mesh(cell='IFE-135',
         slow=('prhor', -1.0, 0.1, 11),
         fast=('battz', -0.5, 0.1, 11),
         repeats=200,
         exposure=1.0,
         extension='xye',
         integrated_dir='xye')

for series in m.scan():
    for row in m.rows():
        row.move()
        for point in row.points():
            point.move()
            point.measure()

The axes are (motor, begin, step, count) in millimetres, the slow one being the outer loop of the raster and the fast one the inner. repeats is how many times the raster is replayed, exposure is seconds per point. Set integrated_dir to the subdirectory bubble writes the integrated patterns into, or to '' when it writes them next to the frames, and extension to their extension. The files come out as IFE-135_<series>_<slow>_<fast>, all counters five digits wide from zero.

Add dry_run=True to print the moves and the names without measuring anything, which is the fastest way to check a mesh before the beam is on.

A holder with several cells is measured cell by cell: one raster of the first cell, one of the second, and so on, then round again. Every cell is a mesh of its own, with its own folder, marker and geometry, and rounds() plays them in turn, handing out the cell whose turn it is with its series already set:

from bm01macros import Mesh, rounds

cells = [Mesh(cell=name, slow=('prhor', x, 0.1, 11), fast=('battz', z, 0.1, 11),
              repeats=200, exposure=1.0, extension='xye', integrated_dir='xye')
         for name, x, z in (('NaPF6-G2',    -67.45, -38.75),
                            ('NaOTf-G1',    -67.65,  31.50),
                            ('NaOTf-G2',    -42.36,  -3.25),
                            ('NaPF6-G2_NR', -17.20, -38.50),
                            ('Black-P',     -17.33,  31.50))]

for m in rounds(*cells):
    for row in m.rows():
        row.move()
        for point in row.points():
            point.move()
            point.measure()

The body of the loop is the one above, so only the loop over the series changes. Mind that begin is the first point of a raster and not its centre: the numbers above are the aligned cell positions less half a raster. The rasters need not be the same size or the same step, and every cell keeps its own repeats; a cell that has played all of its rasters drops out of the rounds while the others go on. Two cells may not share a folder, or they would overwrite each other point by point.

For one frame per cell instead of a map of each, see Multi-battery cell.

Restarting into the same folder after an interruption needs an explicit signature:

m = Mesh(cell='IFE-135', ..., resume=True)

The helper then checks the geometry against the marker on disk, continues from the first free series, and leaves the interrupted series as a hole. A geometry that does not match is refused: the old points would be laid out by the new one and the maps would silently lie. In a holder every cell finds its own first free series, and rounds() lifts them all to the highest of those, so that a series index keeps meaning the same round in every cell; the series skipped by the cells that were behind stay holes.