<commit_before>"""
Reading from neuroscope format files.
Ref: http://neuroscope.sourceforge.net/

It is an old format from Buzsaki's lab

Some old open datasets from spike sorting
are still using this format.

This only the signals.
This should be done (but maybe never will):
  * SpikeTrain file   '.clu'  '.res'
  * Event  '.ext.evt'  or '.evt.ext'

Author: <NAME>

"""
from pathlib import Path

from .baserawio import (BaseRawIO, _signal_channel_dtype, _signal_stream_dtype,
                _spike_channel_dtype, _event_channel_dtype)

import numpy as np
from xml.etree import ElementTree


class NeuroScopeRawIO(BaseRawIO):
    extensions = ['xml', 'dat']
    rawmode = 'one-file'

    def __init__(self, filename=''):
        BaseRawIO.__init__(self)
        self.filename = filename

    def _source_name(self):
        return Path(self.filename).stem

    def _parse_header(self):
        file_path = Path(self.filename)

        supported_data_extensions = ['.dat', '.lfp', '.eeg']
        suffix = file_path.suffix
        if suffix == '.xml':
            # Keeps the old behavior for an xml input
            self.data_extension = ".dat"
        elif suffix == '':
            # Empty suffix to keep testing behavior with non-existing file passing
            self.data_extension = ".dat"
        elif suffix in supported_data_extensions:
            self.data_extension = suffix
        else:
            error_string = (
                f"Format {suffix} not supported"
                f"filename format should be {supported_data_extensions} or xml"
            )
            raise KeyError(error_string)
        
        xml_file_path = file_path.with_suffix(".xml")
        tree = ElementTree.parse(xml_file_path)
        root = tree.getroot()
        acq = root.find('acquisitionSystem')
        nbits = int(acq.find('nBits').text)
        nb_channel = int(acq.find('nChannels').text)
        self._sampling_rate = float(acq.find('samplingRate').text)
        voltage_range = float(acq.find('voltageRange').text)
        # offset = int(acq.find('offset').text)
        amplification = float(acq.find('amplification').text)

        # find groups for channels
        channel_group = {}
        for grp_index, xml_chx in enumerate(
                root.find('anatomicalDescription').find('channelGroups').findall('group')):
            for xml_rc in xml_chx:
                channel_group[int(xml_rc.text)] = grp_index

        if nbits == 16:
            sig_dtype = 'int16'
            gain = voltage_range / (2 ** 16) / amplification / 1000.
            # ~ elif nbits==32:<commit_msg>add support for eeg and lfp formats with neuroscope - PEP correction #2<commit_after>"""
Reading from neuroscope format files.
Ref: http://neuroscope.sourceforge.net/

It is an old format from Buzsaki's lab

Some old open datasets from spike sorting
are still using this format.

This only the signals.
This should be done (but maybe never will):
  * SpikeTrain file   '.clu'  '.res'
  * Event  '.ext.evt'  or '.evt.ext'

Author: <NAME>

"""
from pathlib import Path

from .baserawio import (BaseRawIO, _signal_channel_dtype, _signal_stream_dtype,
                _spike_channel_dtype, _event_channel_dtype)

import numpy as np
from xml.etree import ElementTree


class NeuroScopeRawIO(BaseRawIO):
    extensions = ['xml', 'dat']
    rawmode = 'one-file'

    def __init__(self, filename=''):
        BaseRawIO.__init__(self)
        self.filename = filename

    def _source_name(self):
        return Path(self.filename).stem

    def _parse_header(self):
        file_path = Path(self.filename)

        supported_data_extensions = ['.dat', '.lfp', '.eeg']
        suffix = file_path.suffix
        if suffix == '.xml':
            # Keeps the old behavior for an xml input
            self.data_extension = ".dat"
        elif suffix == '':
            # Empty suffix to keep testing behavior with non-existing file passing
            self.data_extension = ".dat"
        elif suffix in supported_data_extensions:
            self.data_extension = suffix
        else:
            error_string = (
                f"Format {suffix} not supported"
                f"filename format should be {supported_data_extensions} or xml"
            )
            raise KeyError(error_string)

        xml_file_path = file_path.with_suffix(".xml")
        tree = ElementTree.parse(xml_file_path)
        root = tree.getroot()
        acq = root.find('acquisitionSystem')
        nbits = int(acq.find('nBits').text)
        nb_channel = int(acq.find('nChannels').text)
        self._sampling_rate = float(acq.find('samplingRate').text)
        voltage_range = float(acq.find('voltageRange').text)
        # offset = int(acq.find('offset').text)
        amplification = float(acq.find('amplification').text)

        # find groups for channels
        channel_group = {}
        for grp_index, xml_chx in enumerate(
                root.find('anatomicalDescription').find('channelGroups').findall('group')):
            for xml_rc in xml_chx:
                channel_group[int(xml_rc.text)] = grp_index

        if nbits == 16:
            sig_dtype = 'int16'
            gain = voltage_range / (2 ** 16) / amplification / 1000.
            # ~ elif nbits==32:
{'fraction_non_alphanumeric': 0.1050628092881614, 'fraction_numerical': 0.005138941758660068, 'mean_word_length': 2.416775032509753, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 24}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5974536', 'n_tokens_mistral': 1597, 'n_tokens_neox': 1525, 'n_words': 400}