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.

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:
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.
[ 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.
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