General API Design, Error Handling

The .NET API is a wrapper around the existing C/C++ API of fluxEngine that follows the following guidelines:

  • While some classes are instantiated by calling their constructors, more complex classes can only be created by calling static methods.

  • All classes that wrap native objects implement the IDisposable interface.

  • All classes that wrap native objects also implement finalizers in case the user forgot to call Dispose().

  • Errors are reported by throwing exceptions.

  • Timeouts are specified via System.TimeSpan.


The .NET API design of fluxEngine is currently not finalized and may be subject to minor alterations in the future.

Error Handling

API calls that result in an error will throw an exception. The exception will be one of the following:

  • ArgumentException if an invalid argument was passed to the method in question

  • OutOfMemoryException if an allocation failed (most likely due to being out of memory)

  • ArgumentOutOfRangeException if an index was supplied that is not within the valid range

  • ArgumentOutOfRangeException if an index was supplied that is not within the valid range

  • System.IO.IOException or a subclass if a file operating was the cause of the error

  • LuxFlux.fluxEngineNET.Error or a subclass thereof (which in itself is a subclass of Exception) if an error occurred that does not fall into the previous categories

  • If a user-supplied callback is provided, and that callbacks throws any exception, that exception is then propagated back out to the user

All exceptions that are either LuxFlux.fluxEngineNET.Error or a subclass thereof have additional fields for more information about the error:

  • Accessing Code on the exception object will return an error code of type LuxFlux.fluxEngineNET.ErrorCode that allows the user to further identify the type of error that occurred.

  • Accessing OSErrorCode on the exception object will return an operating system error code if the operation failed due to a system call failing

See the documentation of LuxFlux.fluxEngineNET.Error and LuxFlux.fluxEngineNET.ErrorCode for further details.

Initializing the Library

To initialize the library a license file is required. The user must read that license file into memory and supply fluxEngine with it.

The following code demonstrates how to properly initialize fluxLicense and how to tear it down again.

 1 // Get the data of the license file from somewhere
 2 byte[] licenseData = System.IO.File.ReadAllBytes(fileName);
 3 try
 4 {
 5     var handle = new LuxFlux.fluxEngineNET.Handle(licenseData);
 6     // handle is now valid, may be used
 7     handle.Dispose();
 8     // handle has now been disposed
 9 }
10 catch (Exception e)
11 {
12     Console.WriteLine($"Error: {e.Message}");
13 }

Licenses tied to camera serial numbers

If a license is tied to a camera serial number, certain operations will fail unless the camera is currently connected. These operations include (but are not limited to):

  • Loading a model

  • Creating a processing context (even for offline processing)

  • Processing data with an already existing processing context

  • Loading a HSI cube from disk

For this reason, even if only offline data is to be processed, if a license file is tied to a camera serial number, the user must always first connect to that camera before performing any of these operations. The camera must stay connected while the user wants to perform any of these operations.

It is still possible to save HSI cubes to disk even if no camera is connected. This is to ensure that the camera fails unexpectedly during operation (because e.g. somebody unplugged it) to give the user a chance to save the data they curreently have in memory.

If the license is tied to a dongle or a mainboard serial, this does not apply, and these operations can be performed at any time after a handle has been created. (If a dongle is phyiscally removed after creating a handle, the same restrictions apply though.)

Setting up processing threads

fluxEngine supports parallel processing, but it has to be set up at the very beginning. This is done via the CreateProcessingThreads() method.

The following example code demonstrates how to perform processing with 4 threads, assuming a handle has already been created:

1 try
2 {
3     handle.CreateProcessingThreads(4);
4 }
5 catch (Exception e)
6 {
7     Console.WriteLine($"Error: {e.Message}");
8 }


This will only create 3 (not 4!) background threads that will help with data processing. The thread that calls ProcessingContext.ProcessNext() will be considered the first thread (with index 0) that participates in parallel processing.


Modern processors support Hyperthreading (Intel) or SMT (AMD) to provide more logical cores that are phyiscally available. It is generally not recommended to use more threads than are phyiscally available, as workloads such as fluxEngine will typically slow down when using more cores in a system than are physically available.


When running fluxEngine with very small amounts of data, in the extreme case with cubes that have only one pixel, parallelization will not improve performance. In cases where cubes consisting of only one pixel are processed, it is recommended to not parallelize at all and skip this step.


Only one fluxEngine operation may be performed per handle at the same time; executing multiple processing contexts from different threads will cause them to be run sequentially.

Since it is currently possible to only create a single handle for fluxEngine, this means only one operation can be active at the same time; though the limitation of only a single handle will be lifted in a later version of fluxEngine.