Skip to main content
Skip table of contents

Prediktera Data Server

The Prediktera Data Server is used to receive data streamed in real-time from other software into Breeze. It can be used when there is no built-in support for a specific camera in Breeze.

More than one Prediktera Data Server can be set up on a Breeze computer.

How it works

The Data Server acts like a line scan camera in Breeze, and as such it has settings that define the dimensions of the data: the pixel resolution, number of bands and data type. It also has a setting for TCP port that specifies where Breeze will be listening for the data.

Once the settings have been made, and Breeze has connected to the Data Server “camera”, the port is listening for data. The data pushed to the port must be in the correct ENVI BIL format as documented below, matching the data dimension configured for the camera.

The external software decides on the timing of data and must send the data one frame (line) at the time.

At the end of this page, we provide sample Python code that streams data to Breeze using the Data Server.

Using the Prediktera Data Server camera

Breeze will use the Data Server camera as any other camera, and as such it can be used to record data for later processing in Breeze, or to run live data through a an analysis workflow (analyse tree in the Play functionality).

To learn more about programmatic control of Breeze, see the Developers reference guide

Notes on merging data with another camera

Data from the Data Server camera and data from another camera can be merged in Breeze. We recommend you set up the Data Server camera as the first camera and give it the same resolution as the native resolution of the second camera. Then add and configure the second camera in Breeze, and use the Merge settings “None”. This will result in a merged data cube where the first bands will come from the Data Server camera, and the other bands from the second camera.

Learn more Merging images.

Timing of frames is very important for the data frames from the two cameras to align. We recommend that frames are triggered using an external trigger for all cameras and thus will be read in sync by Breeze.

If an external trigger cannot be used, an offset or delay can be used to mitigate the problem of synchronization but it still can be very hard to synchronize cameras, especially in industrial applications where conveyor belts can have varying speeds.

If only Data Server cameras are used, synchronization is easier, because data can be pushed to both cameras in sync.

Configuration

These are the setting for the Data Server camera. The settings in this screenshot matches the Python code at the end of this page.

When you click Connect at the end of the settings page, Breeze will start listening to the configured port for data.

image-20250520-135911.png

Type

Server (only available option). Streaming data from TCP server.

TCP port

Specify the TCP port that Breeze will listen to for data.

Width

Frame width in pixels.

Number of bands (height)

The number of data dimensions for each pixel.

Band names

The wavelength names, usually in nanometers, as a semicolon-separated list.

Tip: If you already have a ENVI file with the right header names, you can Import them using the Import button on the settings page.

Example from nuts tutorial data:

TEXT
1164.52;1209.84;1255.04;1300.16;1345.2;1390.17;1435.09;1479.97;1524.81;1569.64;1614.45;1659.25;1704.05;1748.85;1793.66;1838.47;1883.3;1928.12;1972.95;2017.79;2062.62;2107.45;2152.26;2197.05;2241.81;2286.53;2331.2;2375.81;2420.34;2464.78;2509.12

Data size

  • Byte: 1 byte

  • Short: 2 bytes

  • Float: 4 bytes

  • Double: 8 bytes

The size of each data value.

Max signal

The expected maximum signal value:
1 for adjusted raw images (e.g. reflectance), or the maximum value for raw data.

Frame format

Frames must be in ENVI BIL format for correct processing. The dimensions must match what has been configured the Prediktera Data Server camera in Breeze Settings.

TEXT
[ Frame Number (4 bytes) ][ BIL Data (Width x Height x Data Size) ]

Frame Number

  • Type: UInt32

    • Endianness: Big-endian

    • Size: 4 bytes

The frame number is typically expected to increase by 1 for each frame.

BIL Data

  • Format:

    • The format should align with the expected Breeze Runtime workflow, e.g., Float32 reflectance with a maximum signal of 1.

    • Float32 for adjusted raw data (e.g., reflectance, absorption)

    • Otherwise, raw data size based on configuration

  • Size: Width x Height x Data Size bytes

Ensure the corresponding value is set in Breeze.

Example code sending frames to Breeze

Python code to read an ENVI BIL file in Float32 and send it frame by frame to the Prediktera Data Server over TCP/IP. Each frame is prepended with its frame number.

PY
import socket
import time
import struct
import keyboard
import numpy as np

# Configuration
server_ip = '127.0.0.1'  # Replace with the actual IP of the Prediktera Data Server
server_port = 2200  # Replace with the actual port for receiving data
envi_file_path = 'path to file'  # Path to your ENVI BIL file
frame_width = 384  # Width of each frame in pixels
frame_height = 31  # Height of each frame in wavelengths
frame_rate = 100  # Desired frame rate in frames per second (fps)
frame_number = 1


# Function to read ENVI BIL data from disk
def read_envi_bil(filepath, width, height):
    with open(filepath, 'rb') as f:
        # Read the entire file into a numpy array
        data = np.fromfile(f, dtype=np.float32)
        
        # data = np.fromfile(f, dtype=np.uint16) # For standard short raw data
        # Reshape the data to (frame_height, frame_width)
        frames = data.reshape((-1, height, width))
    return frames


# Function to send frame data to Prediktera Data Server
def send_frame(frame, connection):
    global frame_number

    # Flatten the frame to a 1D array
    flat_frame = frame.flatten()

    # Convert the frame data to bytes
    frame_bytes = flat_frame.tobytes()

    # Convert frame number to big endian UInt32
    frame_number_bytes = struct.pack('!I', frame_number)

    frame_number += 1

    # Send the frame number followed by the frame data over TCP
    connection.sendall(frame_number_bytes + frame_bytes)


# Main function to read and send ENVI BIL data
def main():
    # Read ENVI BIL data
    frames = read_envi_bil(envi_file_path, frame_width, frame_height)

    # Calculate the time delay between frames
    frame_delay = 1.0 / frame_rate

    # Establish a connection to the Prediktera Data Server
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((server_ip, server_port))

        # Loop to continuously send frames until q key is pressed
        while not keyboard.is_pressed('q'):
            for i, frame in enumerate(frames):
                start_time = time.time()

                send_frame(frame, s)

                # Ensure the frame rate by waiting before sending the next frame
                elapsed_time = time.time() - start_time
                time_to_wait = frame_delay - elapsed_time
                if time_to_wait > 0:
                    time.sleep(time_to_wait)

                if keyboard.is_pressed('q'):
                    break


if __name__ == "__main__":
    main()

Follow this article for additional information on device configuration: Hardware and settings guide

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.