diff --git a/CHANGELOG.md b/CHANGELOG.md index 6952f7e71..4e0f198d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Changed the spikeinterface.tool functions (e.g. `add_recording`, `add_sorting`) to have `_to_nwbfile` as suffix [PR #1015](https://github.com/catalystneuro/neuroconv/pull/1015) * Deprecated use of `compression` and `compression_options` in `VideoInterface` [PR #1005](https://github.com/catalystneuro/neuroconv/pull/1005) * `get_schema_from_method_signature` has been deprecated; please use `get_json_schema_from_method_signature` instead. [PR #1016](https://github.com/catalystneuro/neuroconv/pull/1016) +* `neuroconv.utils.FilePathType` and `neuroconv.utils.FolderPathType` have been deprecated; please use `pydantic.FilePath` and `pydantic.DirectoryPath` instead. [PR #1017](https://github.com/catalystneuro/neuroconv/pull/1017) ### Features * Added MedPCInterface for operant behavioral output files. [PR #883](https://github.com/catalystneuro/neuroconv/pull/883) @@ -30,6 +31,7 @@ * Add tqdm with warning to DeepLabCut interface [PR #1006](https://github.com/catalystneuro/neuroconv/pull/1006) * `BaseRecordingInterface` now calls default metadata when metadata is not passing mimicking `run_conversion` behavior. [PR #1012](https://github.com/catalystneuro/neuroconv/pull/1012) * Added `get_json_schema_from_method_signature` which constructs Pydantic models automatically from the signature of any function with typical annotation types used throughout NeuroConv. [PR #1016](https://github.com/catalystneuro/neuroconv/pull/1016) +* Replaced all interface annotations with Pydantic types. [PR #1017](https://github.com/catalystneuro/neuroconv/pull/1017) diff --git a/src/neuroconv/basedatainterface.py b/src/neuroconv/basedatainterface.py index 9de06e827..0c9b9d813 100644 --- a/src/neuroconv/basedatainterface.py +++ b/src/neuroconv/basedatainterface.py @@ -6,6 +6,7 @@ from typing import Literal, Optional, Tuple, Union from jsonschema.validators import validate +from pydantic import FilePath from pynwb import NWBFile from .tools.nwb_helpers import ( @@ -42,10 +43,6 @@ def __init__(self, verbose: bool = False, **source_data): self.verbose = verbose self.source_data = source_data - def get_conversion_options_schema(self) -> dict: - """Infer the JSON schema for the conversion options from the method signature (annotation typing).""" - return get_json_schema_from_method_signature(self.add_to_nwbfile, exclude=["nwbfile", "metadata"]) - def get_metadata_schema(self) -> dict: """Retrieve JSON schema for metadata.""" metadata_schema = load_dict_from_file(Path(__file__).parent / "schemas" / "base_metadata_schema.json") @@ -79,6 +76,10 @@ def validate_metadata(self, metadata: dict, append_mode: bool = False) -> None: validate(instance=decoded_metadata, schema=metdata_schema) + def get_conversion_options_schema(self) -> dict: + """Infer the JSON schema for the conversion options from the method signature (annotation typing).""" + return get_json_schema_from_method_signature(self.add_to_nwbfile, exclude=["nwbfile", "metadata"]) + def create_nwbfile(self, metadata: Optional[dict] = None, **conversion_options) -> NWBFile: """ Create and return an in-memory pynwb.NWBFile object with this interface's data added to it. @@ -121,7 +122,7 @@ def add_to_nwbfile(self, nwbfile: NWBFile, **conversion_options) -> None: def run_conversion( self, - nwbfile_path: str, + nwbfile_path: FilePath, nwbfile: Optional[NWBFile] = None, metadata: Optional[dict] = None, overwrite: bool = False, diff --git a/src/neuroconv/datainterfaces/behavior/audio/audiointerface.py b/src/neuroconv/datainterfaces/behavior/audio/audiointerface.py index 6054a65b9..532ad5b42 100644 --- a/src/neuroconv/datainterfaces/behavior/audio/audiointerface.py +++ b/src/neuroconv/datainterfaces/behavior/audio/audiointerface.py @@ -4,6 +4,7 @@ import numpy as np import scipy +from pydantic import FilePath from pynwb import NWBFile from ....basetemporalalignmentinterface import BaseTemporalAlignmentInterface @@ -27,7 +28,7 @@ class AudioInterface(BaseTemporalAlignmentInterface): associated_suffixes = (".wav",) info = "Interface for writing audio recordings to an NWB file." - def __init__(self, file_paths: list, verbose: bool = False): + def __init__(self, file_paths: List[FilePath], verbose: bool = False): """ Data interface for writing acoustic recordings to an NWB file. diff --git a/src/neuroconv/datainterfaces/behavior/deeplabcut/_dlc_utils.py b/src/neuroconv/datainterfaces/behavior/deeplabcut/_dlc_utils.py index ddea0751d..39245c307 100644 --- a/src/neuroconv/datainterfaces/behavior/deeplabcut/_dlc_utils.py +++ b/src/neuroconv/datainterfaces/behavior/deeplabcut/_dlc_utils.py @@ -7,11 +7,10 @@ import numpy as np import pandas as pd import yaml +from pydantic import FilePath from pynwb import NWBFile from ruamel.yaml import YAML -from ....utils import FilePathType - def _read_config(config_file_path): """ @@ -303,9 +302,9 @@ def _write_pes_to_nwbfile( def add_subject_to_nwbfile( nwbfile: NWBFile, - h5file: FilePathType, + h5file: FilePath, individual_name: str, - config_file: FilePathType, + config_file: FilePath, timestamps: Optional[Union[List, np.ndarray]] = None, pose_estimation_container_kwargs: Optional[dict] = None, ) -> NWBFile: diff --git a/src/neuroconv/datainterfaces/behavior/deeplabcut/deeplabcutdatainterface.py b/src/neuroconv/datainterfaces/behavior/deeplabcut/deeplabcutdatainterface.py index a0bfa3fb4..f35f3854c 100644 --- a/src/neuroconv/datainterfaces/behavior/deeplabcut/deeplabcutdatainterface.py +++ b/src/neuroconv/datainterfaces/behavior/deeplabcut/deeplabcutdatainterface.py @@ -2,10 +2,10 @@ from typing import List, Optional, Union import numpy as np +from pydantic import FilePath from pynwb.file import NWBFile from ....basetemporalalignmentinterface import BaseTemporalAlignmentInterface -from ....utils import FilePathType class DeepLabCutInterface(BaseTemporalAlignmentInterface): @@ -27,8 +27,8 @@ def get_source_schema(cls) -> dict: def __init__( self, - file_path: FilePathType, - config_file_path: FilePathType, + file_path: FilePath, + config_file_path: FilePath, subject_name: str = "ind1", verbose: bool = True, ): @@ -37,9 +37,9 @@ def __init__( Parameters ---------- - file_path : FilePathType + file_path : FilePath path to the h5 file output by dlc. - config_file_path : FilePathType + config_file_path : FilePath path to .yml config file subject_name : str, default: "ind1" the name of the subject for which the :py:class:`~pynwb.file.NWBFile` is to be created. diff --git a/src/neuroconv/datainterfaces/behavior/fictrac/fictracdatainterface.py b/src/neuroconv/datainterfaces/behavior/fictrac/fictracdatainterface.py index da52b10b7..13136b691 100644 --- a/src/neuroconv/datainterfaces/behavior/fictrac/fictracdatainterface.py +++ b/src/neuroconv/datainterfaces/behavior/fictrac/fictracdatainterface.py @@ -6,12 +6,13 @@ from typing import Optional, Union import numpy as np +from pydantic import FilePath from pynwb.behavior import Position, SpatialSeries from pynwb.file import NWBFile from ....basetemporalalignmentinterface import BaseTemporalAlignmentInterface from ....tools import get_module -from ....utils import FilePathType, calculate_regular_series_rate +from ....utils import calculate_regular_series_rate class FicTracDataInterface(BaseTemporalAlignmentInterface): @@ -155,9 +156,9 @@ def get_source_schema(cls) -> dict: def __init__( self, - file_path: FilePathType, + file_path: FilePath, radius: Optional[float] = None, - configuration_file_path: Optional[FilePathType] = None, + configuration_file_path: Optional[FilePath] = None, verbose: bool = True, ): """ @@ -165,12 +166,12 @@ def __init__( Parameters ---------- - file_path : a string or a path + file_path : FilePath Path to the .dat file (the output of fictrac) radius : float, optional The radius of the ball in meters. If provided the radius is stored as a conversion factor and the units are set to meters. If not provided the units are set to radians. - configuration_file_path : a string or a path, optional + configuration_file_path : FilePath, optional Path to the .txt file with the configuration metadata. Usually called config.txt verbose : bool, default: True controls verbosity. ``True`` by default. @@ -358,8 +359,8 @@ def set_aligned_starting_time(self, aligned_starting_time): def extract_session_start_time( - file_path: FilePathType, - configuration_file_path: Optional[FilePathType] = None, + file_path: FilePath, + configuration_file_path: Optional[FilePath] = None, ) -> Union[datetime, None]: """ Extract the session start time from a FicTrac data file or its configuration file. @@ -378,9 +379,9 @@ def extract_session_start_time( Parameters ---------- - file_path : FilePathType + file_path : FilePath Path to the FicTrac data file. - configuration_file_path : Optional[FilePathType] + configuration_file_path : FilePath, optional Path to the FicTrac configuration file. If omitted, the function defaults to searching for "fictrac_config.txt" in the same directory as the data file. @@ -413,13 +414,13 @@ def extract_session_start_time( return None -def parse_fictrac_config(file_path: FilePathType) -> dict: +def parse_fictrac_config(file_path: FilePath) -> dict: """ Parse a FicTrac configuration file and return a dictionary of its parameters. Parameters ---------- - file_path : str, Path + file_path : FilePath Path to the configuration file in txt format. Returns diff --git a/src/neuroconv/datainterfaces/behavior/lightningpose/lightningposeconverter.py b/src/neuroconv/datainterfaces/behavior/lightningpose/lightningposeconverter.py index 3907134a6..20c080a6e 100644 --- a/src/neuroconv/datainterfaces/behavior/lightningpose/lightningposeconverter.py +++ b/src/neuroconv/datainterfaces/behavior/lightningpose/lightningposeconverter.py @@ -1,6 +1,7 @@ from copy import deepcopy from typing import List, Optional +from pydantic import FilePath from pynwb import NWBFile from neuroconv import NWBConverter @@ -8,7 +9,6 @@ from neuroconv.tools.nwb_helpers import make_or_load_nwbfile from neuroconv.utils import ( DeepDict, - FilePathType, dict_deep_update, get_schema_from_method_signature, ) @@ -28,9 +28,9 @@ def get_source_schema(cls): def __init__( self, - file_path: FilePathType, - original_video_file_path: FilePathType, - labeled_video_file_path: Optional[FilePathType] = None, + file_path: FilePath, + original_video_file_path: FilePath, + labeled_video_file_path: Optional[FilePath] = None, image_series_original_video_name: Optional[str] = None, image_series_labeled_video_name: Optional[str] = None, verbose: bool = True, @@ -41,11 +41,11 @@ def __init__( Parameters ---------- - file_path : a string or a path + file_path : FilePath Path to the .csv file that contains the predictions from Lightning Pose. - original_video_file_path : a string or a path + original_video_file_path : FilePath Path to the original video file (.mp4). - labeled_video_file_path : a string or a path, optional + labeled_video_file_path : FilePath, optional Path to the labeled video file (.mp4). image_series_original_video_name: string, optional The name of the ImageSeries to add for the original video. @@ -160,7 +160,7 @@ def add_to_nwbfile( def run_conversion( self, - nwbfile_path: Optional[str] = None, + nwbfile_path: Optional[FilePath] = None, nwbfile: Optional[NWBFile] = None, metadata: Optional[dict] = None, overwrite: bool = False, diff --git a/src/neuroconv/datainterfaces/behavior/lightningpose/lightningposedatainterface.py b/src/neuroconv/datainterfaces/behavior/lightningpose/lightningposedatainterface.py index 28c93db9c..b9761b2c6 100644 --- a/src/neuroconv/datainterfaces/behavior/lightningpose/lightningposedatainterface.py +++ b/src/neuroconv/datainterfaces/behavior/lightningpose/lightningposedatainterface.py @@ -5,13 +5,13 @@ from typing import Optional, Tuple import numpy as np +from pydantic import FilePath from pynwb import NWBFile from ....basetemporalalignmentinterface import BaseTemporalAlignmentInterface from ....tools import get_module from ....utils import ( DeepDict, - FilePathType, calculate_regular_series_rate, get_base_schema, ) @@ -60,9 +60,9 @@ def get_metadata_schema(self) -> dict: def __init__( self, - file_path: FilePathType, - original_video_file_path: FilePathType, - labeled_video_file_path: Optional[FilePathType] = None, + file_path: FilePath, + original_video_file_path: FilePath, + labeled_video_file_path: Optional[FilePath] = None, verbose: bool = True, ): """ @@ -70,9 +70,9 @@ def __init__( Parameters ---------- - file_path : a string or a path + file_path : FilePath Path to the .csv file that contains the predictions from Lightning Pose. - original_video_file_path : a string or a path + original_video_file_path : FilePath Path to the original video file (.mp4). labeled_video_file_path : a string or a path, optional Path to the labeled video file (.mp4). diff --git a/src/neuroconv/datainterfaces/behavior/medpc/medpc_helpers.py b/src/neuroconv/datainterfaces/behavior/medpc/medpc_helpers.py index 3610c4a49..8e8b7289b 100644 --- a/src/neuroconv/datainterfaces/behavior/medpc/medpc_helpers.py +++ b/src/neuroconv/datainterfaces/behavior/medpc/medpc_helpers.py @@ -1,9 +1,8 @@ import numpy as np +from pydantic import FilePath -from neuroconv.utils import FilePathType - -def get_medpc_variables(file_path: FilePathType, variable_names: list) -> dict: +def get_medpc_variables(file_path: FilePath, variable_names: list) -> dict: """ Get the values of the given single-line variables from a MedPC file for all sessions in that file. @@ -85,7 +84,7 @@ def _get_session_lines(lines: list, session_conditions: dict, start_variable: st def read_medpc_file( - file_path: FilePathType, + file_path: FilePath, medpc_name_to_info_dict: dict, session_conditions: dict, start_variable: str, diff --git a/src/neuroconv/datainterfaces/behavior/medpc/medpcdatainterface.py b/src/neuroconv/datainterfaces/behavior/medpc/medpcdatainterface.py index 267f006f5..0c109f559 100644 --- a/src/neuroconv/datainterfaces/behavior/medpc/medpcdatainterface.py +++ b/src/neuroconv/datainterfaces/behavior/medpc/medpcdatainterface.py @@ -1,12 +1,13 @@ from typing import Optional import numpy as np +from pydantic import FilePath from pynwb.behavior import BehavioralEpochs, IntervalSeries from pynwb.file import NWBFile from neuroconv.basetemporalalignmentinterface import BaseTemporalAlignmentInterface from neuroconv.tools import get_package, nwb_helpers -from neuroconv.utils import DeepDict, FilePathType +from neuroconv.utils import DeepDict from .medpc_helpers import read_medpc_file @@ -42,7 +43,7 @@ class MedPCInterface(BaseTemporalAlignmentInterface): def __init__( self, - file_path: FilePathType, + file_path: FilePath, session_conditions: dict, start_variable: str, metadata_medpc_name_to_info_dict: dict, @@ -54,7 +55,7 @@ def __init__( Parameters ---------- - file_path : FilePathType + file_path : FilePath Path to the MedPC file. session_conditions : dict The conditions that define the session. The keys are the names of the single-line variables (ex. 'Start Date') diff --git a/src/neuroconv/datainterfaces/behavior/miniscope/miniscopedatainterface.py b/src/neuroconv/datainterfaces/behavior/miniscope/miniscopedatainterface.py index e55fec432..6a46e84fe 100644 --- a/src/neuroconv/datainterfaces/behavior/miniscope/miniscopedatainterface.py +++ b/src/neuroconv/datainterfaces/behavior/miniscope/miniscopedatainterface.py @@ -1,10 +1,11 @@ from pathlib import Path +from pydantic import DirectoryPath from pynwb import NWBFile from .... import BaseDataInterface from ....tools import get_package -from ....utils import DeepDict, FolderPathType +from ....utils import DeepDict class MiniscopeBehaviorInterface(BaseDataInterface): @@ -23,13 +24,13 @@ def get_source_schema(cls) -> dict: ] = "The main Miniscope folder. The movie files are expected to be in sub folders within the main folder." return source_schema - def __init__(self, folder_path: FolderPathType): + def __init__(self, folder_path: DirectoryPath): """ Initialize reading recordings from the Miniscope behavioral camera. Parameters ---------- - folder_path : FolderPathType + folder_path : DirectoryPath The path that points to the main Miniscope folder. The movie files are expected to be in sub folders within the main folder. """ diff --git a/src/neuroconv/datainterfaces/behavior/neuralynx/neuralynx_nvt_interface.py b/src/neuroconv/datainterfaces/behavior/neuralynx/neuralynx_nvt_interface.py index 414b2d0d5..51e04821d 100644 --- a/src/neuroconv/datainterfaces/behavior/neuralynx/neuralynx_nvt_interface.py +++ b/src/neuroconv/datainterfaces/behavior/neuralynx/neuralynx_nvt_interface.py @@ -2,12 +2,13 @@ from typing import Optional import numpy as np +from pydantic import FilePath from pynwb import NWBFile from pynwb.behavior import CompassDirection, Position, SpatialSeries from .nvt_utils import read_data, read_header from ....basetemporalalignmentinterface import BaseTemporalAlignmentInterface -from ....utils import DeepDict, FilePathType, NWBMetaDataEncoder, get_base_schema +from ....utils import DeepDict, NWBMetaDataEncoder, get_base_schema from ....utils.path import infer_path @@ -19,13 +20,13 @@ class NeuralynxNvtInterface(BaseTemporalAlignmentInterface): associated_suffixes = (".nvt",) info = "Interface for writing Neuralynx position tracking .nvt files to NWB." - def __init__(self, file_path: FilePathType, verbose: bool = True): + def __init__(self, file_path: FilePath, verbose: bool = True): """ Interface for writing Neuralynx .nvt files to nwb. Parameters ---------- - file_path : FilePathType + file_path : FilePath Path to the .nvt file verbose : bool, default: True controls verbosity. diff --git a/src/neuroconv/datainterfaces/behavior/neuralynx/nvt_utils.py b/src/neuroconv/datainterfaces/behavior/neuralynx/nvt_utils.py index 278433b5c..99a22e577 100644 --- a/src/neuroconv/datainterfaces/behavior/neuralynx/nvt_utils.py +++ b/src/neuroconv/datainterfaces/behavior/neuralynx/nvt_utils.py @@ -8,9 +8,7 @@ from typing import Dict, List, Union import numpy as np - -# Constants for header size and record format -from neuroconv.utils import FilePathType +from pydantic import FilePath HEADER_SIZE = 16 * 1024 @@ -120,7 +118,7 @@ def read_data(filename: str) -> Dict[str, np.ndarray]: return {name: records[name].squeeze() for name, *_ in RECORD_FORMAT} -def truncate_file(source_filename: FilePathType, dest_filename: str, n_records: int = 10) -> None: # pragma: no cover +def truncate_file(source_filename: FilePath, dest_filename: str, n_records: int = 10) -> None: # pragma: no cover """ Creates a new .nvt file with the same header and truncated data. Useful for creating test files. diff --git a/src/neuroconv/datainterfaces/behavior/sleap/sleap_utils.py b/src/neuroconv/datainterfaces/behavior/sleap/sleap_utils.py index 16d998053..b0dae3a3a 100644 --- a/src/neuroconv/datainterfaces/behavior/sleap/sleap_utils.py +++ b/src/neuroconv/datainterfaces/behavior/sleap/sleap_utils.py @@ -1,8 +1,9 @@ +from pydantic import FilePath + from ....tools import get_package -from ....utils import FilePathType -def extract_timestamps(video_file_path: FilePathType) -> list: +def extract_timestamps(video_file_path: FilePath) -> list: """Extract the timestamps using pyav Parameters diff --git a/src/neuroconv/datainterfaces/behavior/sleap/sleapdatainterface.py b/src/neuroconv/datainterfaces/behavior/sleap/sleapdatainterface.py index a689d970e..a74b90a67 100644 --- a/src/neuroconv/datainterfaces/behavior/sleap/sleapdatainterface.py +++ b/src/neuroconv/datainterfaces/behavior/sleap/sleapdatainterface.py @@ -2,12 +2,12 @@ from typing import Optional import numpy as np +from pydantic import FilePath from pynwb.file import NWBFile from .sleap_utils import extract_timestamps from ....basetemporalalignmentinterface import BaseTemporalAlignmentInterface from ....tools import get_package -from ....utils import FilePathType class SLEAPInterface(BaseTemporalAlignmentInterface): @@ -29,8 +29,8 @@ def get_source_schema(cls) -> dict: def __init__( self, - file_path: FilePathType, - video_file_path: Optional[FilePathType] = None, + file_path: FilePath, + video_file_path: Optional[FilePath] = None, verbose: bool = True, frames_per_second: Optional[float] = None, ): @@ -39,7 +39,7 @@ def __init__( Parameters ---------- - file_path : FilePathType + file_path : FilePath Path to the .slp file (the output of sleap) verbose : bool, default: True controls verbosity. ``True`` by default. diff --git a/src/neuroconv/datainterfaces/behavior/video/video_utils.py b/src/neuroconv/datainterfaces/behavior/video/video_utils.py index 5000c468b..78c66472a 100644 --- a/src/neuroconv/datainterfaces/behavior/video/video_utils.py +++ b/src/neuroconv/datainterfaces/behavior/video/video_utils.py @@ -3,15 +3,13 @@ import numpy as np from hdmf.data_utils import GenericDataChunkIterator +from pydantic import FilePath from tqdm import tqdm from ....tools import get_package -from ....utils import FilePathType -def get_video_timestamps( - file_path: FilePathType, max_frames: Optional[int] = None, display_progress: bool = True -) -> list: +def get_video_timestamps(file_path: FilePath, max_frames: Optional[int] = None, display_progress: bool = True) -> list: """Extract the timestamps of the video located in file_path Parameters @@ -36,7 +34,7 @@ def get_video_timestamps( class VideoCaptureContext: """Retrieving video metadata and frames using a context manager.""" - def __init__(self, file_path: FilePathType): + def __init__(self, file_path: FilePath): cv2 = get_package(package_name="cv2", installation_instructions="pip install opencv-python-headless") self.vc = cv2.VideoCapture(filename=file_path) @@ -178,7 +176,7 @@ class VideoDataChunkIterator(GenericDataChunkIterator): def __init__( self, - video_file: FilePathType, + video_file: FilePath, buffer_gb: float = None, chunk_shape: tuple = None, stub_test: bool = False, diff --git a/src/neuroconv/datainterfaces/behavior/video/videodatainterface.py b/src/neuroconv/datainterfaces/behavior/video/videodatainterface.py index 56880b820..ca651e597 100644 --- a/src/neuroconv/datainterfaces/behavior/video/videodatainterface.py +++ b/src/neuroconv/datainterfaces/behavior/video/videodatainterface.py @@ -6,6 +6,7 @@ import numpy as np import psutil from hdmf.data_utils import DataChunkIterator +from pydantic import FilePath from pynwb import NWBFile from pynwb.image import ImageSeries from tqdm import tqdm @@ -29,7 +30,7 @@ class VideoInterface(BaseDataInterface): def __init__( self, - file_paths: list, + file_paths: List[FilePath], verbose: bool = False, *, metadata_key_name: str = "Videos", @@ -39,7 +40,7 @@ def __init__( Parameters ---------- - file_paths : list of FilePathTypes + file_paths : list of FilePaths Many video storage formats segment a sequence of videos over the course of the experiment. Pass the file paths for this videos as a list in sorted, consecutive order. metadata_key_name : str, optional diff --git a/src/neuroconv/datainterfaces/ecephys/axona/axona_utils.py b/src/neuroconv/datainterfaces/ecephys/axona/axona_utils.py index ae095c19d..f7db5924d 100644 --- a/src/neuroconv/datainterfaces/ecephys/axona/axona_utils.py +++ b/src/neuroconv/datainterfaces/ecephys/axona/axona_utils.py @@ -4,12 +4,11 @@ import dateutil import numpy as np +from pydantic import FilePath from pynwb.behavior import Position, SpatialSeries -from ....utils import FilePathType - -def get_eeg_sampling_frequency(file_path: FilePathType) -> float: +def get_eeg_sampling_frequency(file_path: FilePath) -> float: """ Read sampling frequency from .eegX or .egfX file header. @@ -30,7 +29,7 @@ def get_eeg_sampling_frequency(file_path: FilePathType) -> float: # Helper functions for AxonaLFPDataInterface -def read_eeg_file_lfp_data(file_path: FilePathType) -> np.memmap: +def read_eeg_file_lfp_data(file_path: FilePath) -> np.memmap: """ Read LFP data from Axona `.eegX` or `.egfX` file. @@ -64,7 +63,7 @@ def read_eeg_file_lfp_data(file_path: FilePathType) -> np.memmap: return eeg_data -def get_all_file_paths(file_path: FilePathType) -> list: +def get_all_file_paths(file_path: FilePath) -> list: """ Read LFP file_paths of `.eeg` or `.egf` files in file_path's directory. E.g. if file_path='/my/directory/my_file.eeg', all .eeg channels will be @@ -89,7 +88,7 @@ def get_all_file_paths(file_path: FilePathType) -> list: return path_list -def read_all_eeg_file_lfp_data(file_path: FilePathType) -> np.ndarray: +def read_all_eeg_file_lfp_data(file_path: FilePath) -> np.ndarray: """ Read LFP data from all Axona `.eeg` or `.egf` files in file_path's directory. E.g. if file_path='/my/directory/my_file.eeg', all .eeg channels will be conactenated @@ -122,7 +121,7 @@ def read_all_eeg_file_lfp_data(file_path: FilePathType) -> np.ndarray: # Helper functions for AxonaPositionDataInterface -def parse_generic_header(file_path: FilePathType, params: Union[list, set]) -> dict: +def parse_generic_header(file_path: FilePath, params: Union[list, set]) -> dict: """ Given a binary file with phrases and line breaks, enters the first word of a phrase as dictionary key and the following @@ -159,7 +158,7 @@ def parse_generic_header(file_path: FilePathType, params: Union[list, set]) -> d return header -def read_axona_iso_datetime(set_file: FilePathType) -> str: +def read_axona_iso_datetime(set_file: FilePath) -> str: """ Creates datetime object (y, m, d, h, m, s) from .set file header and converts it to ISO 8601 format @@ -173,7 +172,7 @@ def read_axona_iso_datetime(set_file: FilePathType) -> str: return dateutil.parser.parse(date_string + " " + time_string).isoformat() -def get_header_bstring(file: FilePathType) -> bytes: +def get_header_bstring(file: FilePath) -> bytes: """ Scan file for the occurrence of 'data_start' and return the header as byte string @@ -198,7 +197,7 @@ def get_header_bstring(file: FilePathType) -> bytes: return header -def read_bin_file_position_data(bin_file_path: FilePathType) -> np.ndarray: +def read_bin_file_position_data(bin_file_path: FilePath) -> np.ndarray: """ Read position data from Axona `.bin` file (if present). @@ -289,7 +288,7 @@ def read_bin_file_position_data(bin_file_path: FilePathType) -> np.ndarray: return pos_data -def read_pos_file_position_data(pos_file_path: FilePathType) -> np.ndarray: +def read_pos_file_position_data(pos_file_path: FilePath) -> np.ndarray: """ Read position data from Axona `.pos` file. @@ -359,7 +358,7 @@ def read_pos_file_position_data(pos_file_path: FilePathType) -> np.ndarray: return pos_data -def get_position_object(file_path: FilePathType) -> Position: +def get_position_object(file_path: FilePath) -> Position: """ Read position data from .bin or .pos file and convert to pynwb.behavior.SpatialSeries objects. If possible it should always diff --git a/src/neuroconv/datainterfaces/ecephys/axona/axonadatainterface.py b/src/neuroconv/datainterfaces/ecephys/axona/axonadatainterface.py index bd3fe06fa..69612c85c 100644 --- a/src/neuroconv/datainterfaces/ecephys/axona/axonadatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/axona/axonadatainterface.py @@ -1,5 +1,6 @@ """Collection of Axona interfaces.""" +from pydantic import FilePath from pynwb import NWBFile from .axona_utils import ( @@ -11,7 +12,7 @@ from ..baserecordingextractorinterface import BaseRecordingExtractorInterface from ....basedatainterface import BaseDataInterface from ....tools.nwb_helpers import get_module -from ....utils import FilePathType, get_schema_from_method_signature +from ....utils import get_schema_from_method_signature class AxonaRecordingInterface(BaseRecordingExtractorInterface): @@ -29,12 +30,12 @@ def get_source_schema(cls) -> dict: source_schema["properties"]["file_path"]["description"] = "Path to .bin file." return source_schema - def __init__(self, file_path: FilePathType, verbose: bool = True, es_key: str = "ElectricalSeries"): + def __init__(self, file_path: FilePath, verbose: bool = True, es_key: str = "ElectricalSeries"): """ Parameters ---------- - file_path: FilePathType + file_path: FilePath Path to .bin file. verbose: bool, optional, default: True es_key: str, default: "ElectricalSeries" @@ -125,7 +126,7 @@ def get_source_schema(cls) -> dict: type="object", ) - def __init__(self, file_path: FilePathType, noise_std: float = 3.5): + def __init__(self, file_path: FilePath, noise_std: float = 3.5): super().__init__(filename=file_path, noise_std=noise_std) self.source_data = dict(file_path=file_path, noise_std=noise_std) @@ -147,7 +148,7 @@ def get_source_schema(cls) -> dict: additionalProperties=False, ) - def __init__(self, file_path: FilePathType): + def __init__(self, file_path: FilePath): data = read_all_eeg_file_lfp_data(file_path).T sampling_frequency = get_eeg_sampling_frequency(file_path) super().__init__(traces_list=[data], sampling_frequency=sampling_frequency) diff --git a/src/neuroconv/datainterfaces/ecephys/biocam/biocamdatainterface.py b/src/neuroconv/datainterfaces/ecephys/biocam/biocamdatainterface.py index 8df5a1fc9..f12f3a93d 100644 --- a/src/neuroconv/datainterfaces/ecephys/biocam/biocamdatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/biocam/biocamdatainterface.py @@ -1,5 +1,6 @@ +from pydantic import FilePath + from ..baserecordingextractorinterface import BaseRecordingExtractorInterface -from ....utils.types import FilePathType class BiocamRecordingInterface(BaseRecordingExtractorInterface): @@ -19,7 +20,7 @@ def get_source_schema(cls) -> dict: schema["properties"]["file_path"]["description"] = "Path to the .bwr file." return schema - def __init__(self, file_path: FilePathType, verbose: bool = True, es_key: str = "ElectricalSeries"): + def __init__(self, file_path: FilePath, verbose: bool = True, es_key: str = "ElectricalSeries"): """ Load and prepare data for Biocam. diff --git a/src/neuroconv/datainterfaces/ecephys/blackrock/blackrockdatainterface.py b/src/neuroconv/datainterfaces/ecephys/blackrock/blackrockdatainterface.py index 460ada6ce..19e34fdcd 100644 --- a/src/neuroconv/datainterfaces/ecephys/blackrock/blackrockdatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/blackrock/blackrockdatainterface.py @@ -1,10 +1,12 @@ from pathlib import Path from typing import Optional +from pydantic import FilePath + from .header_tools import parse_nev_basic_header, parse_nsx_basic_header from ..baserecordingextractorinterface import BaseRecordingExtractorInterface from ..basesortingextractorinterface import BaseSortingExtractorInterface -from ....utils import FilePathType, get_schema_from_method_signature +from ....utils import get_schema_from_method_signature class BlackrockRecordingInterface(BaseRecordingExtractorInterface): @@ -25,8 +27,8 @@ def get_source_schema(cls): def __init__( self, - file_path: FilePathType, - nsx_override: Optional[FilePathType] = None, + file_path: FilePath, + nsx_override: Optional[FilePath] = None, verbose: bool = True, es_key: str = "ElectricalSeries", ): @@ -81,7 +83,7 @@ def get_source_schema(cls) -> dict: metadata_schema["properties"]["file_path"].update(description="Path to Blackrock .nev file.") return metadata_schema - def __init__(self, file_path: FilePathType, sampling_frequency: float = None, verbose: bool = True): + def __init__(self, file_path: FilePath, sampling_frequency: float = None, verbose: bool = True): """ Parameters ---------- diff --git a/src/neuroconv/datainterfaces/ecephys/cellexplorer/cellexplorerdatainterface.py b/src/neuroconv/datainterfaces/ecephys/cellexplorer/cellexplorerdatainterface.py index e9e7a703f..731ce981b 100644 --- a/src/neuroconv/datainterfaces/ecephys/cellexplorer/cellexplorerdatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/cellexplorer/cellexplorerdatainterface.py @@ -3,15 +3,15 @@ import numpy as np import scipy +from pydantic import DirectoryPath, FilePath from pynwb import NWBFile from ..baserecordingextractorinterface import BaseRecordingExtractorInterface from ..basesortingextractorinterface import BaseSortingExtractorInterface from ....tools import get_package -from ....utils import FilePathType, FolderPathType -def add_channel_metadata_to_recoder(recording_extractor, folder_path: FolderPathType): +def add_channel_metadata_to_recoder(recording_extractor, folder_path: DirectoryPath): """ Main function to add channel metadata to a recording extractor from a CellExplorer session. The metadata is added as channel properties to the recording extractor. @@ -73,7 +73,7 @@ def add_channel_metadata_to_recoder(recording_extractor, folder_path: FolderPath def add_channel_metadata_to_recorder_from_session_file( recording_extractor, - folder_path: FolderPathType, + folder_path: DirectoryPath, ): """ Extracts channel metadata from the CellExplorer's `session.mat` file and adds @@ -177,7 +177,7 @@ def add_channel_metadata_to_recorder_from_session_file( def add_channel_metadata_to_recorder_from_channel_map_file( recording_extractor, - folder_path: FolderPathType, + folder_path: DirectoryPath, ): """ Extracts channel metadata from the `chanMap.mat` file used by Kilosort and adds @@ -294,7 +294,7 @@ def get_source_schema(cls) -> dict: source_schema["properties"]["folder_path"]["description"] = "Folder containing the .session.mat file" return source_schema - def __init__(self, folder_path: FolderPathType, verbose: bool = True, es_key: str = "ElectricalSeries"): + def __init__(self, folder_path: DirectoryPath, verbose: bool = True, es_key: str = "ElectricalSeries"): """ Parameters @@ -374,7 +374,7 @@ class CellExplorerLFPInterface(CellExplorerRecordingInterface): sampling_frequency_key = "srLfp" binary_file_extension = "lfp" - def __init__(self, folder_path: FolderPathType, verbose: bool = True, es_key: str = "ElectricalSeriesLFP"): + def __init__(self, folder_path: DirectoryPath, verbose: bool = True, es_key: str = "ElectricalSeriesLFP"): super().__init__(folder_path, verbose, es_key) def add_to_nwbfile( @@ -411,7 +411,7 @@ class CellExplorerSortingInterface(BaseSortingExtractorInterface): associated_suffixes = (".mat", ".sessionInfo", ".spikes", ".cellinfo") info = "Interface for CellExplorer sorting data." - def __init__(self, file_path: FilePathType, verbose: bool = True): + def __init__(self, file_path: FilePath, verbose: bool = True): """ Initialize read of Cell Explorer file. diff --git a/src/neuroconv/datainterfaces/ecephys/edf/edfdatainterface.py b/src/neuroconv/datainterfaces/ecephys/edf/edfdatainterface.py index 13659b450..119e9f8d2 100644 --- a/src/neuroconv/datainterfaces/ecephys/edf/edfdatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/edf/edfdatainterface.py @@ -1,6 +1,7 @@ +from pydantic import FilePath + from ..baserecordingextractorinterface import BaseRecordingExtractorInterface from ....tools import get_package -from ....utils.types import FilePathType class EDFRecordingInterface(BaseRecordingExtractorInterface): @@ -22,7 +23,7 @@ def get_source_schema(cls) -> dict: source_schema["properties"]["file_path"]["description"] = "Path to the .edf file." return source_schema - def __init__(self, file_path: FilePathType, verbose: bool = True, es_key: str = "ElectricalSeries"): + def __init__(self, file_path: FilePath, verbose: bool = True, es_key: str = "ElectricalSeries"): """ Load and prepare data for EDF. Currently, only continuous EDF+ files (EDF+C) and original EDF files (EDF) are supported diff --git a/src/neuroconv/datainterfaces/ecephys/intan/intandatainterface.py b/src/neuroconv/datainterfaces/ecephys/intan/intandatainterface.py index ce3504055..d28214598 100644 --- a/src/neuroconv/datainterfaces/ecephys/intan/intandatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/intan/intandatainterface.py @@ -2,11 +2,12 @@ from typing import Optional from packaging.version import Version +from pydantic import FilePath from pynwb.ecephys import ElectricalSeries from ..baserecordingextractorinterface import BaseRecordingExtractorInterface from ....tools import get_package_version -from ....utils import FilePathType, get_schema_from_hdmf_class +from ....utils import get_schema_from_hdmf_class class IntanRecordingInterface(BaseRecordingExtractorInterface): @@ -29,7 +30,7 @@ def get_source_schema(cls) -> dict: def __init__( self, - file_path: FilePathType, + file_path: FilePath, stream_id: Optional[str] = None, verbose: bool = True, es_key: str = "ElectricalSeries", diff --git a/src/neuroconv/datainterfaces/ecephys/kilosort/kilosortdatainterface.py b/src/neuroconv/datainterfaces/ecephys/kilosort/kilosortdatainterface.py index 37f812142..fc6765823 100644 --- a/src/neuroconv/datainterfaces/ecephys/kilosort/kilosortdatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/kilosort/kilosortdatainterface.py @@ -1,5 +1,6 @@ +from pydantic import DirectoryPath + from ..basesortingextractorinterface import BaseSortingExtractorInterface -from ....utils import FolderPathType class KiloSortSortingInterface(BaseSortingExtractorInterface): @@ -19,7 +20,7 @@ def get_source_schema(cls) -> dict: def __init__( self, - folder_path: FolderPathType, + folder_path: DirectoryPath, keep_good_only: bool = False, verbose: bool = True, ): diff --git a/src/neuroconv/datainterfaces/ecephys/maxwell/maxonedatainterface.py b/src/neuroconv/datainterfaces/ecephys/maxwell/maxonedatainterface.py index 73f951270..11902f81b 100644 --- a/src/neuroconv/datainterfaces/ecephys/maxwell/maxonedatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/maxwell/maxonedatainterface.py @@ -3,8 +3,9 @@ from platform import system from typing import Optional +from pydantic import DirectoryPath, FilePath + from ..baserecordingextractorinterface import BaseRecordingExtractorInterface -from ....utils.types import FilePathType, FolderPathType class MaxOneRecordingInterface(BaseRecordingExtractorInterface): # pragma: no cover @@ -22,7 +23,7 @@ class MaxOneRecordingInterface(BaseRecordingExtractorInterface): # pragma: no c @staticmethod def auto_install_maxwell_hdf5_compression_plugin( - hdf5_plugin_path: Optional[FolderPathType] = None, download_plugin: bool = True + hdf5_plugin_path: Optional[DirectoryPath] = None, download_plugin: bool = True ) -> None: """ If you do not yet have the Maxwell compression plugin installed, this function will automatically install it. @@ -43,8 +44,8 @@ def auto_install_maxwell_hdf5_compression_plugin( def __init__( self, - file_path: FilePathType, - hdf5_plugin_path: Optional[FolderPathType] = None, + file_path: FilePath, + hdf5_plugin_path: Optional[DirectoryPath] = None, download_plugin: bool = True, verbose: bool = True, es_key: str = "ElectricalSeries", diff --git a/src/neuroconv/datainterfaces/ecephys/mcsraw/mcsrawdatainterface.py b/src/neuroconv/datainterfaces/ecephys/mcsraw/mcsrawdatainterface.py index 230b1d044..ff8e82139 100644 --- a/src/neuroconv/datainterfaces/ecephys/mcsraw/mcsrawdatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/mcsraw/mcsrawdatainterface.py @@ -1,5 +1,6 @@ +from pydantic import FilePath + from ..baserecordingextractorinterface import BaseRecordingExtractorInterface -from ....utils.types import FilePathType class MCSRawRecordingInterface(BaseRecordingExtractorInterface): @@ -19,7 +20,7 @@ def get_source_schema(cls) -> dict: source_schema["properties"]["file_path"]["description"] = "Path to the .raw file." return source_schema - def __init__(self, file_path: FilePathType, verbose: bool = True, es_key: str = "ElectricalSeries"): + def __init__(self, file_path: FilePath, verbose: bool = True, es_key: str = "ElectricalSeries"): """ Load and prepare data for MCSRaw. diff --git a/src/neuroconv/datainterfaces/ecephys/mearec/mearecdatainterface.py b/src/neuroconv/datainterfaces/ecephys/mearec/mearecdatainterface.py index f69c312fd..9d3797e0f 100644 --- a/src/neuroconv/datainterfaces/ecephys/mearec/mearecdatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/mearec/mearecdatainterface.py @@ -1,8 +1,9 @@ import json +from pydantic import FilePath + from ..baserecordingextractorinterface import BaseRecordingExtractorInterface from ....utils.json_schema import NWBMetaDataEncoder -from ....utils.types import FilePathType class MEArecRecordingInterface(BaseRecordingExtractorInterface): @@ -22,7 +23,7 @@ def get_source_schema(cls) -> dict: source_schema["properties"]["file_path"]["description"] = "Path to the MEArec .h5 file." return source_schema - def __init__(self, file_path: FilePathType, verbose: bool = True, es_key: str = "ElectricalSeries"): + def __init__(self, file_path: FilePath, verbose: bool = True, es_key: str = "ElectricalSeries"): """ Load and prepare data for MEArec. diff --git a/src/neuroconv/datainterfaces/ecephys/neuroscope/neuroscopedatainterface.py b/src/neuroconv/datainterfaces/ecephys/neuroscope/neuroscopedatainterface.py index cfb09e009..d3f9fdfb4 100644 --- a/src/neuroconv/datainterfaces/ecephys/neuroscope/neuroscopedatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/neuroscope/neuroscopedatainterface.py @@ -2,6 +2,7 @@ from typing import Optional import numpy as np +from pydantic import DirectoryPath, FilePath from .neuroscope_utils import ( get_channel_groups, @@ -13,7 +14,6 @@ from ..baserecordingextractorinterface import BaseRecordingExtractorInterface from ..basesortingextractorinterface import BaseSortingExtractorInterface from ....tools import get_package -from ....utils import FilePathType, FolderPathType def filter_non_neural_channels(recording_extractor, xml_file_path: str): @@ -125,9 +125,9 @@ def get_ecephys_metadata(xml_file_path: str) -> dict: def __init__( self, - file_path: FilePathType, + file_path: FilePath, gain: Optional[float] = None, - xml_file_path: Optional[FilePathType] = None, + xml_file_path: Optional[FilePath] = None, verbose: bool = True, es_key: str = "ElectricalSeries", ): @@ -202,9 +202,9 @@ def get_source_schema(self) -> dict: def __init__( self, - file_path: FilePathType, + file_path: FilePath, gain: Optional[float] = None, - xml_file_path: Optional[FilePathType] = None, + xml_file_path: Optional[FilePath] = None, ): """ Load and prepare lfp data and corresponding metadata from the Neuroscope format (.eeg or .lfp files). @@ -267,10 +267,10 @@ def get_source_schema(self) -> dict: def __init__( self, - folder_path: FolderPathType, + folder_path: DirectoryPath, keep_mua_units: bool = True, exclude_shanks: Optional[list] = None, - xml_file_path: Optional[FilePathType] = None, + xml_file_path: Optional[FilePath] = None, verbose: bool = True, ): """ diff --git a/src/neuroconv/datainterfaces/ecephys/openephys/_openephys_utils.py b/src/neuroconv/datainterfaces/ecephys/openephys/_openephys_utils.py index 2dd972aea..2a8128c6e 100644 --- a/src/neuroconv/datainterfaces/ecephys/openephys/_openephys_utils.py +++ b/src/neuroconv/datainterfaces/ecephys/openephys/_openephys_utils.py @@ -4,8 +4,7 @@ from warnings import warn from lxml import etree - -from ....utils import FolderPathType +from pydantic import DirectoryPath def _get_session_start_time(element: etree.Element) -> Union[datetime, None]: @@ -28,7 +27,7 @@ def _get_session_start_time(element: etree.Element) -> Union[datetime, None]: return session_start_time -def _read_settings_xml(folder_path: FolderPathType) -> etree.Element: +def _read_settings_xml(folder_path: DirectoryPath) -> etree.Element: """ Read the settings.xml file from an OpenEphys binary recording folder. Returns the root element of the XML tree. diff --git a/src/neuroconv/datainterfaces/ecephys/openephys/openephysbinarydatainterface.py b/src/neuroconv/datainterfaces/ecephys/openephys/openephysbinarydatainterface.py index 88a700dd9..ccbd3cbbd 100644 --- a/src/neuroconv/datainterfaces/ecephys/openephys/openephysbinarydatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/openephys/openephysbinarydatainterface.py @@ -1,7 +1,9 @@ from typing import List, Optional +from pydantic import DirectoryPath + from ..baserecordingextractorinterface import BaseRecordingExtractorInterface -from ....utils import FolderPathType, get_schema_from_method_signature +from ....utils import get_schema_from_method_signature class OpenEphysBinaryRecordingInterface(BaseRecordingExtractorInterface): @@ -18,7 +20,7 @@ class OpenEphysBinaryRecordingInterface(BaseRecordingExtractorInterface): ExtractorName = "OpenEphysBinaryRecordingExtractor" @classmethod - def get_stream_names(cls, folder_path: FolderPathType) -> List[str]: + def get_stream_names(cls, folder_path: DirectoryPath) -> List[str]: from spikeinterface.extractors import OpenEphysBinaryRecordingExtractor stream_names, _ = OpenEphysBinaryRecordingExtractor.get_streams(folder_path=folder_path) @@ -37,7 +39,7 @@ def get_source_schema(cls) -> dict: def __init__( self, - folder_path: FolderPathType, + folder_path: DirectoryPath, stream_name: Optional[str] = None, block_index: Optional[int] = None, stub_test: bool = False, diff --git a/src/neuroconv/datainterfaces/ecephys/openephys/openephysdatainterface.py b/src/neuroconv/datainterfaces/ecephys/openephys/openephysdatainterface.py index 13fc4e96e..b47df98b9 100644 --- a/src/neuroconv/datainterfaces/ecephys/openephys/openephysdatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/openephys/openephysdatainterface.py @@ -1,10 +1,11 @@ from pathlib import Path from typing import Optional +from pydantic import DirectoryPath + from .openephysbinarydatainterface import OpenEphysBinaryRecordingInterface from .openephyslegacydatainterface import OpenEphysLegacyRecordingInterface from ..baserecordingextractorinterface import BaseRecordingExtractorInterface -from ....utils import FolderPathType class OpenEphysRecordingInterface(BaseRecordingExtractorInterface): @@ -26,7 +27,7 @@ def get_source_schema(cls) -> dict: def __new__( cls, - folder_path: FolderPathType, + folder_path: DirectoryPath, stream_name: Optional[str] = None, block_index: Optional[int] = None, verbose: bool = True, diff --git a/src/neuroconv/datainterfaces/ecephys/openephys/openephyslegacydatainterface.py b/src/neuroconv/datainterfaces/ecephys/openephys/openephyslegacydatainterface.py index 5d680f93b..3403705b1 100644 --- a/src/neuroconv/datainterfaces/ecephys/openephys/openephyslegacydatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/openephys/openephyslegacydatainterface.py @@ -2,8 +2,9 @@ from typing import List, Optional from warnings import warn +from pydantic import DirectoryPath + from ..baserecordingextractorinterface import BaseRecordingExtractorInterface -from ....utils import FolderPathType class OpenEphysLegacyRecordingInterface(BaseRecordingExtractorInterface): @@ -18,7 +19,7 @@ class OpenEphysLegacyRecordingInterface(BaseRecordingExtractorInterface): info = "Interface for converting legacy OpenEphys recording data." @classmethod - def get_stream_names(cls, folder_path: FolderPathType) -> List[str]: + def get_stream_names(cls, folder_path: DirectoryPath) -> List[str]: from spikeinterface.extractors import OpenEphysLegacyRecordingExtractor stream_names, _ = OpenEphysLegacyRecordingExtractor.get_streams(folder_path=folder_path) @@ -36,7 +37,7 @@ def get_source_schema(cls): def __init__( self, - folder_path: FolderPathType, + folder_path: DirectoryPath, stream_name: Optional[str] = None, block_index: Optional[int] = None, verbose: bool = True, diff --git a/src/neuroconv/datainterfaces/ecephys/openephys/openephyssortingdatainterface.py b/src/neuroconv/datainterfaces/ecephys/openephys/openephyssortingdatainterface.py index 8ccbf2ab1..20f292c9a 100644 --- a/src/neuroconv/datainterfaces/ecephys/openephys/openephyssortingdatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/openephys/openephyssortingdatainterface.py @@ -1,5 +1,7 @@ +from pydantic import DirectoryPath + from ..basesortingextractorinterface import BaseSortingExtractorInterface -from ....utils import FolderPathType, get_schema_from_method_signature +from ....utils import get_schema_from_method_signature class OpenEphysSortingInterface(BaseSortingExtractorInterface): @@ -21,7 +23,7 @@ def get_source_schema(cls) -> dict: metadata_schema["additionalProperties"] = False return metadata_schema - def __init__(self, folder_path: FolderPathType, experiment_id: int = 0, recording_id: int = 0): + def __init__(self, folder_path: DirectoryPath, experiment_id: int = 0, recording_id: int = 0): from spikeextractors import OpenEphysSortingExtractor self.Extractor = OpenEphysSortingExtractor diff --git a/src/neuroconv/datainterfaces/ecephys/phy/phydatainterface.py b/src/neuroconv/datainterfaces/ecephys/phy/phydatainterface.py index cac24faa2..e5d250a6e 100644 --- a/src/neuroconv/datainterfaces/ecephys/phy/phydatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/phy/phydatainterface.py @@ -1,7 +1,8 @@ from typing import Optional +from pydantic import DirectoryPath + from ..basesortingextractorinterface import BaseSortingExtractorInterface -from ....utils import FolderPathType class PhySortingInterface(BaseSortingExtractorInterface): @@ -25,7 +26,7 @@ def get_source_schema(cls) -> dict: def __init__( self, - folder_path: FolderPathType, + folder_path: DirectoryPath, exclude_cluster_groups: Optional[list] = None, verbose: bool = True, ): diff --git a/src/neuroconv/datainterfaces/ecephys/plexon/plexondatainterface.py b/src/neuroconv/datainterfaces/ecephys/plexon/plexondatainterface.py index cf10d5f0b..8b2e53338 100644 --- a/src/neuroconv/datainterfaces/ecephys/plexon/plexondatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/plexon/plexondatainterface.py @@ -1,9 +1,10 @@ from pathlib import Path +from pydantic import FilePath + from ..baserecordingextractorinterface import BaseRecordingExtractorInterface from ..basesortingextractorinterface import BaseSortingExtractorInterface from ....utils import DeepDict -from ....utils.types import FilePathType class PlexonRecordingInterface(BaseRecordingExtractorInterface): @@ -23,7 +24,7 @@ def get_source_schema(cls) -> dict: source_schema["properties"]["file_path"]["description"] = "Path to the .plx file." return source_schema - def __init__(self, file_path: FilePathType, verbose: bool = True, es_key: str = "ElectricalSeries"): + def __init__(self, file_path: FilePath, verbose: bool = True, es_key: str = "ElectricalSeries"): """ Load and prepare data for Plexon. @@ -67,7 +68,7 @@ def get_source_schema(cls) -> dict: source_schema["properties"]["file_path"]["description"] = "Path to the .pl2 file." return source_schema - def __init__(self, file_path: FilePathType, verbose: bool = True, es_key: str = "ElectricalSeries"): + def __init__(self, file_path: FilePath, verbose: bool = True, es_key: str = "ElectricalSeries"): """ Load and prepare data for Plexon. @@ -118,7 +119,7 @@ def get_source_schema(cls) -> dict: source_schema["properties"]["file_path"]["description"] = "Path to the plexon spiking data (.plx file)." return source_schema - def __init__(self, file_path: FilePathType, verbose: bool = True): + def __init__(self, file_path: FilePath, verbose: bool = True): """ Load and prepare data for Plexon. diff --git a/src/neuroconv/datainterfaces/ecephys/spike2/spike2datainterface.py b/src/neuroconv/datainterfaces/ecephys/spike2/spike2datainterface.py index dc55b9eb4..5895dfe3c 100644 --- a/src/neuroconv/datainterfaces/ecephys/spike2/spike2datainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/spike2/spike2datainterface.py @@ -1,8 +1,10 @@ from pathlib import Path +from pydantic import FilePath + from ..baserecordingextractorinterface import BaseRecordingExtractorInterface from ....tools import get_package -from ....utils import FilePathType, get_schema_from_method_signature +from ....utils import get_schema_from_method_signature def _test_sonpy_installation() -> None: @@ -33,12 +35,12 @@ def get_source_schema(cls) -> dict: return source_schema @classmethod - def get_all_channels_info(cls, file_path: FilePathType): + def get_all_channels_info(cls, file_path: FilePath): """Retrieve and inspect necessary channel information prior to initialization.""" _test_sonpy_installation() return cls.get_extractor().get_all_channels_info(file_path=file_path) - def __init__(self, file_path: FilePathType, verbose: bool = True, es_key: str = "ElectricalSeries"): + def __init__(self, file_path: FilePath, verbose: bool = True, es_key: str = "ElectricalSeries"): """ Initialize reading of Spike2 file. diff --git a/src/neuroconv/datainterfaces/ecephys/spikegadgets/spikegadgetsdatainterface.py b/src/neuroconv/datainterfaces/ecephys/spikegadgets/spikegadgetsdatainterface.py index 578487a5b..a5ad98d52 100644 --- a/src/neuroconv/datainterfaces/ecephys/spikegadgets/spikegadgetsdatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/spikegadgets/spikegadgetsdatainterface.py @@ -1,7 +1,9 @@ from typing import Optional +from pydantic import FilePath + from ..baserecordingextractorinterface import BaseRecordingExtractorInterface -from ....utils import ArrayType, FilePathType +from ....utils import ArrayType, get_json_schema_from_method_signature class SpikeGadgetsRecordingInterface(BaseRecordingExtractorInterface): @@ -16,13 +18,13 @@ class SpikeGadgetsRecordingInterface(BaseRecordingExtractorInterface): @classmethod def get_source_schema(cls) -> dict: - source_schema = super().get_source_schema() + source_schema = get_json_schema_from_method_signature(cls, exclude=["source_data"]) source_schema["properties"]["file_path"].update(description="Path to SpikeGadgets (.rec) file.") return source_schema def __init__( self, - file_path: FilePathType, + file_path: FilePath, stream_id: str = "trodes", gains: Optional[ArrayType] = None, verbose: bool = True, diff --git a/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglx_utils.py b/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglx_utils.py index e9ba6514e..ba83d296d 100644 --- a/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglx_utils.py +++ b/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglx_utils.py @@ -4,7 +4,7 @@ from datetime import datetime from pathlib import Path -from ....utils import FilePathType +from pydantic import FilePath def add_recording_extractor_properties(recording_extractor) -> None: @@ -55,7 +55,7 @@ def get_session_start_time(recording_metadata: dict) -> datetime: return session_start_time -def fetch_stream_id_for_spikelgx_file(file_path: FilePathType) -> str: +def fetch_stream_id_for_spikelgx_file(file_path: FilePath) -> str: """ Returns the stream_id for a spikelgx file. diff --git a/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglxconverter.py b/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglxconverter.py index eccd430c4..35a4d8881 100644 --- a/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglxconverter.py +++ b/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglxconverter.py @@ -1,10 +1,12 @@ from pathlib import Path from typing import List, Optional +from pydantic import DirectoryPath + from .spikeglxdatainterface import SpikeGLXRecordingInterface from .spikeglxnidqinterface import SpikeGLXNIDQInterface from ....nwbconverter import ConverterPipe -from ....utils import FolderPathType, get_schema_from_method_signature +from ....utils import get_schema_from_method_signature class SpikeGLXConverterPipe(ConverterPipe): @@ -26,14 +28,14 @@ def get_source_schema(cls): return source_schema @classmethod - def get_streams(cls, folder_path: FolderPathType) -> List[str]: + def get_streams(cls, folder_path: DirectoryPath) -> List[str]: from spikeinterface.extractors import SpikeGLXRecordingExtractor return SpikeGLXRecordingExtractor.get_streams(folder_path=folder_path)[0] def __init__( self, - folder_path: FolderPathType, + folder_path: DirectoryPath, streams: Optional[List[str]] = None, verbose: bool = False, ): diff --git a/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglxdatainterface.py b/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglxdatainterface.py index 0cecb39cb..6e8c33586 100644 --- a/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglxdatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglxdatainterface.py @@ -4,6 +4,7 @@ from typing import Optional import numpy as np +from pydantic import FilePath from .spikeglx_utils import ( add_recording_extractor_properties, @@ -12,7 +13,7 @@ get_session_start_time, ) from ..baserecordingextractorinterface import BaseRecordingExtractorInterface -from ....utils import FilePathType, get_schema_from_method_signature +from ....utils import get_schema_from_method_signature class SpikeGLXRecordingInterface(BaseRecordingExtractorInterface): @@ -39,7 +40,7 @@ def get_source_schema(cls) -> dict: def __init__( self, - file_path: FilePathType, + file_path: FilePath, verbose: bool = True, es_key: Optional[str] = None, ): diff --git a/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglxnidqinterface.py b/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglxnidqinterface.py index 61bf6b056..7cff7f11f 100644 --- a/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglxnidqinterface.py +++ b/src/neuroconv/datainterfaces/ecephys/spikeglx/spikeglxnidqinterface.py @@ -2,11 +2,12 @@ from typing import List import numpy as np +from pydantic import FilePath from .spikeglx_utils import get_session_start_time from ..baserecordingextractorinterface import BaseRecordingExtractorInterface from ....tools.signal_processing import get_rising_frames_from_ttl -from ....utils import FilePathType, get_schema_from_method_signature +from ....utils import get_schema_from_method_signature class SpikeGLXNIDQInterface(BaseRecordingExtractorInterface): @@ -27,7 +28,7 @@ def get_source_schema(cls) -> dict: def __init__( self, - file_path: FilePathType, + file_path: FilePath, verbose: bool = True, load_sync_channel: bool = False, es_key: str = "ElectricalSeriesNIDQ", diff --git a/src/neuroconv/datainterfaces/ecephys/tdt/tdtdatainterface.py b/src/neuroconv/datainterfaces/ecephys/tdt/tdtdatainterface.py index 82251c820..420d0f242 100644 --- a/src/neuroconv/datainterfaces/ecephys/tdt/tdtdatainterface.py +++ b/src/neuroconv/datainterfaces/ecephys/tdt/tdtdatainterface.py @@ -1,5 +1,6 @@ +from pydantic import DirectoryPath + from ..baserecordingextractorinterface import BaseRecordingExtractorInterface -from ....utils.types import FolderPathType class TdtRecordingInterface(BaseRecordingExtractorInterface): @@ -11,7 +12,7 @@ class TdtRecordingInterface(BaseRecordingExtractorInterface): def __init__( self, - folder_path: FolderPathType, + folder_path: DirectoryPath, gain: float, stream_id: str = "0", verbose: bool = True, diff --git a/src/neuroconv/datainterfaces/icephys/abf/abfdatainterface.py b/src/neuroconv/datainterfaces/icephys/abf/abfdatainterface.py index 3b9457901..10ec3e8a3 100644 --- a/src/neuroconv/datainterfaces/icephys/abf/abfdatainterface.py +++ b/src/neuroconv/datainterfaces/icephys/abf/abfdatainterface.py @@ -4,6 +4,8 @@ from typing import List from warnings import warn +from pydantic import FilePath + from ..baseicephysinterface import BaseIcephysInterface @@ -49,17 +51,19 @@ def get_source_schema(cls) -> dict: ) return source_schema - def __init__(self, file_paths: list, icephys_metadata: dict = None, icephys_metadata_file_path: str = None): + def __init__( + self, file_paths: List[FilePath], icephys_metadata: dict = None, icephys_metadata_file_path: FilePath = None + ): """ ABF IcephysInterface based on Neo AxonIO. Parameters ---------- - file_paths : list + file_paths : list of FilePaths List of files to be converted to the same NWB file. icephys_metadata : dict, optional Dictionary containing the Icephys-specific metadata. - icephys_metadata_file_path : str, optional + icephys_metadata_file_path : FilePath, optional JSON file containing the Icephys-specific metadata. """ super().__init__(file_paths=file_paths) diff --git a/src/neuroconv/datainterfaces/ophys/brukertiff/brukertiffconverter.py b/src/neuroconv/datainterfaces/ophys/brukertiff/brukertiffconverter.py index e6b7abf15..6f5daeb0c 100644 --- a/src/neuroconv/datainterfaces/ophys/brukertiff/brukertiffconverter.py +++ b/src/neuroconv/datainterfaces/ophys/brukertiff/brukertiffconverter.py @@ -1,5 +1,6 @@ from typing import Literal, Optional +from pydantic import DirectoryPath, FilePath from pynwb import NWBFile from ... import ( @@ -8,7 +9,7 @@ ) from ....nwbconverter import NWBConverter from ....tools.nwb_helpers import make_or_load_nwbfile -from ....utils import FolderPathType, get_schema_from_method_signature +from ....utils import get_schema_from_method_signature class BrukerTiffMultiPlaneConverter(NWBConverter): @@ -31,7 +32,7 @@ def get_conversion_options_schema(self): def __init__( self, - folder_path: FolderPathType, + folder_path: DirectoryPath, plane_separation_type: Literal["disjoint", "contiguous"] = None, verbose: bool = False, ): @@ -40,7 +41,7 @@ def __init__( Parameters ---------- - folder_path : PathType + folder_path : DirectoryPath The path to the folder that contains the Bruker TIF image files (.ome.tif) and configuration files (.xml, .env). plane_separation_type: {'contiguous', 'disjoint'} Defines how to write volumetric imaging data. Use 'contiguous' to create the volumetric two photon series, @@ -97,7 +98,7 @@ def add_to_nwbfile( def run_conversion( self, - nwbfile_path: Optional[str] = None, + nwbfile_path: Optional[FilePath] = None, nwbfile: Optional[NWBFile] = None, metadata: Optional[dict] = None, overwrite: bool = False, @@ -137,7 +138,7 @@ def get_conversion_options_schema(self): def __init__( self, - folder_path: FolderPathType, + folder_path: DirectoryPath, verbose: bool = False, ): """ @@ -145,7 +146,7 @@ def __init__( Parameters ---------- - folder_path : PathType + folder_path : DirectoryPath The path to the folder that contains the Bruker TIF image files (.ome.tif) and configuration files (.xml, .env). verbose : bool, default: True Controls verbosity. @@ -189,7 +190,7 @@ def add_to_nwbfile( def run_conversion( self, - nwbfile_path: Optional[str] = None, + nwbfile_path: Optional[FilePath] = None, nwbfile: Optional[NWBFile] = None, metadata: Optional[dict] = None, overwrite: bool = False, diff --git a/src/neuroconv/datainterfaces/ophys/brukertiff/brukertiffdatainterface.py b/src/neuroconv/datainterfaces/ophys/brukertiff/brukertiffdatainterface.py index 2c663d7e6..d92676219 100644 --- a/src/neuroconv/datainterfaces/ophys/brukertiff/brukertiffdatainterface.py +++ b/src/neuroconv/datainterfaces/ophys/brukertiff/brukertiffdatainterface.py @@ -1,9 +1,9 @@ from typing import List, Literal, Optional from dateutil.parser import parse +from pydantic import DirectoryPath from ..baseimagingextractorinterface import BaseImagingExtractorInterface -from ....utils import FolderPathType from ....utils.dict import DeepDict @@ -25,7 +25,7 @@ def get_source_schema(cls) -> dict: @classmethod def get_streams( cls, - folder_path: FolderPathType, + folder_path: DirectoryPath, plane_separation_type: Literal["contiguous", "disjoint"] = None, ) -> dict: from roiextractors import BrukerTiffMultiPlaneImagingExtractor @@ -40,7 +40,7 @@ def get_streams( def __init__( self, - folder_path: FolderPathType, + folder_path: DirectoryPath, stream_name: Optional[str] = None, verbose: bool = True, ): @@ -49,7 +49,7 @@ def __init__( Parameters ---------- - folder_path : FolderPathType + folder_path : DirectoryPath The path to the folder that contains the Bruker TIF image files (.ome.tif) and configuration files (.xml, .env). stream_name : str, optional The name of the recording stream (e.g. 'Ch2'). @@ -190,7 +190,7 @@ def get_source_schema(cls) -> dict: return source_schema @classmethod - def get_streams(cls, folder_path: FolderPathType) -> dict: + def get_streams(cls, folder_path: DirectoryPath) -> dict: from roiextractors import BrukerTiffMultiPlaneImagingExtractor streams = BrukerTiffMultiPlaneImagingExtractor.get_streams(folder_path=folder_path) @@ -198,7 +198,7 @@ def get_streams(cls, folder_path: FolderPathType) -> dict: def __init__( self, - folder_path: FolderPathType, + folder_path: DirectoryPath, stream_name: Optional[str] = None, verbose: bool = True, ): @@ -207,7 +207,7 @@ def __init__( Parameters ---------- - folder_path : FolderPathType + folder_path : DirectoryPath The path to the folder that contains the Bruker TIF image files (.ome.tif) and configuration files (.xml, .env). stream_name : str, optional The name of the recording stream (e.g. 'Ch2'). diff --git a/src/neuroconv/datainterfaces/ophys/caiman/caimandatainterface.py b/src/neuroconv/datainterfaces/ophys/caiman/caimandatainterface.py index 5d86695f4..386c03d3c 100644 --- a/src/neuroconv/datainterfaces/ophys/caiman/caimandatainterface.py +++ b/src/neuroconv/datainterfaces/ophys/caiman/caimandatainterface.py @@ -1,5 +1,6 @@ +from pydantic import FilePath + from ..basesegmentationextractorinterface import BaseSegmentationExtractorInterface -from ....utils import FilePathType class CaimanSegmentationInterface(BaseSegmentationExtractorInterface): @@ -15,12 +16,12 @@ def get_source_schema(cls) -> dict: source_metadata["properties"]["file_path"]["description"] = "Path to .hdf5 file." return source_metadata - def __init__(self, file_path: FilePathType, verbose: bool = True): + def __init__(self, file_path: FilePath, verbose: bool = True): """ Parameters ---------- - file_path : FilePathType + file_path : FilePath Path to .hdf5 file. verbose : bool, default True Whether to print progress diff --git a/src/neuroconv/datainterfaces/ophys/cnmfe/cnmfedatainterface.py b/src/neuroconv/datainterfaces/ophys/cnmfe/cnmfedatainterface.py index 8c5b93c64..4ea60c892 100644 --- a/src/neuroconv/datainterfaces/ophys/cnmfe/cnmfedatainterface.py +++ b/src/neuroconv/datainterfaces/ophys/cnmfe/cnmfedatainterface.py @@ -1,5 +1,6 @@ +from pydantic import FilePath + from ..basesegmentationextractorinterface import BaseSegmentationExtractorInterface -from ....utils import FilePathType class CnmfeSegmentationInterface(BaseSegmentationExtractorInterface): @@ -9,6 +10,6 @@ class CnmfeSegmentationInterface(BaseSegmentationExtractorInterface): associated_suffixes = (".mat",) info = "Interface for constrained non-negative matrix factorization (CNMFE) segmentation." - def __init__(self, file_path: FilePathType, verbose: bool = True): + def __init__(self, file_path: FilePath, verbose: bool = True): super().__init__(file_path=file_path) self.verbose = verbose diff --git a/src/neuroconv/datainterfaces/ophys/extract/extractdatainterface.py b/src/neuroconv/datainterfaces/ophys/extract/extractdatainterface.py index 211667001..39b3d0a79 100644 --- a/src/neuroconv/datainterfaces/ophys/extract/extractdatainterface.py +++ b/src/neuroconv/datainterfaces/ophys/extract/extractdatainterface.py @@ -1,7 +1,8 @@ from typing import Optional +from pydantic import FilePath + from ..basesegmentationextractorinterface import BaseSegmentationExtractorInterface -from ....utils import FilePathType class ExtractSegmentationInterface(BaseSegmentationExtractorInterface): @@ -13,7 +14,7 @@ class ExtractSegmentationInterface(BaseSegmentationExtractorInterface): def __init__( self, - file_path: FilePathType, + file_path: FilePath, sampling_frequency: float, output_struct_name: Optional[str] = None, verbose: bool = True, diff --git a/src/neuroconv/datainterfaces/ophys/hdf5/hdf5datainterface.py b/src/neuroconv/datainterfaces/ophys/hdf5/hdf5datainterface.py index d30ff3161..c980fcf41 100644 --- a/src/neuroconv/datainterfaces/ophys/hdf5/hdf5datainterface.py +++ b/src/neuroconv/datainterfaces/ophys/hdf5/hdf5datainterface.py @@ -1,7 +1,9 @@ from typing import Literal +from pydantic import FilePath + from ..baseimagingextractorinterface import BaseImagingExtractorInterface -from ....utils import ArrayType, FilePathType +from ....utils import ArrayType class Hdf5ImagingInterface(BaseImagingExtractorInterface): @@ -13,7 +15,7 @@ class Hdf5ImagingInterface(BaseImagingExtractorInterface): def __init__( self, - file_path: FilePathType, + file_path: FilePath, mov_field: str = "mov", sampling_frequency: float = None, start_time: float = None, @@ -26,7 +28,7 @@ def __init__( Parameters ---------- - file_path : FilePathType + file_path : FilePath Path to .h5 or .hdf5 file. mov_field : str, default: 'mov' sampling_frequency : float, optional diff --git a/src/neuroconv/datainterfaces/ophys/micromanagertiff/micromanagertiffdatainterface.py b/src/neuroconv/datainterfaces/ophys/micromanagertiff/micromanagertiffdatainterface.py index 57d966da9..4e758e742 100644 --- a/src/neuroconv/datainterfaces/ophys/micromanagertiff/micromanagertiffdatainterface.py +++ b/src/neuroconv/datainterfaces/ophys/micromanagertiff/micromanagertiffdatainterface.py @@ -1,7 +1,7 @@ from dateutil.parser import parse +from pydantic import DirectoryPath from ..baseimagingextractorinterface import BaseImagingExtractorInterface -from ....utils import FolderPathType class MicroManagerTiffImagingInterface(BaseImagingExtractorInterface): @@ -18,7 +18,7 @@ def get_source_schema(cls) -> dict: source_schema["properties"]["folder_path"]["description"] = "The folder containing the OME-TIF image files." return source_schema - def __init__(self, folder_path: FolderPathType, verbose: bool = True): + def __init__(self, folder_path: DirectoryPath, verbose: bool = True): """ Data Interface for MicroManagerTiffImagingExtractor. diff --git a/src/neuroconv/datainterfaces/ophys/miniscope/miniscopeconverter.py b/src/neuroconv/datainterfaces/ophys/miniscope/miniscopeconverter.py index ab7706646..09aba9f0e 100644 --- a/src/neuroconv/datainterfaces/ophys/miniscope/miniscopeconverter.py +++ b/src/neuroconv/datainterfaces/ophys/miniscope/miniscopeconverter.py @@ -1,11 +1,12 @@ from typing import Optional +from pydantic import DirectoryPath from pynwb import NWBFile from ... import MiniscopeBehaviorInterface, MiniscopeImagingInterface from ....nwbconverter import NWBConverter from ....tools.nwb_helpers import make_or_load_nwbfile -from ....utils import FolderPathType, get_schema_from_method_signature +from ....utils import get_schema_from_method_signature class MiniscopeConverter(NWBConverter): @@ -22,7 +23,7 @@ def get_source_schema(cls): source_schema["properties"]["folder_path"]["description"] = "The path to the main Miniscope folder." return source_schema - def __init__(self, folder_path: FolderPathType, verbose: bool = True): + def __init__(self, folder_path: DirectoryPath, verbose: bool = True): """ Initializes the data interfaces for the Miniscope recording and behavioral data stream. diff --git a/src/neuroconv/datainterfaces/ophys/miniscope/miniscopeimagingdatainterface.py b/src/neuroconv/datainterfaces/ophys/miniscope/miniscopeimagingdatainterface.py index 7031fd7f1..e26cc69fb 100644 --- a/src/neuroconv/datainterfaces/ophys/miniscope/miniscopeimagingdatainterface.py +++ b/src/neuroconv/datainterfaces/ophys/miniscope/miniscopeimagingdatainterface.py @@ -3,10 +3,11 @@ from typing import Literal, Optional import numpy as np +from pydantic import DirectoryPath from pynwb import NWBFile from ..baseimagingextractorinterface import BaseImagingExtractorInterface -from ....utils import DeepDict, FolderPathType, dict_deep_update +from ....utils import DeepDict, dict_deep_update class MiniscopeImagingInterface(BaseImagingExtractorInterface): @@ -25,13 +26,13 @@ def get_source_schema(cls) -> dict: return source_schema - def __init__(self, folder_path: FolderPathType): + def __init__(self, folder_path: DirectoryPath): """ Initialize reading the Miniscope imaging data. Parameters ---------- - folder_path : FolderPathType + folder_path : DirectoryPath The main Miniscope folder. The microscope movie files are expected to be in sub folders within the main folder. """ diff --git a/src/neuroconv/datainterfaces/ophys/sbx/sbxdatainterface.py b/src/neuroconv/datainterfaces/ophys/sbx/sbxdatainterface.py index 079ad6fc9..2fa90a2bb 100644 --- a/src/neuroconv/datainterfaces/ophys/sbx/sbxdatainterface.py +++ b/src/neuroconv/datainterfaces/ophys/sbx/sbxdatainterface.py @@ -1,7 +1,8 @@ from typing import Literal +from pydantic import FilePath + from ..baseimagingextractorinterface import BaseImagingExtractorInterface -from ....utils import FilePathType class SbxImagingInterface(BaseImagingExtractorInterface): @@ -13,7 +14,7 @@ class SbxImagingInterface(BaseImagingExtractorInterface): def __init__( self, - file_path: FilePathType, + file_path: FilePath, sampling_frequency: float = None, verbose: bool = True, photon_series_type: Literal["OnePhotonSeries", "TwoPhotonSeries"] = "TwoPhotonSeries", diff --git a/src/neuroconv/datainterfaces/ophys/scanimage/scanimageimaginginterfaces.py b/src/neuroconv/datainterfaces/ophys/scanimage/scanimageimaginginterfaces.py index 9c9fa7371..76a67ef9b 100644 --- a/src/neuroconv/datainterfaces/ophys/scanimage/scanimageimaginginterfaces.py +++ b/src/neuroconv/datainterfaces/ophys/scanimage/scanimageimaginginterfaces.py @@ -4,9 +4,9 @@ from typing import Optional from dateutil.parser import parse as dateparse +from pydantic import DirectoryPath, FilePath from ..baseimagingextractorinterface import BaseImagingExtractorInterface -from ....utils import FilePathType, FolderPathType class ScanImageImagingInterface(BaseImagingExtractorInterface): @@ -34,7 +34,7 @@ def get_source_schema(cls) -> dict: def __new__( cls, - file_path: FilePathType, + file_path: FilePath, channel_name: Optional[str] = None, plane_name: Optional[str] = None, fallback_sampling_frequency: Optional[float] = None, @@ -92,7 +92,7 @@ def get_source_schema(cls) -> dict: def __init__( self, - file_path: FilePathType, + file_path: FilePath, fallback_sampling_frequency: Optional[float] = None, verbose: bool = True, ): @@ -102,7 +102,7 @@ def __init__( Parameters ---------- - file_path: str + file_path: FilePath Path to tiff file. fallback_sampling_frequency: float, optional The sampling frequency can usually be extracted from the scanimage metadata in @@ -170,7 +170,7 @@ def get_source_schema(cls) -> dict: def __new__( cls, - folder_path: FolderPathType, + folder_path: DirectoryPath, file_pattern: str, channel_name: Optional[str] = None, plane_name: Optional[str] = None, @@ -228,7 +228,7 @@ class ScanImageMultiPlaneImagingInterface(BaseImagingExtractorInterface): def __init__( self, - file_path: FilePathType, + file_path: FilePath, channel_name: Optional[str] = None, image_metadata: Optional[dict] = None, parsed_metadata: Optional[dict] = None, @@ -239,7 +239,7 @@ def __init__( Parameters ---------- - file_path : PathType + file_path : FilePath Path to the TIFF file. channel_name : str Name of the channel for this extractor. @@ -329,7 +329,7 @@ class ScanImageMultiPlaneMultiFileImagingInterface(BaseImagingExtractorInterface def __init__( self, - folder_path: FolderPathType, + folder_path: DirectoryPath, file_pattern: str, channel_name: Optional[str] = None, extract_all_metadata: bool = False, @@ -342,7 +342,7 @@ def __init__( Parameters ---------- - folder_path : PathType + folder_path : DirectoryPath Path to the folder containing the TIFF files. file_pattern : str Pattern for the TIFF files to read -- see pathlib.Path.glob for details. @@ -445,7 +445,7 @@ class ScanImageSinglePlaneImagingInterface(BaseImagingExtractorInterface): def __init__( self, - file_path: FilePathType, + file_path: FilePath, channel_name: Optional[str] = None, plane_name: Optional[str] = None, image_metadata: Optional[dict] = None, @@ -457,7 +457,7 @@ def __init__( Parameters ---------- - file_path : PathType + file_path : FilePath Path to the TIFF file. channel_name : str The name of the channel to load, to determine what channels are available use ScanImageTiffSinglePlaneImagingExtractor.get_available_channels(file_path=...). @@ -562,7 +562,7 @@ class ScanImageSinglePlaneMultiFileImagingInterface(BaseImagingExtractorInterfac def __init__( self, - folder_path: FolderPathType, + folder_path: DirectoryPath, file_pattern: str, channel_name: Optional[str] = None, plane_name: Optional[str] = None, @@ -576,7 +576,7 @@ def __init__( Parameters ---------- - folder_path : PathType + folder_path : DirectoryPath Path to the folder containing the TIFF files. file_pattern : str Pattern for the TIFF files to read -- see pathlib.Path.glob for details. diff --git a/src/neuroconv/datainterfaces/ophys/sima/simadatainterface.py b/src/neuroconv/datainterfaces/ophys/sima/simadatainterface.py index f89ef716c..8bf34cc04 100644 --- a/src/neuroconv/datainterfaces/ophys/sima/simadatainterface.py +++ b/src/neuroconv/datainterfaces/ophys/sima/simadatainterface.py @@ -1,5 +1,6 @@ +from pydantic import FilePath + from ..basesegmentationextractorinterface import BaseSegmentationExtractorInterface -from ....utils import FilePathType class SimaSegmentationInterface(BaseSegmentationExtractorInterface): @@ -9,12 +10,12 @@ class SimaSegmentationInterface(BaseSegmentationExtractorInterface): associated_suffixes = (".sima",) info = "Interface for SIMA segmentation." - def __init__(self, file_path: FilePathType, sima_segmentation_label: str = "auto_ROIs"): + def __init__(self, file_path: FilePath, sima_segmentation_label: str = "auto_ROIs"): """ Parameters ---------- - file_path : FilePathType + file_path : FilePath sima_segmentation_label : str, default: "auto_ROIs" """ super().__init__(file_path=file_path, sima_segmentation_label=sima_segmentation_label) diff --git a/src/neuroconv/datainterfaces/ophys/suite2p/suite2pdatainterface.py b/src/neuroconv/datainterfaces/ophys/suite2p/suite2pdatainterface.py index 8fa04bb5c..359dea25f 100644 --- a/src/neuroconv/datainterfaces/ophys/suite2p/suite2pdatainterface.py +++ b/src/neuroconv/datainterfaces/ophys/suite2p/suite2pdatainterface.py @@ -1,10 +1,11 @@ from copy import deepcopy from typing import Optional +from pydantic import DirectoryPath from pynwb import NWBFile from ..basesegmentationextractorinterface import BaseSegmentationExtractorInterface -from ....utils import DeepDict, FolderPathType +from ....utils import DeepDict def _update_metadata_links_for_plane_segmentation_name(metadata: dict, plane_segmentation_name: str) -> DeepDict: @@ -60,20 +61,20 @@ def get_source_schema(cls) -> dict: return schema @classmethod - def get_available_planes(cls, folder_path: FolderPathType) -> dict: + def get_available_planes(cls, folder_path: DirectoryPath) -> dict: from roiextractors import Suite2pSegmentationExtractor return Suite2pSegmentationExtractor.get_available_planes(folder_path=folder_path) @classmethod - def get_available_channels(cls, folder_path: FolderPathType) -> dict: + def get_available_channels(cls, folder_path: DirectoryPath) -> dict: from roiextractors import Suite2pSegmentationExtractor return Suite2pSegmentationExtractor.get_available_channels(folder_path=folder_path) def __init__( self, - folder_path: FolderPathType, + folder_path: DirectoryPath, channel_name: Optional[str] = None, plane_name: Optional[str] = None, plane_segmentation_name: Optional[str] = None, @@ -83,7 +84,7 @@ def __init__( Parameters ---------- - folder_path : FolderPathType + folder_path : DirectoryPath Path to the folder containing Suite2p segmentation data. Should contain 'plane#' sub-folders. channel_name: str, optional The name of the channel to load. diff --git a/src/neuroconv/datainterfaces/ophys/tdt_fp/tdtfiberphotometrydatainterface.py b/src/neuroconv/datainterfaces/ophys/tdt_fp/tdtfiberphotometrydatainterface.py index 7015a7487..72c854634 100644 --- a/src/neuroconv/datainterfaces/ophys/tdt_fp/tdtfiberphotometrydatainterface.py +++ b/src/neuroconv/datainterfaces/ophys/tdt_fp/tdtfiberphotometrydatainterface.py @@ -6,12 +6,13 @@ import numpy as np import pytz +from pydantic import FilePath from pynwb.file import NWBFile from neuroconv.basetemporalalignmentinterface import BaseTemporalAlignmentInterface from neuroconv.tools import get_package from neuroconv.tools.fiber_photometry import add_fiber_photometry_device -from neuroconv.utils import DeepDict, FilePathType +from neuroconv.utils import DeepDict class TDTFiberPhotometryInterface(BaseTemporalAlignmentInterface): @@ -27,12 +28,12 @@ class TDTFiberPhotometryInterface(BaseTemporalAlignmentInterface): info = "Data Interface for converting fiber photometry data from TDT files." associated_suffixes = ("Tbk", "Tdx", "tev", "tin", "tsq") - def __init__(self, folder_path: FilePathType, verbose: bool = True): + def __init__(self, folder_path: FilePath, verbose: bool = True): """Initialize the TDTFiberPhotometryInterface. Parameters ---------- - folder_path : FilePathType + folder_path : FilePath The path to the folder containing the TDT data. verbose : bool, optional Whether to print status messages, default = True. diff --git a/src/neuroconv/datainterfaces/ophys/tiff/tiffdatainterface.py b/src/neuroconv/datainterfaces/ophys/tiff/tiffdatainterface.py index 30417f345..017aa2e98 100644 --- a/src/neuroconv/datainterfaces/ophys/tiff/tiffdatainterface.py +++ b/src/neuroconv/datainterfaces/ophys/tiff/tiffdatainterface.py @@ -1,7 +1,8 @@ from typing import Literal +from pydantic import FilePath + from ..baseimagingextractorinterface import BaseImagingExtractorInterface -from ....utils import FilePathType class TiffImagingInterface(BaseImagingExtractorInterface): @@ -19,7 +20,7 @@ def get_source_schema(cls) -> dict: def __init__( self, - file_path: FilePathType, + file_path: FilePath, sampling_frequency: float, verbose: bool = True, photon_series_type: Literal["OnePhotonSeries", "TwoPhotonSeries"] = "TwoPhotonSeries", diff --git a/src/neuroconv/datainterfaces/text/csv/csvtimeintervalsinterface.py b/src/neuroconv/datainterfaces/text/csv/csvtimeintervalsinterface.py index 4904e1c19..cb1aecb2b 100644 --- a/src/neuroconv/datainterfaces/text/csv/csvtimeintervalsinterface.py +++ b/src/neuroconv/datainterfaces/text/csv/csvtimeintervalsinterface.py @@ -1,7 +1,7 @@ import pandas as pd +from pydantic import FilePath from ..timeintervalsinterface import TimeIntervalsInterface -from ....utils.types import FilePathType class CsvTimeIntervalsInterface(TimeIntervalsInterface): @@ -11,5 +11,5 @@ class CsvTimeIntervalsInterface(TimeIntervalsInterface): associated_suffixes = (".csv",) info = "Interface for writing a time intervals table from a comma separated value (CSV) file." - def _read_file(self, file_path: FilePathType, **read_kwargs): + def _read_file(self, file_path: FilePath, **read_kwargs): return pd.read_csv(file_path, **read_kwargs) diff --git a/src/neuroconv/datainterfaces/text/excel/exceltimeintervalsinterface.py b/src/neuroconv/datainterfaces/text/excel/exceltimeintervalsinterface.py index 96a375d50..cb4ae2330 100644 --- a/src/neuroconv/datainterfaces/text/excel/exceltimeintervalsinterface.py +++ b/src/neuroconv/datainterfaces/text/excel/exceltimeintervalsinterface.py @@ -1,9 +1,9 @@ from typing import Optional import pandas as pd +from pydantic import FilePath from ..timeintervalsinterface import TimeIntervalsInterface -from ....utils.types import FilePathType class ExcelTimeIntervalsInterface(TimeIntervalsInterface): @@ -15,7 +15,7 @@ class ExcelTimeIntervalsInterface(TimeIntervalsInterface): def __init__( self, - file_path: FilePathType, + file_path: FilePath, read_kwargs: Optional[dict] = None, verbose: bool = True, ): @@ -29,5 +29,5 @@ def __init__( """ super().__init__(file_path=file_path, read_kwargs=read_kwargs, verbose=verbose) - def _read_file(self, file_path: FilePathType, **read_kwargs): + def _read_file(self, file_path: FilePath, **read_kwargs): return pd.read_excel(file_path, **read_kwargs) diff --git a/src/neuroconv/datainterfaces/text/timeintervalsinterface.py b/src/neuroconv/datainterfaces/text/timeintervalsinterface.py index dd7f491f8..ad55852c5 100644 --- a/src/neuroconv/datainterfaces/text/timeintervalsinterface.py +++ b/src/neuroconv/datainterfaces/text/timeintervalsinterface.py @@ -3,12 +3,12 @@ from typing import Dict, Optional import numpy as np +from pydantic import FilePath from pynwb import NWBFile from ...basedatainterface import BaseDataInterface from ...tools.text import convert_df_to_time_intervals from ...utils.dict import load_dict_from_file -from ...utils.types import FilePathType class TimeIntervalsInterface(BaseDataInterface): @@ -18,7 +18,7 @@ class TimeIntervalsInterface(BaseDataInterface): def __init__( self, - file_path: FilePathType, + file_path: FilePath, read_kwargs: Optional[dict] = None, verbose: bool = True, ): @@ -152,5 +152,5 @@ def add_to_nwbfile( return nwbfile @abstractmethod - def _read_file(self, file_path: FilePathType, **read_kwargs): + def _read_file(self, file_path: FilePath, **read_kwargs): pass diff --git a/src/neuroconv/nwbconverter.py b/src/neuroconv/nwbconverter.py index 689ac6050..2f5074d6a 100644 --- a/src/neuroconv/nwbconverter.py +++ b/src/neuroconv/nwbconverter.py @@ -7,6 +7,7 @@ from typing import Dict, List, Literal, Optional, Tuple, Union from jsonschema import validate +from pydantic import FilePath from pynwb import NWBFile from .basedatainterface import BaseDataInterface @@ -173,7 +174,7 @@ def add_to_nwbfile(self, nwbfile: NWBFile, metadata, conversion_options: Optiona def run_conversion( self, - nwbfile_path: Optional[str] = None, + nwbfile_path: Optional[FilePath] = None, nwbfile: Optional[NWBFile] = None, metadata: Optional[dict] = None, overwrite: bool = False, diff --git a/src/neuroconv/tools/data_transfers/_dandi.py b/src/neuroconv/tools/data_transfers/_dandi.py index 291cb5e11..f67f43197 100644 --- a/src/neuroconv/tools/data_transfers/_dandi.py +++ b/src/neuroconv/tools/data_transfers/_dandi.py @@ -7,15 +7,14 @@ from typing import List, Optional, Union from warnings import warn +from pydantic import DirectoryPath from pynwb import NWBHDF5IO -from ...utils import FolderPathType - def automatic_dandi_upload( dandiset_id: str, - nwb_folder_path: FolderPathType, - dandiset_folder_path: Optional[FolderPathType] = None, + nwb_folder_path: DirectoryPath, + dandiset_folder_path: Optional[DirectoryPath] = None, version: str = "draft", staging: bool = False, cleanup: bool = False, diff --git a/src/neuroconv/tools/neo/neo.py b/src/neuroconv/tools/neo/neo.py index bcb27a40b..8873359db 100644 --- a/src/neuroconv/tools/neo/neo.py +++ b/src/neuroconv/tools/neo/neo.py @@ -8,9 +8,9 @@ import neo.io.baseio import numpy as np import pynwb +from pydantic import FilePath from ..nwb_helpers import add_device_from_metadata -from ...utils import OptionalFilePathType response_classes = dict( voltage_clamp=pynwb.icephys.VoltageClampSeries, @@ -439,7 +439,7 @@ def add_neo_to_nwb( def write_neo_to_nwb( neo_reader: neo.io.baseio.BaseIO, - save_path: OptionalFilePathType = None, # pragma: no cover + save_path: Optional[FilePath] = None, # pragma: no cover overwrite: bool = False, nwbfile=None, metadata: dict = None, diff --git a/src/neuroconv/tools/roiextractors/roiextractors.py b/src/neuroconv/tools/roiextractors/roiextractors.py index 3b8cac2ac..75c5a0642 100644 --- a/src/neuroconv/tools/roiextractors/roiextractors.py +++ b/src/neuroconv/tools/roiextractors/roiextractors.py @@ -9,6 +9,7 @@ # from hdmf.common import VectorData from hdmf.data_utils import DataChunkIterator +from pydantic import FilePath from pynwb import NWBFile from pynwb.base import Images from pynwb.device import Device @@ -35,7 +36,6 @@ from ..nwb_helpers import get_default_nwbfile_metadata, get_module, make_or_load_nwbfile from ...utils import ( DeepDict, - OptionalFilePathType, calculate_regular_series_rate, dict_deep_update, ) @@ -570,7 +570,7 @@ def add_imaging( def write_imaging( imaging: ImagingExtractor, - nwbfile_path: OptionalFilePathType = None, + nwbfile_path: Optional[FilePath] = None, nwbfile: Optional[NWBFile] = None, metadata: Optional[dict] = None, overwrite: bool = False, @@ -1447,7 +1447,7 @@ def add_segmentation( def write_segmentation( segmentation_extractor: SegmentationExtractor, - nwbfile_path: OptionalFilePathType = None, + nwbfile_path: Optional[FilePath] = None, nwbfile: Optional[NWBFile] = None, metadata: Optional[dict] = None, overwrite: bool = False, diff --git a/src/neuroconv/tools/spikeinterface/spikeinterface.py b/src/neuroconv/tools/spikeinterface/spikeinterface.py index 48a102bc5..c3ad28813 100644 --- a/src/neuroconv/tools/spikeinterface/spikeinterface.py +++ b/src/neuroconv/tools/spikeinterface/spikeinterface.py @@ -7,6 +7,7 @@ import psutil import pynwb from hdmf.data_utils import AbstractDataChunkIterator, DataChunkIterator +from pydantic import FilePath from spikeinterface import BaseRecording, BaseSorting, SortingAnalyzer from .spikeinterfacerecordingdatachunkiterator import ( @@ -15,7 +16,6 @@ from ..nwb_helpers import get_module, make_or_load_nwbfile from ...utils import ( DeepDict, - FilePathType, calculate_regular_series_rate, dict_deep_update, ) @@ -1130,7 +1130,7 @@ def add_recording_to_nwbfile( def write_recording( recording: BaseRecording, - nwbfile_path: Optional[FilePathType] = None, + nwbfile_path: Optional[FilePath] = None, nwbfile: Optional[pynwb.NWBFile] = None, metadata: Optional[dict] = None, overwrite: bool = False, @@ -1175,7 +1175,7 @@ def write_recording( def write_recording_to_nwbfile( recording: BaseRecording, - nwbfile_path: Optional[FilePathType] = None, + nwbfile_path: Optional[FilePath] = None, nwbfile: Optional[pynwb.NWBFile] = None, metadata: Optional[dict] = None, overwrite: bool = False, @@ -1196,7 +1196,7 @@ def write_recording_to_nwbfile( Parameters ---------- recording : spikeinterface.BaseRecording - nwbfile_path : FilePathType, optional + nwbfile_path : FilePath, optional Path for where to write or load (if overwrite=False) the NWBFile. If specified, the context will always write to this location. nwbfile : NWBFile, optional @@ -1730,7 +1730,7 @@ def add_sorting_to_nwbfile( def write_sorting( sorting: BaseSorting, - nwbfile_path: Optional[FilePathType] = None, + nwbfile_path: Optional[FilePath] = None, nwbfile: Optional[pynwb.NWBFile] = None, metadata: Optional[dict] = None, overwrite: bool = False, @@ -1777,7 +1777,7 @@ def write_sorting( def write_sorting_to_nwbfile( sorting: BaseSorting, - nwbfile_path: Optional[FilePathType] = None, + nwbfile_path: Optional[FilePath] = None, nwbfile: Optional[pynwb.NWBFile] = None, metadata: Optional[dict] = None, overwrite: bool = False, @@ -1799,7 +1799,7 @@ def write_sorting_to_nwbfile( Parameters ---------- sorting : spikeinterface.BaseSorting - nwbfile_path : FilePathType, optional + nwbfile_path : FilePath, optional Path for where to write or load (if overwrite=False) the NWBFile. If specified, the context will always write to this location. nwbfile : NWBFile, optional @@ -2011,7 +2011,7 @@ def add_sorting_analyzer_to_nwbfile( def write_sorting_analyzer( sorting_analyzer: SortingAnalyzer, - nwbfile_path: Optional[FilePathType] = None, + nwbfile_path: Optional[FilePath] = None, nwbfile: Optional[pynwb.NWBFile] = None, metadata: Optional[dict] = None, overwrite: bool = False, @@ -2056,7 +2056,7 @@ def write_sorting_analyzer( def write_sorting_analyzer_to_nwbfile( sorting_analyzer: SortingAnalyzer, - nwbfile_path: Optional[FilePathType] = None, + nwbfile_path: Optional[FilePath] = None, nwbfile: Optional[pynwb.NWBFile] = None, metadata: Optional[dict] = None, overwrite: bool = False, @@ -2083,7 +2083,7 @@ def write_sorting_analyzer_to_nwbfile( ---------- sorting_analyzer : spikeinterface.SortingAnalyzer The sorting analyzer object to be written to the NWBFile. - nwbfile_path : FilePathType + nwbfile_path : FilePath Path for where to write or load (if overwrite=False) the NWBFile. If specified, the context will always write to this location. nwbfile : NWBFile, optional @@ -2163,7 +2163,7 @@ def write_sorting_analyzer_to_nwbfile( # TODO: Remove February 2025 def write_waveforms( waveform_extractor, - nwbfile_path: Optional[FilePathType] = None, + nwbfile_path: Optional[FilePath] = None, nwbfile: Optional[pynwb.NWBFile] = None, metadata: Optional[dict] = None, overwrite: bool = False, diff --git a/src/neuroconv/tools/testing/mock_ttl_signals.py b/src/neuroconv/tools/testing/mock_ttl_signals.py index 6b4cd5f22..936d16e7e 100644 --- a/src/neuroconv/tools/testing/mock_ttl_signals.py +++ b/src/neuroconv/tools/testing/mock_ttl_signals.py @@ -4,11 +4,12 @@ import numpy as np from numpy.typing import DTypeLike +from pydantic import DirectoryPath from pynwb import NWBHDF5IO, H5DataIO, TimeSeries from pynwb.testing.mock.file import mock_NWBFile from ..importing import is_package_installed -from ...utils import ArrayType, FolderPathType +from ...utils import ArrayType def _check_parameter_dtype_consistency( @@ -128,7 +129,7 @@ def generate_mock_ttl_signal( return trace -def regenerate_test_cases(folder_path: FolderPathType, regenerate_reference_images: bool = False): # pragma: no cover +def regenerate_test_cases(folder_path: DirectoryPath, regenerate_reference_images: bool = False): # pragma: no cover """ Regenerate the test cases of the file included in the main testing suite, which is frozen between breaking changes. diff --git a/src/neuroconv/tools/yaml_conversion_specification/_yaml_conversion_specification.py b/src/neuroconv/tools/yaml_conversion_specification/_yaml_conversion_specification.py index 2c7e5b25c..10e33cbc8 100644 --- a/src/neuroconv/tools/yaml_conversion_specification/_yaml_conversion_specification.py +++ b/src/neuroconv/tools/yaml_conversion_specification/_yaml_conversion_specification.py @@ -5,9 +5,10 @@ import click from jsonschema import RefResolver, validate +from pydantic import DirectoryPath, FilePath from ...nwbconverter import NWBConverter -from ...utils import FilePathType, FolderPathType, dict_deep_update, load_dict_from_file +from ...utils import dict_deep_update, load_dict_from_file @click.command() @@ -45,9 +46,9 @@ def run_conversion_from_yaml_cli( def run_conversion_from_yaml( - specification_file_path: FilePathType, - data_folder_path: Optional[FolderPathType] = None, - output_folder_path: Optional[FolderPathType] = None, + specification_file_path: FilePath, + data_folder_path: Optional[DirectoryPath] = None, + output_folder_path: Optional[DirectoryPath] = None, overwrite: bool = False, ): """ diff --git a/src/neuroconv/utils/__init__.py b/src/neuroconv/utils/__init__.py index 9e80dbbac..1e2bca630 100644 --- a/src/neuroconv/utils/__init__.py +++ b/src/neuroconv/utils/__init__.py @@ -18,11 +18,6 @@ ) from .types import ( ArrayType, - FilePathType, - FloatType, - FolderPathType, IntType, OptionalArrayType, - OptionalFilePathType, - OptionalFolderPathType, ) diff --git a/src/neuroconv/utils/dict.py b/src/neuroconv/utils/dict.py index 0ab2b814e..0a92520f7 100644 --- a/src/neuroconv/utils/dict.py +++ b/src/neuroconv/utils/dict.py @@ -9,8 +9,7 @@ import numpy as np import yaml - -from .types import FilePathType +from pydantic import FilePath class NoDatesSafeLoader(yaml.SafeLoader): @@ -37,7 +36,7 @@ def remove_implicit_resolver(cls, tag_to_remove): NoDatesSafeLoader.remove_implicit_resolver("tag:yaml.org,2002:timestamp") -def load_dict_from_file(file_path: FilePathType) -> dict: +def load_dict_from_file(file_path: FilePath) -> dict: """Safely load metadata from .yml or .json files.""" file_path = Path(file_path) assert file_path.is_file(), f"{file_path} is not a file." diff --git a/src/neuroconv/utils/types.py b/src/neuroconv/utils/types.py index 67dc24c5b..fe476c8f8 100644 --- a/src/neuroconv/utils/types.py +++ b/src/neuroconv/utils/types.py @@ -1,12 +1,7 @@ -from pathlib import Path -from typing import Optional, TypeVar, Union +from typing import Optional, Union import numpy as np -FilePathType = TypeVar("FilePathType", str, Path) -FolderPathType = TypeVar("FolderPathType", str, Path) -OptionalFilePathType = Optional[FilePathType] -OptionalFolderPathType = Optional[FolderPathType] ArrayType = Union[list, np.ndarray] OptionalArrayType = Optional[ArrayType] FloatType = float diff --git a/tests/test_behavior/test_audio_interface.py b/tests/test_behavior/test_audio_interface.py index 9d61f3171..bdfcf1e52 100644 --- a/tests/test_behavior/test_audio_interface.py +++ b/tests/test_behavior/test_audio_interface.py @@ -10,17 +10,17 @@ from dateutil.tz import gettz from hdmf.testing import TestCase from numpy.testing import assert_array_equal +from pydantic import FilePath from pynwb import NWBHDF5IO from scipy.io.wavfile import read, write from neuroconv import NWBConverter from neuroconv.datainterfaces.behavior.audio.audiointerface import AudioInterface from neuroconv.tools.testing.data_interface_mixins import AudioInterfaceTestMixin -from neuroconv.utils import FilePathType def create_audio_files( - test_dir: FilePathType, + test_dir: FilePath, num_audio_files: int, sampling_rate: int, num_frames: int,