Skip to content

OTB Examples

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

Basic OTB Example

import matplotlib.pyplot as plt
from emgio import EMG

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

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

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

# Plot one channel of each type
plt.figure(figsize=(12, 8))
subplot_count = len(channel_types)
for i, ch_type in enumerate(channel_types, 1):
    channels = emg.get_channels_by_type(ch_type)
    if channels:
        plt.subplot(subplot_count, 1, i)
        # Select the first channel of this type
        sample_channel = emg.select_channels([channels[0]])
        sample_channel.plot_signals(
            time_range=(0, 5),
            title=f"{ch_type} Sample: {channels[0]}",
            ax=plt.gca()
        )

plt.tight_layout()
plt.show()

Working with EMG Channels

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

from emgio import EMG
import matplotlib.pyplot as plt
import numpy as np

# Load OTB data
emg = EMG.from_file('otb_data.otb+', importer='otb')

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

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

    # Select EMG channels
    emg_data = emg.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 emgio import EMG
import matplotlib.pyplot as plt

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

emg1 = EMG.from_file(file1, importer='otb')
emg2 = EMG.from_file(file2, importer='otb')

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

# Check that they have the same channel structure
channels1 = set(emg1.channels.keys())
channels2 = set(emg2.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 emg1.channels[ch]['channel_type'] == 'EMG']

if emg_channels:
    # Select a channel to compare
    channel_to_compare = emg_channels[0]

    plt.figure(figsize=(12, 8))

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

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

    plt.tight_layout()
    plt.show()

Exporting OTB Data to EDF/BDF

Converting OTB data to EDF/BDF format:

from emgio import EMG

# Load OTB data
emg = EMG.from_file('data.otb+', importer='otb')

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

# Export all channels
output_path = 'otb_all_channels'
emg.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 = emg.get_channels_by_type('EMG')
if emg_channels:
    emg_only = emg.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(emg.channels) > 100:  # EDF typically handles fewer channels
    print("Large number of channels detected, splitting export")

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

    for i, channel_list in enumerate(channel_lists):
        subset_emg = emg.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.