Skip to content

OTB Examples

This page provides examples for working with OTB+ files from OT Bioelettronica devices using biosigIO.

Basic OTB Example

import matplotlib.pyplot as plt
from biosigio import Recording

# Load OTB data
data_path = 'path_to_your_otb_file.otb+'
rec = Recording.from_file(data_path, importer='otb')

# Print device information
print("\nDevice Information:")
print("-" * 50)
print(f"Device: {rec.get_metadata('device')}")
print(f"Resolution: {rec.get_metadata('signal_resolution')} bits")

# Print channel type summary
print("\nChannel Type Summary:")
print("-" * 50)
channel_types = rec.get_channel_types()
for ch_type in channel_types:
    channels = rec.get_channels_by_type(ch_type)
    print(f"{ch_type}: {len(channels)} channels")

# Plot one channel of each type (each call manages its own figure)
for ch_type in channel_types:
    channels = rec.get_channels_by_type(ch_type)
    if channels:
        # Select the first channel of this type
        sample_channel = rec.select_channels([channels[0]])
        sample_channel.plot_signals(
            time_range=(0, 5),
            title=f"{ch_type} Sample: {channels[0]}"
        )

Working with EMG Channels

OTB files often contain multiple channel types. Here's how to work specifically with EMG channels:

from biosigio import Recording
import matplotlib.pyplot as plt
import numpy as np

# Load OTB data
rec = Recording.from_file('otb_data.otb+', importer='otb')

# Create a new Recording object with only EMG channels
emg_channels = rec.get_channels_by_type('EMG')

if emg_channels:
    print(f"Found {len(emg_channels)} EMG channels")

    # Select EMG channels
    emg_data = rec.select_channels(emg_channels)

    # Plot EMG data
    plt.figure(figsize=(15, 10))

    # If there are many channels, select a subset
    channels_to_plot = emg_channels[:8] if len(emg_channels) > 8 else emg_channels

    emg_data.plot_signals(
        channels=channels_to_plot,
        time_range=(0, 5),
        title='EMG Channels from OTB File',
        grid=True
    )

    plt.tight_layout()
    plt.show()

    # Optional: Calculate and plot RMS of EMG signals
    plt.figure(figsize=(15, 6))

    # Calculate RMS in 100ms windows
    fs = emg_data.get_sampling_frequency()
    window_size = int(0.1 * fs)  # 100ms window

    for i, channel in enumerate(channels_to_plot):
        # Get signal data
        signal = emg_data.signals[channel].values

        # Calculate RMS in windows
        n_windows = len(signal) // window_size
        rms = np.zeros(n_windows)

        for w in range(n_windows):
            start = w * window_size
            end = start + window_size
            window_data = signal[start:end]
            rms[w] = np.sqrt(np.mean(np.square(window_data)))

        # Create time vector for RMS
        time = np.arange(n_windows) * (window_size / fs)

        # Plot RMS
        plt.plot(time, rms, label=channel)

    plt.title('RMS of EMG Signals (100ms windows)')
    plt.xlabel('Time (s)')
    plt.ylabel('RMS Amplitude')
    plt.legend()
    plt.grid(True)
    plt.tight_layout()
    plt.show()
else:
    print("No EMG channels found in the file")

Working with Multiple OTB Files

When working with multiple recordings from the same experiment:

from biosigio import Recording
import matplotlib.pyplot as plt

# Load two OTB files
file1 = 'session1.otb+'
file2 = 'session2.otb+'

rec1 = Recording.from_file(file1, importer='otb')
rec2 = Recording.from_file(file2, importer='otb')

# Add metadata to distinguish them
rec1.set_metadata('session', '1')
rec1.set_metadata('condition', 'rest')
rec2.set_metadata('session', '2')
rec2.set_metadata('condition', 'contraction')

# Check that they have the same channel structure
channels1 = set(rec1.channels.keys())
channels2 = set(rec2.channels.keys())
common_channels = channels1.intersection(channels2)

print(f"File 1 has {len(channels1)} channels")
print(f"File 2 has {len(channels2)} channels")
print(f"Common channels: {len(common_channels)}")

# Compare EMG channels between sessions
emg_channels = [ch for ch in common_channels 
                if rec1.channels[ch]['channel_type'] == 'EMG']

if emg_channels:
    # Select a channel to compare (each call manages its own figure)
    channel_to_compare = emg_channels[0]

    # Plot channel from first session
    rec1.plot_signals(
        [channel_to_compare],
        time_range=(0, 5),
        title=f"Session 1 ({rec1.get_metadata('condition')}): {channel_to_compare}"
    )

    # Plot same channel from second session
    rec2.plot_signals(
        [channel_to_compare],
        time_range=(0, 5),
        title=f"Session 2 ({rec2.get_metadata('condition')}): {channel_to_compare}"
    )

Exporting OTB Data to EDF/BDF

Converting OTB data to EDF/BDF format:

from biosigio import Recording

# Load OTB data
rec = Recording.from_file('data.otb+', importer='otb')

# Add metadata for export
rec.set_metadata('subject', 'S001')
rec.set_metadata('recording_date', '2023-01-15')
rec.set_metadata('experimenter', 'Researcher')

# Export all channels
output_path = 'otb_all_channels'
rec.to_edf(output_path)  # Format (EDF/BDF) selected automatically
print(f"Exported all channels to: {output_path}")

# Export only EMG channels for clarity
emg_channels = rec.get_channels_by_type('EMG')
if emg_channels:
    emg_only = rec.select_channels(emg_channels)
    output_path = 'otb_emg_only'
    emg_only.to_edf(output_path)
    print(f"Exported EMG channels to: {output_path}")

# If there are too many channels for EDF, you might need to split
# EDF has limitations on the number of channels it can handle
if len(rec.channels) > 100:  # EDF typically handles fewer channels
    print("Large number of channels detected, splitting export")

    # Split into groups of 50 channels
    channel_lists = [list(rec.channels.keys())[i:i+50] 
                    for i in range(0, len(rec.channels), 50)]

    for i, channel_list in enumerate(channel_lists):
        subset_emg = rec.select_channels(channel_list)
        output_path = f'otb_split_{i+1}'
        subset_emg.to_edf(output_path)
        print(f"Exported channel group {i+1} to: {output_path}")

These examples demonstrate how to load OTB data, explore channel information, work with specific channel types, compare multiple recordings, and export to EDF/BDF format.