Runnable Examples
fluxEngine comes with several example programs that the user may run. It also comes with a simple example cube (reduced to a small size) and an example model that does nothing but average the spectrum.
C++ Examples
The C++ examples can be found in the directory examples/cpp
in the
fluxEngine directory. It uses the CMake build system to build the
various examples.
As a first step the user must modify the file
examples/cpp/paths.h
and adjust the following paths:
g_licenseFileName
– the path to the license file for fluxEngine
g_driverDirectory
– the path to the directory containing the device drivers (may be left as-is if no device-specific examples are to be tested)
g_recordingCubeFileName
– the name of the ENVI file that will be written by the examples that generate ENVI recordings
In paths.h
there are two different path definitions, depending on
the operating system.
On Windows the paths should be specified as a
std::wstring
so that Unicode paths will work.(It is also possible to specify them as a
std::string
on Windows, but then only the local code page (CP_ACP
) is used to encode the file names, which may mean that some file names cannot be represented in this manner.)On Linux and macOS the paths must be specified as a
std::string
as these platforms always encoude their paths in 8bit.
Note
On Windows it should be noted that the directory separator, \
,
must be escaped as \\
in a C/C++ string. For example, write
L"C:\\Users\\developer\\Desktop\\fluxEngine.lic"
, which the
C++ compiler will then interpret correctly as the path
C:\Users\developer\Desktop\fluxEngine.lic
.
After paths.h
has been adjusted, CMake must be run. The same CMake
snippet that is described in Building with CMake is
used here, so the user must specify the base directory for fluxEngine
as an argument to CMake.
The following console snippet shows how this may be done on Windows:
C:\Users\developer\Documents\fluxEngine-latest\examples\cpp> mkdir build
C:\Users\developer\Documents\fluxEngine-latest\examples\cpp> cd build
C:\Users\developer\Documents\fluxEngine-latest\examples\cpp\build> cmake -G "GENERATOR" .. -D FLUXENGINE_DIR=C:\Users\developer\Documents\fluxEngine-latest
The GENERATOR
should be replaced with the correct generator for the
compiler in use, e.g. cmake -G "Visual Studio 16 2019" -A "x64"
for
Visual Studio 2019 or cmake -G "MinGW Makefiles"
for MinGW.
The following console snippet shows how this may be done on Linux:
/home/developer/fluxEngine-latest/examples/cpp$ mkdir build
/home/developer/fluxEngine-latest/examples/cpp$ cd build
/home/developer/fluxEngine-latest/examples/build$ cmake .. -D FLUXENGINE_DIR=/home/developer/fluxEngine-latest
After CMake has run the examples may now be built. This may either be
done via cmake --build
from the command line, or, alterantively,
via the development tools directly.
The following sections describe the available examples.
There are several helper methods that may be found in helpers.h
and
helpers.cpp
. They exist for handling file-names properly in a
cross-plattform way. On Windows systems the function
encodeFileNameForConnectionParameter()
may be of particular
interest, as it shows how to properly encode filenames for device
connection parameters.
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 calculatese the
spectral average for each pixel.
There are two versions of this example: one that uses the
fluxEngine::createMeasurementProcessingContext()
function
to create the processing context, and another that does it manually via
the constructor of the
ProcessingContext
class.
The source files are example_read_envi_and_process.cpp
for the
simple version, and example_read_envi_and_process_explicit.cpp
for
the explicit version.
The executable names are ExampleReadENVIAndProcess
and
ExampleReadENVIAndProcessExplicit
, respectively.
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
Enumerate Devices
The example will enumerate all devices that could be found with the drivers that were provided. The driver directory has to be set properly, otherwise no devices and no drivers will be found.
The source file name is example_enumerate_devices.cpp
.
The executable name is ExampleEnumerateDevices
.
When only the virtual pushbroom camera driver is available in the drivers directory, the following output will appear (after 10s):
fluxEngine version: [...]
Found driver VirtualHyperCamera with state OK
Found device for driver VirtualHyperCamera
- Display name: Virtual Hyper Camera Driver
- Manufacturer:
- Model: Virtual Hyper Camera Driver
- Serial number:
- Connection parameters:
- CameraType (Enumeration); default value = PushBroom (0)
- PushBroom = 0
- Cube (File); default value =
- DarkReferenceCube (File); default value =
- WhiteReferenceCube (File); default value =
Obtain a frame from a camera
This example will connect to the virtual pushbroom camera (using
MiniCube.hdr
and its references), obtain a single frame, and
display the values of the upper left 4x4 pixels of the frame.
The source file name is example_obtain_camera_buffer.cpp
.
The executable name is ExampleObtainCameraBuffer
.
The output should look like the following:
fluxEngine version: [...]
Attempting to connect to device...
Connected.
Device parameters:
- Interval (Integer)
Starting acquisition:
Done.
Obtaining buffer:
Done.
Stopping acquisition:
Done.
Pixel value @(0, 0) = 6153
Pixel value @(1, 0) = 5114
Pixel value @(2, 0) = 6143
Pixel value @(3, 0) = 7069
Pixel value @(4, 0) = 7856
Pixel value @(0, 1) = 6143
Pixel value @(1, 1) = 5099
Pixel value @(2, 1) = 6119
Pixel value @(3, 1) = 6966
Pixel value @(4, 1) = 7805
Pixel value @(0, 2) = 6186
Pixel value @(1, 2) = 5142
Pixel value @(2, 2) = 6212
Pixel value @(3, 2) = 7114
Pixel value @(4, 2) = 7862
Pixel value @(0, 3) = 6152
Pixel value @(1, 3) = 5171
Pixel value @(2, 3) = 6159
Pixel value @(3, 3) = 7142
Pixel value @(4, 3) = 7882
Pixel value @(0, 4) = 6227
Pixel value @(1, 4) = 5164
Pixel value @(2, 4) = 6192
Pixel value @(3, 4) = 7118
Pixel value @(4, 4) = 7893
Generate a Preview for a PushBroom
This example will connect to the virtual pushbroom camera (using
MiniCube.hdr
and its references), create a instrument preview
processing context for the PushBroom and run it for 10 frames. It will
display the first 6 pixels of each of these lines.
Note
The behavior of this example changed slightly in version 4.11 with the virtual camera; in previous versions it would depend on the camera driver whether the wavelengths were averaged, but starting in version 4.11 the spectral bands are always averaged for previews, regardless of the specific camera driver.
The source file name is example_pushbroom_preview.cpp
.
The executable name is ExamplePushBroomPreview
.
The output should look like the following:
fluxEngine version: [...]
Attempting to connect to device...
Connected.
Starting acquisition:
Done.
Generating preview "image" for the first 10 lines:
7217.22 7160.26 7168.58 7146.76 7159.23 7192.86
7348.53 7317.49 7322.11 7314.67 7316.54 7305.82
7441.55 7431.62 7447.21 7439.7 7431.3 7396.99
7485.26 7476.21 7511.7 7488.82 7479.78 7450.21
7516.45 7492.98 7555.88 7512.07 7508.67 7492.33
7539.83 7494.71 7578.19 7520.96 7533.36 7524.27
7553.11 7498.3 7589.73 7525.6 7552.7 7546.77
7570.4 7507.74 7596.02 7532.91 7581.62 7576.05
7597.72 7538.99 7609.41 7555.27 7619.44 7610.17
7635.46 7582.75 7630.93 7591.69 7655.63 7643.03
Stopping acquisition:
Done.
Record an ENVI Cube in Intensities with References from a PushBroom
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 and create an ENVI recording
consisting of the first 100 lines returned from the device.
The source file name is example_pushbroom_create_envi.cpp
.
The executable name is ExamplePushBroomCreateENVI
.
The output should look like the following:
fluxEngine version: [...]
Attempting to connect to device...
- DarkReferenceCube: examples/data/MiniCube_Dark.hdr
- Cube: examples/data/MiniCube.hdr
- WhiteReferenceCube: examples/data/MiniCube_White.hdr
Connected.
Measuring white reference:
Done.
Measuring dark reference:
Done.
The recording will create a cube with the wavelengths: [945.03, 948.2, 951.37, 954.54, 957.7, 960.87, 964.04, 967.2, 970.37, 973.54, 976.7, 979.86, 983.03, 986.19, 989.36, 992.52, 995.68, 998.84, 1002, 1005.16, 1008.33, 1011.49, 1014.65, 1017.8, 1020.96, 1024.12, 1027.28, 1030.44, 1033.6, 1036.75, 1039.91, 1043.06, 1046.22, 1049.38, 1052.53, 1055.68, 1058.84, 1061.99, 1065.15, 1068.3, 1071.45, 1074.6, 1077.75, 1080.9, 1084.06, 1087.21, 1090.36, 1093.5, 1096.65, 1099.8, 1102.95, 1106.1, 1109.25, 1112.39, 1115.54, 1118.69, 1121.83, 1124.98, 1128.12, 1131.27, 1134.41, 1137.55, 1140.7, 1143.84, 1146.98, 1150.12, 1153.27, 1156.41, 1159.55, 1162.69, 1165.83, 1168.97, 1172.11, 1175.25, 1178.39, 1181.52, 1184.66, 1187.8, 1190.94, 1194.07, 1197.21, 1200.34, 1203.48, 1206.61, 1209.75, 1212.88, 1216.02, 1219.15, 1222.28, 1225.41, 1228.55, 1231.68, 1234.81, 1237.94, 1241.07, 1244.2, 1247.33, 1250.46, 1253.59, 1256.72, 1259.85, 1262.97, 1266.1, 1269.23, 1272.36, 1275.48, 1278.61, 1281.73, 1284.86, 1287.98, 1291.11, 1294.23, 1297.35, 1300.48, 1303.6, 1306.72, 1309.85, 1312.97, 1316.09, 1319.21, 1322.33, 1325.45, 1328.57, 1331.69, 1334.81, 1337.93, 1341.04, 1344.16, 1347.28, 1350.4, 1353.51, 1356.63, 1359.75, 1362.86, 1365.98, 1369.09, 1372.21, 1375.32, 1378.43, 1381.55, 1384.66, 1387.77, 1390.88, 1394, 1397.11, 1400.22, 1403.33, 1406.44, 1409.55, 1412.66, 1415.77, 1418.88, 1421.99, 1425.09, 1428.2, 1431.31, 1434.42, 1437.52, 1440.63, 1443.73, 1446.84, 1449.94, 1453.05, 1456.15, 1459.26, 1462.36, 1465.47, 1468.57, 1471.67, 1474.77, 1477.87, 1480.98, 1484.08, 1487.18, 1490.28, 1493.38, 1496.48, 1499.58, 1502.68, 1505.78, 1508.87, 1511.97, 1515.07, 1518.17, 1521.26, 1524.36, 1527.46, 1530.55, 1533.65, 1536.74, 1539.84, 1542.93, 1546.02, 1549.12, 1552.21, 1555.3, 1558.4, 1561.49, 1564.58, 1567.67, 1570.76, 1573.85, 1576.94, 1580.03, 1583.12, 1586.21, 1589.3, 1592.39, 1595.48, 1598.57, 1601.66, 1604.74, 1607.83, 1610.92, 1614, 1617.09, 1620.17, 1623.26, 1626.34, 1629.43, 1632.51, 1635.6, 1638.68, 1641.76, 1644.85, 1647.93, 1651.01, 1654.09, 1657.17, 1660.25, 1663.34, 1666.42, 1669.5, 1672.58, 1675.66, 1678.73, 1681.81, 1684.89, 1687.97, 1691.05, 1694.12, 1697.2, 1700.28, 1703.35, 1706.43, 1709.51, 1712.58, 1715.66, 1718.73, 1721.81, 1724.88, 1727.95, 1731.03, 1734.1, 1737.17, 1740.24]
Starting acquisition:
Done.
Recording buffers....................................................................................................
Stopping acquisition:
Done.
Creating measurement:
Done.
Saving measurement to disk:
Done.
This will then store an ENVI cube in the file name specified in
g_recordingCubeFileName
. The cube will be saved in intensities, and
a white and dark reference cube will also be written.
Record an ENVI Cube in Intensities with References from a PushBroom (Normalized)
This example is identical to the previous example, but it generates an ENVI cube in reflectances, and normalizes the wavelengths to a regular grid from 950nm to 1650nm in steps of 4nm.
The source file name is example_pushbroom_create_envi_normalized.cpp
.
The executable name is ExamplePushBroomCreateENVINormalized
.
The output should look like the following:
fluxEngine version: [...]
Attempting to connect to device...
- DarkReferenceCube: examples/data/MiniCube_Dark.hdr
- Cube: examples/data/MiniCube.hdr
- WhiteReferenceCube: examples/data/MiniCube_White.hdr
Connected.
Measuring white reference:
Done.
Measuring dark reference:
Done.
The recording will create a cube with the wavelengths: [950, 954, 958, 962, 966, 970, 974, 978, 982, 986, 990, 994, 998, 1002, 1006, 1010, 1014, 1018, 1022, 1026, 1030, 1034, 1038, 1042, 1046, 1050, 1054, 1058, 1062, 1066, 1070, 1074, 1078, 1082, 1086, 1090, 1094, 1098, 1102, 1106, 1110, 1114, 1118, 1122, 1126, 1130, 1134, 1138, 1142, 1146, 1150, 1154, 1158, 1162, 1166, 1170, 1174, 1178, 1182, 1186, 1190, 1194, 1198, 1202, 1206, 1210, 1214, 1218, 1222, 1226, 1230, 1234, 1238, 1242, 1246, 1250, 1254, 1258, 1262, 1266, 1270, 1274, 1278, 1282, 1286, 1290, 1294, 1298, 1302, 1306, 1310, 1314, 1318, 1322, 1326, 1330, 1334, 1338, 1342, 1346, 1350, 1354, 1358, 1362, 1366, 1370, 1374, 1378, 1382, 1386, 1390, 1394, 1398, 1402, 1406, 1410, 1414, 1418, 1422, 1426, 1430, 1434, 1438, 1442, 1446, 1450, 1454, 1458, 1462, 1466, 1470, 1474, 1478, 1482, 1486, 1490, 1494, 1498, 1502, 1506, 1510, 1514, 1518, 1522, 1526, 1530, 1534, 1538, 1542, 1546, 1550, 1554, 1558, 1562, 1566, 1570, 1574, 1578, 1582, 1586, 1590, 1594, 1598, 1602, 1606, 1610, 1614, 1618, 1622, 1626, 1630, 1634, 1638, 1642, 1646, 1650]
Starting acquisition:
Done.
Recording buffers....................................................................................................
Stopping acquisition:
Done.
Creating measurement:
Done.
Saving measurement to disk:
Done.
This will then store an ENVI cube in the file name specified in
g_recordingCubeFileName
. The cube will be saved in reflectances,
and no references will be saved for this reason.
Record an ENVI Cube in Intensities with References from a PushBroom While Generating a Preview
This example is identical to the PushBroom recording example, but it also generates a preview image at the same time while the recording is being performed. This may be useful when creating a user-facing application that wants to display a preview of the data that is currently being recorded, while not having to create a separate processing context for the preview data itself.
The source file name is example_pushbroom_create_envi_with_preview.cpp
.
The executable name is ExamplePushBroomCreateENVIWithPreview
.
The output should look like the following:
fluxEngine version: 4.11.0~rc1
Attempting to connect to device...
- DarkReferenceCube: /home/christian/LuxFlux/Code/fluxEnginePublic/examples/data/MiniCube_Dark.hdr
- WhiteReferenceCube: /home/christian/LuxFlux/Code/fluxEnginePublic/examples/data/MiniCube_White.hdr
- Cube: /home/christian/LuxFlux/Code/fluxEnginePublic/examples/data/MiniCube.hdr
Connected.
Measuring white reference:
Done.
Measuring dark reference:
Done.
The recording will create a cube with the wavelengths: [945.03, 948.2, 951.37, 954.54, 957.7, 960.87, 964.04, 967.2, 970.37, 973.54, 976.7, 979.86, 983.03, 986.19, 989.36, 992.52, 995.68, 998.84, 1002, 1005.16, 1008.33, 1011.49, 1014.65, 1017.8, 1020.96, 1024.12, 1027.28, 1030.44, 1033.6, 1036.75, 1039.91, 1043.06, 1046.22, 1049.38, 1052.53, 1055.68, 1058.84, 1061.99, 1065.15, 1068.3, 1071.45, 1074.6, 1077.75, 1080.9, 1084.06, 1087.21, 1090.36, 1093.5, 1096.65, 1099.8, 1102.95, 1106.1, 1109.25, 1112.39, 1115.54, 1118.69, 1121.83, 1124.98, 1128.12, 1131.27, 1134.41, 1137.55, 1140.7, 1143.84, 1146.98, 1150.12, 1153.27, 1156.41, 1159.55, 1162.69, 1165.83, 1168.97, 1172.11, 1175.25, 1178.39, 1181.52, 1184.66, 1187.8, 1190.94, 1194.07, 1197.21, 1200.34, 1203.48, 1206.61, 1209.75, 1212.88, 1216.02, 1219.15, 1222.28, 1225.41, 1228.55, 1231.68, 1234.81, 1237.94, 1241.07, 1244.2, 1247.33, 1250.46, 1253.59, 1256.72, 1259.85, 1262.97, 1266.1, 1269.23, 1272.36, 1275.48, 1278.61, 1281.73, 1284.86, 1287.98, 1291.11, 1294.23, 1297.35, 1300.48, 1303.6, 1306.72, 1309.85, 1312.97, 1316.09, 1319.21, 1322.33, 1325.45, 1328.57, 1331.69, 1334.81, 1337.93, 1341.04, 1344.16, 1347.28, 1350.4, 1353.51, 1356.63, 1359.75, 1362.86, 1365.98, 1369.09, 1372.21, 1375.32, 1378.43, 1381.55, 1384.66, 1387.77, 1390.88, 1394, 1397.11, 1400.22, 1403.33, 1406.44, 1409.55, 1412.66, 1415.77, 1418.88, 1421.99, 1425.09, 1428.2, 1431.31, 1434.42, 1437.52, 1440.63, 1443.73, 1446.84, 1449.94, 1453.05, 1456.15, 1459.26, 1462.36, 1465.47, 1468.57, 1471.67, 1474.77, 1477.87, 1480.98, 1484.08, 1487.18, 1490.28, 1493.38, 1496.48, 1499.58, 1502.68, 1505.78, 1508.87, 1511.97, 1515.07, 1518.17, 1521.26, 1524.36, 1527.46, 1530.55, 1533.65, 1536.74, 1539.84, 1542.93, 1546.02, 1549.12, 1552.21, 1555.3, 1558.4, 1561.49, 1564.58, 1567.67, 1570.76, 1573.85, 1576.94, 1580.03, 1583.12, 1586.21, 1589.3, 1592.39, 1595.48, 1598.57, 1601.66, 1604.74, 1607.83, 1610.92, 1614, 1617.09, 1620.17, 1623.26, 1626.34, 1629.43, 1632.51, 1635.6, 1638.68, 1641.76, 1644.85, 1647.93, 1651.01, 1654.09, 1657.17, 1660.25, 1663.34, 1666.42, 1669.5, 1672.58, 1675.66, 1678.73, 1681.81, 1684.89, 1687.97, 1691.05, 1694.12, 1697.2, 1700.28, 1703.35, 1706.43, 1709.51, 1712.58, 1715.66, 1718.73, 1721.81, 1724.88, 1727.95, 1731.03, 1734.1, 1737.17, 1740.24]
Starting acquisition:
Done.
Recording buffers while generating preview:
7217.22 7160.26 7168.58 7146.76 7159.23 7192.86
7348.53 7317.49 7322.11 7314.67 7316.54 7305.82
7441.55 7431.62 7447.21 7439.7 7431.3 7396.99
[... more output here ...]
7348.53 7317.49 7322.11 7314.67 7316.54 7305.82
7441.55 7431.62 7447.21 7439.7 7431.3 7396.99
7485.26 7476.21 7511.7 7488.82 7479.78 7450.21
Stopping acquisition:
Done.
Creating measurement:
Done.
Saving measurement to disk:
Done.
This will then store an ENVI cube in the file name specified in
g_recordingCubeFileName
. The cube will be saved in reflectances,
and no references will be saved for this reason.
Process Data from a PushBroom Device in a Model
This example will connect to the virtual pushbroom camera (using
MiniCube.hdr
and its references), measure a white & dark reference,
create a processing context for the model
instrument_function.fluxmdl
. The first 10 lines returned from the
device will be processed, and the spectral average at the 4 left-most
pixels for each of these lines will be shown.
The source file name is example_pushbroom_process_model.cpp.cpp
.
The executable name is ExamplePushBroomProcessModel
.
The output should look like the following:
fluxEngine version: [...]
Attempting to connect to device...
- DarkReferenceCube: examples/data/MiniCube_Dark.hdr
- Cube: examples/data/MiniCube.hdr
- WhiteReferenceCube: examples/data/MiniCube_White.hdr
Connected.
Measuring white reference:
Done.
Measuring dark reference:
Done.
Starting acquisition:
Done.
Processing the first 10 lines...
Spectral Average @(0, 0) = 0.652092
Spectral Average @(1, 0) = 0.641689
Spectral Average @(2, 0) = 0.633773
Spectral Average @(3, 0) = 0.636609
Spectral Average @(0, 1) = 0.664377
Spectral Average @(1, 1) = 0.656757
[...]
Spectral Average @(2, 8) = 0.67596
Spectral Average @(3, 8) = 0.674892
Spectral Average @(0, 9) = 0.691204
Spectral Average @(1, 9) = 0.68223
Spectral Average @(2, 9) = 0.678032
Spectral Average @(3, 9) = 0.678329
Stopping acquisition:
Done.
Python Examples
The Python examples can be found in the directory examples/python
in the fluxEngine directory.
As a first step the user must modify the file
examples/python/fluxEngine_example_paths.h
and adjust the following
paths:
licenseFileName
– the path to the license file for fluxEngine
driverDirectory
– the path to the directory containing the device drivers (may be left as-is if no device-specific examples are to be tested)
recordingCubeFileName
– the name of the ENVI file that will be written by the examples that generate ENVI recordings
The examples have the same functionality as the corresponding C++ examples with the same name and produce approximately the same output.