Read ENVI Cube and Process using Model

The example will read the example HSI cube MiniCube.hdr and process it using the instrument_function.fluxmdl, and return the result of the model for a couple of pixels. The model itself just calculates the spectral average for each pixel.

This version of the example uses fluxEngine to automatically create a processing context from a measurement, in contrast to the other variant of this example, which creates the processing context manually from the structure of the loaded cube.

C++

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

 1#if defined(_WIN32) && defined(_MSC_VER)
 2#include <windows.h>
 3#endif
 4
 5#include <iostream>
 6#include <string>
 7#include <fstream>
 8#include <streambuf>
 9#include <algorithm>
10#include <utility>
11
12#include <cstddef>
13
14#include <fluxEngine/fluxEngine>
15
16#include "paths.h"
17#include "helpers.h"
18
19int main()
20{
21    try {
22        std::cout << "fluxEngine version: " << fluxEngine::versionString() << std::endl;
23        fluxEngine::Handle handle(readFile(g_licenseFileName));
24        handle.createProcessingThreads(4);
25
26        /* NOTE: if the license file is tied to the serial number of a
27         * camera, one must connect with the camera first (see the
28         * device examples for details) for the following lines of code
29         * to work (and not fail with a licensing error).
30         *
31         * If the license is tied to a dongle or a mainboard serial
32         * connecting to a camera is not necessary.
33         */
34
35        // Load data
36        fluxEngine::MeasurementList cubeList = fluxEngine::loadMeasurementList(handle, "ENVI", g_cubeFileName);
37        fluxEngine::Model model = fluxEngine::Model(handle, fluxEngine::Model::FromFile, g_modelFileName);
38
39        // Create a processing context
40        fluxEngine::ProcessingContext context = fluxEngine::ProcessingContext::createMeasurementProcessingContext(cubeList, 0, model, 0);
41        int const sinkIndex = context.findOutputSink(/* outputId = */ 0);
42
43        // Process the data
44        context.setSourceData(cubeList, 0);
45        context.processNext();
46        fluxEngine::ProcessingContext::OutputSinkData outputData = context.outputSinkData(sinkIndex);
47        fluxEngine::TensorData view{outputData};
48
49        if (view.order() != 3
50            || view.dataType() != fluxEngine::DataType::Float64
51            || view.dimension(2) != 1)
52            throw std::runtime_error("The model is not expected");
53
54        // The cube we are loading is very small (12x14 pixels),
55        // but if a larger cube is being loaded, this will produce
56        // a _lot_ of output!
57        for (int64_t y = 0; y < view.dimension(0); ++y) {
58            for (int64_t x = 0; x < view.dimension(1); ++x)
59                std::cout << "Pixel (" << x << ", " << y << ") has average value " << view.at<double>(y, x, 0) << '\n';
60        }
61        std::cout << std::flush;
62    } catch (std::exception& e) {
63        std::cerr << "Error: " << e.what() << std::endl;
64        return 1;
65    } catch (...) {
66        std::cerr << "Unknown error." << std::endl;
67        return 1;
68    }
69
70    return 0;
71}

This source file will compile to the executable ExampleReadENVIAndProcess.

The following classes and methods are among those used in this example:

.NET

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

 1using System;
 2
 3namespace ExampleReadENVIAndProcess
 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.CreateProcessingThreads(4);
12
13            /* NOTE: if the license file is tied to the serial number of a
14             * camera, one must connect with the camera first (see the
15             * device examples for details) for the following lines of code
16             * to work (and not fail with a licensing error).
17             *
18             * If the license is tied to a dongle or a mainboard serial
19             * connecting to a camera is not necessary.
20             */
21
22            // Load data
23            var cubeList = LuxFlux.fluxEngineNET.IO.LoadMeasurementList(handle, "ENVI", ExampleHelpers.Paths.ExampleDataFileName("MiniCube.hdr"));
24            var model = LuxFlux.fluxEngineNET.Model.LoadFromFile(handle, ExampleHelpers.Paths.ExampleDataFileName("instrument_function.fluxmdl"));
25
26            // Create a processing context
27            var context = LuxFlux.fluxEngineNET.ProcessingContext.CreateForMeasurement(cubeList, 0, model, 0);
28            int sinkIndex = context.OutputSinkInfoById(/* outputId = */ 0).Index;
29
30            // Process the data
31            context.SetSourceData(cubeList, 0);
32            context.ProcessNext();
33            var outputData = context.OutputSinkData(sinkIndex);
34            var data = outputData.AsTensorCopy();
35
36            if (data.Order != 3 || data.DataType != LuxFlux.fluxEngineNET.DataType.Float64 || data.Dimensions[2] != 1)
37                throw new Exception("The model is not expected");
38
39            // The cube we are loading is very small (12x14 pixels),
40            // but if a larger cube is being loaded, this will produce
41            // a _lot_ of output!
42            for (Int64 y = 0; y < data.Dimensions[0]; ++y)
43            {
44                for (Int64 x = 0; x < data.Dimensions[1]; ++x)
45                {
46                    Console.WriteLine($"Pixel ({x}, {y}) has average value {data.Value<double>(y, x, 0)}");
47                }
48            }
49
50            context.Dispose();
51            model.Dispose();
52            cubeList.Dispose();
53            handle.Dispose();
54        }
55    }
56}

The following classes and methods are among those used in this example:

Python

The source code of the example can be found in the file example_read_envi_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
15# NOTE: if the license file is tied to the serial number of a
16# camera, one must connect with the camera first (see the
17# device examples for details) for the following lines of code
18# to work (and not fail with a licensing error).
19#
20# If the license is tied to a dongle or a mainboard serial
21# connecting to a camera is not necessary.
22
23# Load model
24with open(os.path.join(data_dir, 'instrument_function.fluxmdl'), 'rb') as f:
25    model = fluxEngine.Model(handle, f.read())
26
27# Load cube
28cubeList = fluxEngine.loadMeasurementList(handle, 'ENVI', os.path.join(data_dir, 'MiniCube.hdr'))
29
30# Create a processing context
31context = fluxEngine.ProcessingContext(model, fluxEngine.ProcessingContext.MeasurementProcessing,
32                                       measurementList=cubeList, index=0)
33
34sinkIndex = context.findOutputSink(0)
35
36context.setSourceData(cubeList, 0)
37context.processNext()
38outputData = context.outputSinkData(sinkIndex)
39
40# The cube we are loading is very small (12x14 pixels),
41# but if a larger cube is being loaded, this will produce
42# a _lot_ of output!
43print(outputData[:, :, 0])

The following classes and methods are among those used in this example:

Expected Output

The output should look like the following:

fluxEngine version: [...]
Pixel (0, 0) has average value 0.652092
Pixel (1, 0) has average value 0.641689
Pixel (2, 0) has average value 0.633773
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 (8, 0) has average value 0.655668
Pixel (9, 0) has average value 0.656452
Pixel (10, 0) has average value 0.661276
Pixel (11, 0) has average value 0.671736
Pixel (12, 0) has average value 0.663536
Pixel (13, 0) has average value 0.666235
Pixel (0, 1) has average value 0.664377
Pixel (1, 1) has average value 0.656757
Pixel (2, 1) has average value 0.648442
[...]
Pixel (10, 11) has average value 0.713334
Pixel (11, 11) has average value 0.728156
Pixel (12, 11) has average value 0.725411
Pixel (13, 11) has average value 0.745923