Source code for utils.intan.intanutil.read_header
#! /bin/env python
#
# Michael Gibson 23 April 2015
import struct
import sys
from .qstring import read_qstring
[docs]def read_header(fid):
"""Reads the Intan File Format header from the given file."""
# Check 'magic number' at beginning of file to make sure this is an Intan
# Technologies RHD2000 data file.
(magic_number,) = struct.unpack("<I", fid.read(4))
if magic_number != int("c6912702", 16):
raise Exception("Unrecognized file type.")
header = {}
# Read version number.
version = {}
(version["major"], version["minor"]) = struct.unpack("<hh", fid.read(4))
header["version"] = version
# print('')
# print('Reading Intan Technologies RHD2000 Data File, Version {}.{}'.format(version['major'], version['minor']))
# print('')
freq = {}
# Read information of sampling rate and amplifier frequency settings.
(header["sample_rate"],) = struct.unpack("<f", fid.read(4))
(
freq["dsp_enabled"],
freq["actual_dsp_cutoff_frequency"],
freq["actual_lower_bandwidth"],
freq["actual_upper_bandwidth"],
freq["desired_dsp_cutoff_frequency"],
freq["desired_lower_bandwidth"],
freq["desired_upper_bandwidth"],
) = struct.unpack("<hffffff", fid.read(26))
# This tells us if a software 50/60 Hz notch filter was enabled during
# the data acquisition.
(notch_filter_mode,) = struct.unpack("<h", fid.read(2))
header["notch_filter_frequency"] = 0
if notch_filter_mode == 1:
header["notch_filter_frequency"] = 50
elif notch_filter_mode == 2:
header["notch_filter_frequency"] = 60
freq["notch_filter_frequency"] = header["notch_filter_frequency"]
(
freq["desired_impedance_test_frequency"],
freq["actual_impedance_test_frequency"],
) = struct.unpack("<ff", fid.read(8))
note1 = read_qstring(fid)
note2 = read_qstring(fid)
note3 = read_qstring(fid)
header["notes"] = {"note1": note1, "note2": note2, "note3": note3}
# If data file is from GUI v1.1 or later, see if temperature sensor data was saved.
header["num_temp_sensor_channels"] = 0
if (version["major"] == 1 and version["minor"] >= 1) or (version["major"] > 1):
(header["num_temp_sensor_channels"],) = struct.unpack("<h", fid.read(2))
# If data file is from GUI v1.3 or later, load eval board mode.
header["eval_board_mode"] = 0
if ((version["major"] == 1) and (version["minor"] >= 3)) or (version["major"] > 1):
(header["eval_board_mode"],) = struct.unpack("<h", fid.read(2))
# Place frequency-related information in data structure. (Note: much of this structure is set above)
freq["amplifier_sample_rate"] = header["sample_rate"]
freq["aux_input_sample_rate"] = header["sample_rate"] / 4
freq["supply_voltage_sample_rate"] = header["sample_rate"] / 60
freq["board_adc_sample_rate"] = header["sample_rate"]
freq["board_dig_in_sample_rate"] = header["sample_rate"]
header["frequency_parameters"] = freq
# Create structure arrays for each type of data channel.
header["spike_triggers"] = []
header["amplifier_channels"] = []
header["aux_input_channels"] = []
header["supply_voltage_channels"] = []
header["board_adc_channels"] = []
header["board_dig_in_channels"] = []
header["board_dig_out_channels"] = []
# Read signal summary from data file header.
(number_of_signal_groups,) = struct.unpack("<h", fid.read(2))
for signal_group in range(0, number_of_signal_groups):
signal_group_name = read_qstring(fid)
signal_group_prefix = read_qstring(fid)
(
signal_group_enabled,
signal_group_num_channels,
signal_group_num_amp_channels,
) = struct.unpack("<hhh", fid.read(6))
if (signal_group_num_channels > 0) and (signal_group_enabled > 0):
for signal_channel in range(0, signal_group_num_channels):
new_channel = {
"port_name": signal_group_name,
"port_prefix": signal_group_prefix,
"port_number": signal_group,
}
new_channel["native_channel_name"] = read_qstring(fid)
new_channel["custom_channel_name"] = read_qstring(fid)
(
new_channel["native_order"],
new_channel["custom_order"],
signal_type,
channel_enabled,
new_channel["chip_channel"],
new_channel["board_stream"],
) = struct.unpack("<hhhhhh", fid.read(12))
new_trigger_channel = {}
(
new_trigger_channel["voltage_trigger_mode"],
new_trigger_channel["voltage_threshold"],
new_trigger_channel["digital_trigger_channel"],
new_trigger_channel["digital_edge_polarity"],
) = struct.unpack("<hhhh", fid.read(8))
(
new_channel["electrode_impedance_magnitude"],
new_channel["electrode_impedance_phase"],
) = struct.unpack("<ff", fid.read(8))
if channel_enabled:
if signal_type == 0:
header["amplifier_channels"].append(new_channel)
header["spike_triggers"].append(new_trigger_channel)
elif signal_type == 1:
header["aux_input_channels"].append(new_channel)
elif signal_type == 2:
header["supply_voltage_channels"].append(new_channel)
elif signal_type == 3:
header["board_adc_channels"].append(new_channel)
elif signal_type == 4:
header["board_dig_in_channels"].append(new_channel)
elif signal_type == 5:
header["board_dig_out_channels"].append(new_channel)
else:
raise Exception("Unknown channel type.")
# Summarize contents of data file.
header["num_amplifier_channels"] = len(header["amplifier_channels"])
header["num_aux_input_channels"] = len(header["aux_input_channels"])
header["num_supply_voltage_channels"] = len(header["supply_voltage_channels"])
header["num_board_adc_channels"] = len(header["board_adc_channels"])
header["num_board_dig_in_channels"] = len(header["board_dig_in_channels"])
header["num_board_dig_out_channels"] = len(header["board_dig_out_channels"])
return header
if __name__ == "__main__":
h = read_header(open(sys.argv[1], "rb"))
print(h)