Record data from a PushBroom and then process the entire recording

This example will connect to the virtual pushbroom camera (using MiniCube.hdr and its references), measure a white & dark reference, create a recording processing context, record a cube consisting of the first 100 lines returned from the device. It will then process the entire cube using a different processing context for the model instrument_function.fluxmdl.

This is in contrast to processing PushBroom data line by line, which fluxEngine also supports.

Note

The amount of RAM required when processing entire cubes will quickly become very large; it is therefore recommended to limit the number of lines that are recorded using this method.

C++

The source code of the example can be found in the file example_pushbroom_record_and_process.cpp:

  1#if defined(_WIN32) && defined(_MSC_VER)
  2#include <windows.h>
  3#endif
  4
  5#include <iostream>
  6#include <iomanip>
  7#include <string>
  8#include <fstream>
  9#include <streambuf>
 10#include <algorithm>
 11#include <utility>
 12
 13#include <cstddef>
 14
 15#include <fluxEngine/fluxEngine>
 16
 17#include "paths.h"
 18#include "helpers.h"
 19
 20int main()
 21{
 22    try {
 23        std::cout << "fluxEngine version: " << fluxEngine::versionString() << std::endl;
 24        fluxEngine::Handle handle(readFile(g_licenseFileName));
 25        handle.setDriverBaseDirectory(g_driverDirectory);
 26        handle.setDriverIsolationExecutable(g_driverIsolationExecutable);
 27        handle.createProcessingThreads(4);
 28
 29        // Load virtual camera
 30        fluxEngine::EnumerationResult enumeratedDevices = fluxEngine::enumerateDevices(handle, -1, std::chrono::seconds{1});
 31        fluxEngine::EnumeratedDevice* virtualCameraDevice = nullptr;
 32        for (auto const& device : enumeratedDevices.devices) {
 33            if (device->driver->name == "VirtualHyperCamera") {
 34                virtualCameraDevice = device.get();
 35                break;
 36            }
 37        }
 38
 39        if (!virtualCameraDevice)
 40            throw std::runtime_error("Could not find virtual camera driver");
 41
 42        fluxEngine::ConnectionSettings connectionSettings;
 43        connectionSettings.driverName = virtualCameraDevice->driver->name;
 44        connectionSettings.driverType = virtualCameraDevice->driver->type;
 45        connectionSettings.id = virtualCameraDevice->id;
 46        connectionSettings.timeout = std::chrono::seconds{60};
 47        connectionSettings.connectionParameters["Cube"] = encodeFileNameForConnectionParameter(g_cubeFileName);
 48        connectionSettings.connectionParameters["WhiteReferenceCube"] = encodeFileNameForConnectionParameter(g_whiteCubeFileName);
 49        connectionSettings.connectionParameters["DarkReferenceCube"] = encodeFileNameForConnectionParameter(g_darkCubeFileName);
 50
 51        std::cout << "Attempting to connect to device...\n" << std::flush;
 52        for (auto const& parameter : connectionSettings.connectionParameters)
 53            std::cout << "  - " << parameter.first << ": " << parameter.second << "\n" << std::flush;
 54        fluxEngine::DeviceGroup deviceGroup = fluxEngine::connectDeviceGroup(handle, connectionSettings);
 55        std::cout << "Connected.\n" << std::flush;
 56        fluxEngine::InstrumentDevice* camera = dynamic_cast<fluxEngine::InstrumentDevice*>(deviceGroup.primaryDevice());
 57        if (!camera) {
 58            deviceGroup.disconnect(std::chrono::seconds{5});
 59            throw std::runtime_error("The device is not an instrument device");
 60        }
 61
 62        camera->setupInternalBuffers(5);
 63
 64        /* Load model
 65         *
 66         * This should be done after connecting with the camera, in
 67         * case the license is tied to a camera serial number. (In
 68         * case the license is tied to a dongle or a mainboard id,
 69         * this may be done beforehand.)
 70         */
 71        fluxEngine::Model model = fluxEngine::Model(handle, fluxEngine::Model::FromFile, g_modelFileName);
 72
 73        /* NOTE:
 74         * For real devices a this point the user should probably be
 75         * asked to insert a white reference underneath the camera.
 76         *
 77         * For the virtual device this is not required.
 78         */
 79
 80        fluxEngine::InstrumentDevice::AcquisitionParameters acqParams;
 81        std::cout << "Measuring white reference:\n" << std::flush;
 82        fluxEngine::BufferContainer whiteReference = fluxEngine::createRingBufferContainer(camera, 10);
 83        acqParams.referenceName = "WhiteReference";
 84        camera->startAcquisition(acqParams);
 85        for (int i = 0; i < 10; ++i) {
 86            fluxEngine::BufferInfo buffer = camera->retrieveBuffer(std::chrono::seconds{1});
 87            if (buffer.ok) {
 88                whiteReference.add(buffer);
 89                camera->returnBuffer(buffer.id);
 90            }
 91        }
 92        camera->stopAcquisition();
 93        std::cout << "Done.\n" << std::flush;
 94
 95        /* NOTE:
 96         * For real devices a this point the user should probably be
 97         * asked to obscure the optics in front of the camera in order
 98         * for a proper dark reference to be measured.
 99         *
100         * For the virtual device this is not required.
101         *
102         * Some cameras do have an internal shutter, where manual user
103         * intervention is also not required here.
104         */
105
106        std::cout << "Measuring dark reference:\n" << std::flush;
107        fluxEngine::BufferContainer darkReference = fluxEngine::createBufferContainer(camera, 10);
108        acqParams.referenceName = "DarkReference";
109        camera->startAcquisition(acqParams);
110        for (int i = 0; i < 10; ++i) {
111            fluxEngine::BufferInfo buffer = camera->retrieveBuffer(std::chrono::seconds{1});
112            if (buffer.ok) {
113                darkReference.add(buffer);
114                camera->returnBuffer(buffer.id);
115            }
116        }
117        camera->stopAcquisition();
118        std::cout << "Done.\n" << std::flush;
119
120        // Create recording context
121        fluxEngine::ProcessingContext::InstrumentParameters instrumentParameters;
122        instrumentParameters.whiteReference = &whiteReference;
123        instrumentParameters.darkReference = &darkReference;
124        fluxEngine::ProcessingContext::HSIRecordingResult contextAndInfo = fluxEngine::ProcessingContext::createInstrumentHSIRecordingContext(camera, fluxEngine::ValueType::Intensity, instrumentParameters, {});
125
126        // Create buffer container for recording 100 lines
127        fluxEngine::BufferContainer recordingBuffer = fluxEngine::createBufferContainer(contextAndInfo.context, 100);
128
129        /* NOTE:
130         * For real devices a this point the user should probably be
131         * asked to position the object to measure underneath the
132         * camera and start the motion of the motion control device
133         * they have.
134         *
135         * For the virtual device this is not required.
136         */
137
138        std::cout << "Starting acquisition:\n" << std::flush;
139        acqParams.referenceName = {};
140        camera->startAcquisition(acqParams);
141        std::cout << "Done.\n" << std::flush;
142
143        std::cout << "Recording buffers" << std::flush;
144        while (recordingBuffer.count() < 100) {
145            fluxEngine::BufferInfo buffer = camera->retrieveBuffer(std::chrono::milliseconds{100});
146            if (!buffer.ok)
147                continue;
148
149            contextAndInfo.context.setSourceData(buffer);
150            contextAndInfo.context.processNext();
151            recordingBuffer.addLastResult(contextAndInfo.context);
152            std::cout << '.' << std::flush;
153
154            camera->returnBuffer(buffer.id);
155        }
156        std::cout << "\n" << std::flush;
157
158        std::cout << "Stopping acquisition:\n" << std::flush;
159        camera->stopAcquisition();
160        std::cout << "Done.\n" << std::flush;
161
162        std::cout << "Creating measurement:\n" << std::flush;
163        fluxEngine::MeasurementHSICubeBufferInput recordingInput;
164        recordingInput.name = "Sample recording";
165        recordingInput.valueType = fluxEngine::ValueType::Intensity;
166        recordingInput.bufferContainers.push_back(&recordingBuffer);
167        recordingInput.wavelengths = contextAndInfo.wavelengths;
168        recordingInput.whiteReference = contextAndInfo.whiteReference;
169        recordingInput.darkReference = contextAndInfo.darkReference;
170        recordingInput.calibrationInfo = &contextAndInfo.calibrationInfo;
171        fluxEngine::MeasurementList cube = fluxEngine::createMeasurementHSICube(handle, recordingInput);
172        std::cout << "Done.\n" << std::flush;
173
174        std::cout << "Processing the cube:\n" << std::flush;
175        fluxEngine::ProcessingContext context = fluxEngine::ProcessingContext::createMeasurementProcessingContext(cube, 0, model, 0);
176        int const sinkIndex = context.findOutputSink(/* outputId = */ 0);
177
178        // Process the data
179        context.setSourceData(cube, 0);
180        context.processNext();
181        std::cout << "Done.\n" << std::flush;
182
183        fluxEngine::ProcessingContext::OutputSinkData outputData = context.outputSinkData(sinkIndex);
184        fluxEngine::TensorData view{outputData};
185
186        if (view.order() != 3
187            || view.dataType() != fluxEngine::DataType::Float64
188            || view.dimension(2) != 1)
189            throw std::runtime_error("The model is not expected");
190
191        // The cube we are loading is very small (12x14 pixels),
192        // but if a larger cube is being loaded, this will produce
193        // a _lot_ of output!
194        // (Show only the first 10 lines.)
195        for (int64_t y = 0; y < 10; ++y) {
196            for (int64_t x = 0; x < view.dimension(1); ++x)
197                std::cout << "Pixel (" << x << ", " << y << ") has average value " << view.at<double>(y, x, 0) << '\n';
198        }
199        std::cout << std::flush;
200    } catch (std::exception& e) {
201        std::cerr << "Error: " << e.what() << std::endl;
202        return 1;
203    } catch (...) {
204        std::cerr << "Unknown error." << std::endl;
205        return 1;
206    }
207
208    return 0;
209}

This source file will compile to the executable ExamplePushBroomRecordAndProcess.

.NET

The source code of the example can be found in the file ExamplePushBroomRecordAndProcess\Program.cs.

  1using System;
  2
  3namespace ExamplePushBroomRecordAndProcess
  4{
  5    class Program
  6    {
  7        static void Main(string[] args)
  8        {
  9            Console.WriteLine("fluxEngine version: " + LuxFlux.fluxEngineNET.Version.String);
 10            var handle = new LuxFlux.fluxEngineNET.Handle(ExampleHelpers.IO.ReadLicenseFile());
 11            handle.SetDriverBaseDirectory(ExampleHelpers.Paths.DriverDirectory);
 12            handle.CreateProcessingThreads(4);
 13
 14            // Load virtual camera
 15            var enumeratedDevices = LuxFlux.fluxEngineNET.DeviceEnumeration.EnumerateDevices(handle, null, TimeSpan.FromSeconds(1));
 16            LuxFlux.fluxEngineNET.EnumeratedDevice virtualCameraDevice = null;
 17            foreach (var device in enumeratedDevices.Devices)
 18            {
 19                if (device.Driver.Name == "VirtualHyperCamera")
 20                {
 21                    virtualCameraDevice = device;
 22                    break;
 23                }
 24            }
 25
 26            if (virtualCameraDevice == null)
 27                throw new Exception("Could not find virtual camera driver");
 28
 29            var connectionSettings = new LuxFlux.fluxEngineNET.ConnectionSettings();
 30            connectionSettings.DriverName = virtualCameraDevice.Driver.Name;
 31            connectionSettings.DriverType = virtualCameraDevice.Driver.Type;
 32            connectionSettings.Id = virtualCameraDevice.Id;
 33            connectionSettings.Timeout = TimeSpan.FromSeconds(60);
 34            connectionSettings.ConnectionParameters = new System.Collections.Generic.Dictionary<string, string>();
 35            connectionSettings.ConnectionParameters["Cube"] = ExampleHelpers.Paths.ExampleDataFileName("MiniCube.hdr");
 36            connectionSettings.ConnectionParameters["WhiteReferenceCube"] = ExampleHelpers.Paths.ExampleDataFileName("MiniCube_White.hdr");
 37            connectionSettings.ConnectionParameters["DarkReferenceCube"] = ExampleHelpers.Paths.ExampleDataFileName("MiniCube_Dark.hdr");
 38
 39            Console.WriteLine("Attempting to connect to device...");
 40            var deviceGroup = LuxFlux.fluxEngineNET.DeviceGroup.Connect(handle, connectionSettings);
 41            Console.WriteLine("Connected.");
 42            if (!(deviceGroup.PrimaryDevice is LuxFlux.fluxEngineNET.InstrumentDevice))
 43            {
 44                deviceGroup.Disconnect(TimeSpan.FromSeconds(5));
 45                throw new Exception("The device is not an instrument device.");
 46            }
 47            var camera = (LuxFlux.fluxEngineNET.InstrumentDevice)deviceGroup.PrimaryDevice;
 48
 49            camera.SetupInternalBuffers(5);
 50
 51            /* Load model
 52             *
 53             * This should be done after connecting with the camera, in
 54             * case the license is tied to a camera serial number. (In
 55             * case the license is tied to a dongle or a mainboard id,
 56             * this may be done beforehand.)
 57             */
 58            var model = LuxFlux.fluxEngineNET.Model.LoadFromFile(handle, ExampleHelpers.Paths.ExampleDataFileName("instrument_function.fluxmdl"));
 59
 60            /* NOTE:
 61             * For real devices a this point the user should probably be
 62             * asked to insert a white reference underneath the camera.
 63             *
 64             * For the virtual device this is not required.
 65             */
 66
 67            var acqParams = new LuxFlux.fluxEngineNET.InstrumentDevice.AcquisitionParameters();
 68            Console.WriteLine("Measuring white reference:");
 69            var whiteReference = LuxFlux.fluxEngineNET.Util.CreateRingBufferContainer(camera, 10);
 70            acqParams.ReferenceName = "WhiteReference";
 71            camera.StartAcquisition(acqParams);
 72            for (int i = 0; i < 10; ++i)
 73            {
 74                var buffer = camera.RetrieveBuffer(TimeSpan.FromSeconds(1));
 75                if (buffer != null)
 76                {
 77                    try
 78                    {
 79                        whiteReference.Add(buffer);
 80                    }
 81                    finally
 82                    {
 83                        camera.ReturnBuffer(buffer);
 84                    }
 85                }
 86            }
 87            camera.StopAcquisition();
 88            Console.WriteLine("Done.");
 89
 90            /* NOTE:
 91             * For real devices a this point the user should probably be
 92             * asked to obscure the optics in front of the camera in order
 93             * for a proper dark reference to be measured.
 94             *
 95             * For the virtual device this is not required.
 96             *
 97             * Some cameras do have an internal shutter, where manual user
 98             * intervention is also not required here.
 99             */
100
101            Console.WriteLine("Measuring dark reference:");
102            var darkReference = LuxFlux.fluxEngineNET.Util.CreateRingBufferContainer(camera, 10);
103            acqParams.ReferenceName = "DarkReference";
104            camera.StartAcquisition(acqParams);
105            for (int i = 0; i < 10; ++i)
106            {
107                var buffer = camera.RetrieveBuffer(TimeSpan.FromSeconds(1));
108                if (buffer != null)
109                {
110                    try
111                    {
112                        darkReference.Add(buffer);
113                    }
114                    finally
115                    {
116                        camera.ReturnBuffer(buffer);
117                    }
118                }
119            }
120            camera.StopAcquisition();
121            Console.WriteLine("Done.");
122
123            // Create recording context
124            var instrumentReferences = new LuxFlux.fluxEngineNET.ProcessingContext.BufferReferenceInput();
125            instrumentReferences.WhiteReference = whiteReference;
126            instrumentReferences.DarkReference = darkReference;
127            var instrumentParameters = new LuxFlux.fluxEngineNET.ProcessingContext.InstrumentParameters();
128            instrumentParameters.ReferenceInput = instrumentReferences;
129
130            var contextAndInfo = LuxFlux.fluxEngineNET.ProcessingContext.CreateForInstrumentHSIRecording(camera, LuxFlux.fluxEngineNET.ValueType.Intensity, instrumentParameters);
131
132            // Create buffer container for recording 100 lines
133            var recordingBuffer = LuxFlux.fluxEngineNET.Util.CreateBufferContainer(contextAndInfo.Context, 100);
134
135            /* NOTE:
136             * For real devices a this point the user should probably be
137             * asked to position the object to measure underneath the
138             * camera and start the motion of the motion control device
139             * they have.
140             *
141             * For the virtual device this is not required.
142             */
143
144            Console.WriteLine("Starting acquisition:");
145            acqParams.ReferenceName = null;
146            camera.StartAcquisition(acqParams);
147            Console.WriteLine("Done.");
148
149            Console.Out.Write("Recording buffers");
150            Console.Out.Flush();
151            while (recordingBuffer.Count < 100)
152            {
153                var buffer = camera.RetrieveBuffer(TimeSpan.FromMilliseconds(100));
154                if (buffer == null)
155                    continue;
156
157                try
158                {
159                    contextAndInfo.Context.SetSourceData(buffer);
160                    contextAndInfo.Context.ProcessNext();
161                    recordingBuffer.AddLastResult(contextAndInfo.Context);
162                    Console.Out.Write(".");
163                    Console.Out.Flush();
164                }
165                finally
166                {
167                    camera.ReturnBuffer(buffer);
168                }
169            }
170            Console.WriteLine("");
171
172            Console.WriteLine("Stopping acquisition:");
173            camera.StopAcquisition();
174            Console.WriteLine("Done.");
175
176            Console.WriteLine("Creating measurement:");
177            var recordingInput = new LuxFlux.fluxEngineNET.MeasurementHSICubeBufferInput();
178            recordingInput.Name = "Sample recording";
179            recordingInput.ValueType = LuxFlux.fluxEngineNET.ValueType.Intensity;
180            recordingInput.BufferContainers = new LuxFlux.fluxEngineNET.BufferContainer[1];
181            recordingInput.BufferContainers[0] = recordingBuffer;
182            recordingInput.WhiteReference = contextAndInfo.WhiteReference;
183            recordingInput.DarkReference = contextAndInfo.DarkReference;
184            recordingInput.IlluminationReference = contextAndInfo.IlluminationReference;
185            recordingInput.CalibrationInfo = contextAndInfo.CalibrationInfo;
186            recordingInput.Wavelengths = contextAndInfo.Wavelengths;
187            var cube = LuxFlux.fluxEngineNET.MeasurementList.CreateForHSICube(handle, recordingInput);
188            Console.WriteLine("Done.");
189
190            Console.WriteLine("Done.");
191            var context = LuxFlux.fluxEngineNET.ProcessingContext.CreateForMeasurement(cube, 0, model, 0);
192            int sinkIndex = context.OutputSinkInfoById(/* outputId = */ 0).Index;
193
194            // Process the data
195            context.SetSourceData(cube, 0);
196            context.ProcessNext();
197            Console.WriteLine("Done.");
198
199            var outputData = context.OutputSinkData(sinkIndex);
200            var data = outputData.AsTensorCopy();
201
202            if (data.Order != 3 || data.DataType != LuxFlux.fluxEngineNET.DataType.Float64 || data.Dimensions[2] != 1)
203                throw new Exception("The model is not expected");
204
205            // The cube we are loading is very small (12x14 pixels),
206            // but if a larger cube is being loaded, this will produce
207            // a _lot_ of output!
208            // Only showing the first 10 lines anyway.
209            for (Int64 y = 0; y < 10; ++y)
210            {
211                for (Int64 x = 0; x < data.Dimensions[1]; ++x)
212                {
213                    Console.WriteLine($"Pixel ({x}, {y}) has average value {data.Value<double>(y, x, 0)}");
214                }
215            }
216
217            Console.WriteLine("Disconnecting from device...");
218            deviceGroup.Disconnect(TimeSpan.FromSeconds(5));
219            Console.WriteLine("Done.");
220            context.Dispose();
221            model.Dispose();
222            cube.Dispose();
223            handle.Dispose();
224        }
225    }
226}

Python

The source code of the example can be found in the file example_pushbroom_record_and_process.py:

  1#!/usr/bin/env python3
  2
  3import fluxEngine
  4import os, sys
  5
  6import fluxEngine_example_paths as paths
  7data_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'data')
  8
  9print('fluxEngine version {}'.format(fluxEngine.versionString()))
 10with open(paths.licenseFileName, 'rb') as f:
 11    handle = fluxEngine.Handle(f.read())
 12handle.setDriverBaseDirectory(paths.driverDirectory)
 13handle.createProcessingThreads(4)
 14
 15enumeratedDevices = fluxEngine.enumerateDevices(handle, -1, 5000)
 16virtualCameraDevice = None
 17for device in enumeratedDevices.devices:
 18    if device.driver.name == 'VirtualHyperCamera':
 19        virtualCameraDevice = device
 20
 21if not virtualCameraDevice:
 22    raise Exception('Could not find virtual camera driver')
 23
 24connectionSettings = fluxEngine.ConnectionSettings(virtualCameraDevice.driver.name, virtualCameraDevice.driver.type, virtualCameraDevice.id)
 25connectionSettings.timeout = 60000
 26connectionSettings.connectionParameters['Cube'] = os.path.join(data_dir, 'MiniCube.hdr')
 27connectionSettings.connectionParameters['WhiteReferenceCube'] = os.path.join(data_dir, 'MiniCube_White.hdr')
 28connectionSettings.connectionParameters['DarkReferenceCube'] = os.path.join(data_dir, 'MiniCube_Dark.hdr')
 29
 30print("Attempting to connect to device...")
 31deviceGroup = fluxEngine.DeviceGroup(handle, connectionSettings)
 32print("Connected.")
 33
 34camera = deviceGroup.primaryDevice()
 35if not isinstance(camera, fluxEngine.InstrumentDevice):
 36    deviceGroup.disconnect(5000)
 37    raise Exception('The device is not an instrument device')
 38
 39camera.setupInternalBuffers(5)
 40
 41# Load model
 42#
 43# This should be done after connecting with the camera, in
 44# case the license is tied to a camera serial number. (In
 45# case the license is tied to a dongle or a mainboard id,
 46# this may be done beforehand.)
 47with open(os.path.join(data_dir, 'instrument_function.fluxmdl'), 'rb') as f:
 48    model = fluxEngine.Model(handle, f.read())
 49
 50# NOTE:
 51# For real devices a this point the user should probably be
 52# asked to insert a white reference underneath the camera.
 53#
 54# For the virtual device this is not required.
 55
 56acqParams = fluxEngine.InstrumentDevice.AcquisitionParameters()
 57
 58print('Measuring white reference:')
 59whiteReference = fluxEngine.BufferContainer(camera, 10)
 60acqParams.referenceName = "WhiteReference"
 61camera.startAcquisition(acqParams)
 62for i in range(10):
 63    buffer = camera.retrieveBuffer(1000)
 64    if buffer:
 65        whiteReference.add(buffer)
 66        camera.returnBuffer(buffer)
 67camera.stopAcquisition()
 68print('Done.')
 69
 70# NOTE:
 71# For real devices a this point the user should probably be
 72# asked to obscure the optics in front of the camera in order
 73# for a proper dark reference to be measured.
 74#
 75# For the virtual device this is not required.
 76#
 77# Some cameras do have an internal shutter, where manual user
 78# intervention is also not required here.
 79#
 80
 81print('Measuring dark reference:')
 82darkReference = fluxEngine.BufferContainer(camera, 10)
 83acqParams.referenceName = "DarkReference"
 84camera.startAcquisition(acqParams)
 85for i in range(10):
 86    buffer = camera.retrieveBuffer(1000)
 87    if buffer:
 88        darkReference.add(buffer)
 89        camera.returnBuffer(buffer)
 90camera.stopAcquisition()
 91print('Done.')
 92
 93# Create recording contect
 94instrumentParameters = fluxEngine.InstrumentParameters()
 95instrumentParameters.whiteReference = whiteReference
 96instrumentParameters.darkReference = darkReference
 97
 98context = fluxEngine.ProcessingContext(None, fluxEngine.ProcessingContext.InstrumentHSIRecording,
 99                                       device=camera,
100                                       valueType=fluxEngine.ValueType.Intensity,
101                                       instrumentParameters=instrumentParameters)
102recordingInfo = context.hsiRecordingResultInfo()
103
104# Create buffer container for recording 100 lines
105recordingBuffer = fluxEngine.createBufferContainerForRecordingContext(context, 100)
106
107# NOTE:
108# For real devices a this point the user should probably be
109# asked to position the object to measure underneath the
110# camera and start the motion of the motion control device
111# they have.
112#
113# For the virtual device this is not required.
114#
115
116print('Starting acquisition:')
117acqParams.referenceName = None
118camera.startAcquisition(acqParams)
119print('Done.')
120
121print('Recording buffers:')
122while recordingBuffer.count() < 100:
123    buffer = camera.retrieveBuffer(100)
124    if not buffer:
125        continue
126
127    context.setSourceData(buffer)
128    context.processNext()
129    recordingBuffer.addLastResult(context)
130    sys.stdout.write('.')
131    sys.stdout.flush()
132    camera.returnBuffer(buffer)
133sys.stdout.write('\n')
134print('Done.')
135
136print('Stopping acquisition:')
137camera.stopAcquisition()
138print('Done.')
139
140print('Creating measurement:')
141recordingInput = fluxEngine.MeasurementHSICubeBufferInput()
142recordingInput.name = "Sample recording"
143recordingInput.valueType = fluxEngine.ValueType.Intensity
144recordingInput.bufferContainers.append(recordingBuffer)
145recordingInput.wavelengths = recordingInfo.wavelengths
146recordingInput.whiteReference = recordingInfo.whiteReference
147recordingInput.darkReference = recordingInfo.darkReference
148recordingInput.calibrationInfo = recordingInfo.calibrationInfo
149
150cube = fluxEngine.createMeasurementHSICube(handle, recordingInput)
151print('Done.')
152
153print('Processing the cube:')
154context = fluxEngine.ProcessingContext(model, fluxEngine.ProcessingContext.MeasurementProcessing,
155                                       measurementList=cube, index=0)
156sinkIndex = context.findOutputSink(0)
157
158context.setSourceData(cube, 0)
159context.processNext()
160print('Done.')
161
162outputData = context.outputSinkData(sinkIndex)
163# The cube we are loading is very small (12x14 pixels),
164# but if a larger cube is being loaded, this will produce
165# a _lot_ of output!
166# (Show only the first 10 lines.)
167print(outputData[0:10, :, 0])

Expected Output

The output should look like the following:

fluxEngine version: [...]
Attempting to connect to device...
  - DarkReferenceCube: examples/data/MiniCube_Dark.hdr
  - WhiteReferenceCube: examples/data/MiniCube_White.hdr
  - Cube: examples/data/MiniCube.hdr
Connected.
Measuring white reference:
Done.
Measuring dark reference:
Done.
Starting acquisition:
Done.
Recording buffers....................................................................................................
Stopping acquisition:
Done.
Creating measurement:
Done.
Processing the cube:
Done.
Pixel (0, 0) has average value 0.652092
Pixel (1, 0) has average value 0.641689
Pixel (2, 0) has average value 0.633774
Pixel (3, 0) has average value 0.636609
Pixel (4, 0) has average value 0.633638
Pixel (5, 0) has average value 0.648021
Pixel (6, 0) has average value 0.652871
Pixel (7, 0) has average value 0.661865
[...]
Pixel (6, 9) has average value 0.679719
Pixel (7, 9) has average value 0.69257
Pixel (8, 9) has average value 0.691668
Pixel (9, 9) has average value 0.698366
Pixel (10, 9) has average value 0.699787
Pixel (11, 9) has average value 0.710912
Pixel (12, 9) has average value 0.707087
Pixel (13, 9) has average value 0.727694