NCEM 4D Camera Raw Data Versions

This is a record of the layout of raw 4D Camera data. It inlucdes information about the headers and the data shape.

The raw files contain a header block and then a data block for each frame or sector. This is the general layout:

raw file
├── frame
    ├── header
    └── data
...
└── frame
    ├── header
    └── data

header version 1

To be added

header version 2

To be added

header version 3

The raw data is written as full frames.

  • Header

    • scan number, 1 x uint32

    • frame number, 1 x uint16

    • STEM scan size, 2 x uint16

    • STEM position of this frame, 2x uint16

  • Data with shape (576,576)

    • frame data, 331776 x uint16

  • Numpy custom dtype

cameraDtype3 = np.dtype([('scan_num','<u4'),('frame_num','<u4'),('scan_size','2<u2'),('scan_pos','2<u2'),('data','331776<u2')])
frame = cameraDtype3.data.reshape((576,576))

header version 4

The raw data is written in sectors as 1/4 of the full frame.

The positions of the sectors correspond to the module number in the file name.

  • Header

    • scan number, 1 x uint32

    • frame number, 1 x uint32

    • STEM scan size, 2 x uint16

    • STEM position of this frame, 2x uint16

  • Data with shape (576, 144)

    • sector data, 82944 x uint16

  • Numpy custom dtype and sector reshape order

cameraDtype4 = np.dtype([('scan_num','<u4'),('frame_num','<u4'),('scan_size','2<u2'),('scan_pos','2<u2'),('data','82944<u2')])
frame = cameraDtype4.data.reshape((576, 144))

header version 5

The raw data is written in sectors as 1/4 of the full frame. In this version the sectors are written transposed compared to version4 making the data contiguous.

The positions of the sectors correspond to the module number in the file name. See below for manual stitching code.

  • Header

    • scan number, 1 x uint32

    • frame number, 1 x uint32

    • STEM scan size, 2 x uint16

    • STEM position of this frame, 2x uint16

  • Data with shape (144, 576)

    • sector data, 82944 x uint16

  • Numpy custom dtype and sector reshape order.

cameraDtype5 = np.dtype([('scan_num','<u4'),('frame_num','<u4'),('scan_size','2<u2'),('scan_pos','2<u2'),('data','82944<u2')])
frame = cameraDtype5.data.reshape((144, 576))
  • Reconstruct full frames manually

import numpy as np
modulePositions = ((0,144),(144,144*2),(144*2,144*3),(144*3,144*4))

scan = np.zeros((scanXY[0], scanXY[1], 576, 576), dtype='<u2')

for file in files:
    #print(file.stem)
    with open(file, 'rb') as f1:
        start = str(file).find('module')
        m = int(str(file)[start+6])
        module = modulePositions[int(str(file)[start+6])]
        dataSet = np.fromfile(f1, dtype=cameraDtype, count = -1)
        for pos, data in zip(dataSet['pos'], dataSet['data']):
            scan[pos[0], pos[1], module[0]:module[1], :] = data.reshape((detectorI, detectorJ))