Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simplify the loading of input files in the io module #minor #335

Merged
merged 4 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 24 additions & 97 deletions efel/io.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import annotations
"""IO handler for eFEL"""

"""
Expand All @@ -18,89 +19,22 @@
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
from pathlib import Path
import neo
import numpy as np

import os

# pylint:disable=E0611, F0401
import urllib.parse as up
import urllib.request as ur
def load_ascii_input(
file_path: Path | str, delimiter: str = " "
) -> tuple[np.ndarray, np.ndarray]:
"""Loads electrophysiology data from an ASCII file.

# pylint:enable=E0611,F0401

import mimetypes


def windows_compatible(func):
"""Decorator allowing to use urlparse with windows."""

def inner(fragment_url):
"""Change windows path part to url."""
# if system is windows
if os.name == "nt":
fragment_url.replace("\\", "/")

parsed_url = func(fragment_url)

return parsed_url

return inner


def load_fragment(fragment_url, mime_type=None):
"""Load fragment

Load a fragment (e.g. time series data) from a given URL
Returns: A tuple containing two numpy arrays, one for time and one for voltage.
"""
parsed_url = windows_compatible(up.urlparse)(fragment_url)

scheme = parsed_url.scheme
server_loc = parsed_url.netloc
path = parsed_url.path
fragment_string = parsed_url.fragment

# reform path for windows files
if scheme == "file" and os.name == "nt":
path = ur.url2pathname(r"\\" + server_loc + path)

if mime_type is None:
mimetypes.init()
mime_type, _ = mimetypes.guess_type(path)
if mime_type is None:
raise TypeError(
'load_fragment: impossible to guess MIME type from url, '
'please specify the type manually as argument: %s' % path)

if scheme == 'file' and os.name == 'nt':
file_handle = open(path, 'r')
elif scheme == 'file':
file_handle = open(os.path.join(server_loc, path), 'r')

if 'text/' in mime_type:
import numpy

if fragment_string == '':
cols = None
else:
import re

match = re.match("col=([0-9]+)", fragment_string)
if match is None or len(match.groups()) != 1:
raise TypeError(
"load_fragment: don't understand url fragment %s" %
fragment_string)
else:
cols = int(match.groups()[0]) - 1

# Unfortunately we need this if statement
# Setting usecols to None throws an error in the loadtxt call
if cols is not None:
fragment_content = numpy.loadtxt(file_handle, usecols=[cols])
else:
fragment_content = numpy.loadtxt(file_handle)

return fragment_content
else:
raise TypeError('load_fragment: unknown mime type %s' % mime_type)
file_path = Path(file_path)
data = np.loadtxt(file_path, delimiter=delimiter)
time, voltage = data[:, 0], data[:, 1]
return time, voltage


def extract_stim_times_from_neo_data(blocks, stim_start, stim_end):
Expand Down Expand Up @@ -242,37 +176,30 @@ def load_neo_file(file_name, stim_start=None, stim_end=None, **kwargs):
returned object : [Segments_1, Segments_2, ..., Segments_n]
Segments_1 = [Traces_1, Traces_2, ..., Traces_n]
"""

import neo

reader = neo.io.get_io(file_name)
blocks = reader.read(**kwargs)

stim_start, stim_end = extract_stim_times_from_neo_data(
blocks, stim_start, stim_end)
if stim_start is None or stim_end is None:
raise ValueError(
'No stim_start or stim_end has been found inside epochs or events.'
' You can directly specify their value as argument "stim_start"'
' and "stim_end"')
'No stim_start or stim_end found in epochs or events. '
'Please specify "stim_start" and "stim_end" arguments.')

# this part of the code transforms the data format.
# Convert data for eFEL
efel_blocks = []
for bl in blocks:
efel_segments = []
for seg in bl.segments:
traces = []
count_traces = 0
analogsignals = seg.analogsignals

for sig in analogsignals:
traces.append({})
traces[count_traces]['T'] = sig.times.rescale('ms').magnitude
traces[count_traces]['V'] = sig.rescale('mV').magnitude
traces[count_traces]['stim_start'] = [stim_start]
traces[count_traces]['stim_end'] = [stim_end]
count_traces += 1

for sig in seg.analogsignals:
trace = {
'T': sig.times.rescale('ms').magnitude,
'V': sig.rescale('mV').magnitude,
'stim_start': [stim_start],
'stim_end': [stim_end]
}
traces.append(trace)
efel_segments.append(traces)
efel_blocks.append(efel_segments)

Expand Down
3 changes: 1 addition & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@
name="efel",
version=versioneer.get_version(),
cmdclass=versioneer.get_cmdclass(),
install_requires=['numpy>=1.6'],
extras_require={'neo': ['neo[neomatlabio]>=0.5.1']},
install_requires=['numpy>=1.6', 'neo>=0.5.2'],
packages=['efel', 'efel.pyfeatures', 'efel.units'],
author="BlueBrain Project, EPFL",
maintainer="Werner Van Geit",
Expand Down
Loading
Loading