Skip to main content
Skip table of contents

Prediktera Data Server

Overview:
The Prediktera Data Server receives frames in ENVI BIL format over TCP/IP in real-time. The received frames are processed using a user-defined Analysis Tree, and the prediction results are sent back through the TCP/IP data stream or event port. See Developers reference guide

See Developer reference guide | Prediktera Data Server for integrated setup of data streaming server.

Communication:

  • TCP/IP Ports: The server listens on the specified port for incoming data.

  • Data Format: Frames must be in ENVI BIL format for correct processing. The format should align with the expected Breeze Runtime workflow, e.g., Float32 reflectance with a maximum signal of 1.

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.

Configuration

Type

  • Server

    • Streaming data from TCP server.

Port

Specify the streaming port.

Width

Frame width in pixels.

Height

Number of bands.

Max signal

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

Data size

  • Byte: 1 byte

  • Short: 2 bytes

  • Float: 4 bytes

  • Double: 8 bytes

The expected size of each data value.

Wavelength

The wavelength names, usually in nanometers, as a semicolon-separated list, or read from a header file.

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

Frame format

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

Frame Number

  • Type: UInt32

    • Endianness: Big-endian

    • Size: 4 bytes

BIL Data

  • Format:

    • 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

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.