diff --git a/AFQ/api/participant.py b/AFQ/api/participant.py index b5a6e4458..09c3d05eb 100644 --- a/AFQ/api/participant.py +++ b/AFQ/api/participant.py @@ -15,7 +15,7 @@ from AFQ.tasks.segmentation import get_segmentation_plan from AFQ.tasks.viz import get_viz_plan from AFQ.utils.path import drop_extension -from AFQ.data.s3bids import read_json +from AFQ.data.utils import read_json __all__ = ["ParticipantAFQ"] diff --git a/AFQ/data/s3bids.py b/AFQ/data/s3bids.py index 65a6d2d20..e03428366 100644 --- a/AFQ/data/s3bids.py +++ b/AFQ/data/s3bids.py @@ -11,7 +11,6 @@ from dask.diagnostics import ProgressBar from pathlib import Path -import os import os.path as op import logging @@ -24,10 +23,41 @@ from bids import BIDSLayout from AFQ.data.fetch import to_bids_description +import warnings +import functools + + +# +---------------------+ +# | Deprecation helpers | +# +---------------------+ +def deprecate_function(func): + @functools.wraps(func) + def new_func(*args, **kwargs): + msg = f"The function {func.__name__} is part of the " + msg += "AFQ.data.s3bids module, which will be removed " + msg += "in version 2.0 of pyAFQ." + warnings.warn(msg, DeprecationWarning, stacklevel=2) + return func(*args, **kwargs) + + return new_func + + +def deprecate_class(klass): + class new_klass(klass): + def __init__(self, *args, **kwargs): + msg = f"The class {klass.__name__} is part of the " + msg += "AFQ.data.s3bids module, which will be removed " + msg += "in version 2.0 of pyAFQ." + warnings.warn(msg, DeprecationWarning, stacklevel=2) + + return klass.__init__(*args, **kwargs) + return new_klass + # +----------------------------------------------------+ # | Begin S3BIDSStudy classes and supporting functions | # +----------------------------------------------------+ +@deprecate_function def get_s3_client(anon=True): """Return a boto3 s3 client @@ -193,6 +223,7 @@ def _download_from_s3(fname, bucket, key, overwrite=False, anon=True): fs.get("/".join([bucket, key]), fname) +@deprecate_class class S3BIDSSubject: """A single study subject hosted on AWS S3""" @@ -442,6 +473,7 @@ def split_key(key): progress.close() +@deprecate_class class HBNSubject(S3BIDSSubject): """A subject in the HBN study @@ -525,6 +557,7 @@ def get_deriv_type(s3_key): self._s3_keys = s3_keys +@deprecate_class class S3BIDSStudy: """A BIDS-compliant study hosted on AWS S3""" @@ -953,6 +986,7 @@ def download(self, directory, compute(*results, scheduler='threads') +@deprecate_class class HBNSite(S3BIDSStudy): """An HBN study site @@ -1184,6 +1218,7 @@ def s3fs_nifti_write(img, fname, fs=None): ff.write(data) +@deprecate_function def s3fs_nifti_read(fname, fs=None, anon=False): """ Lazily reads a nifti image from S3. @@ -1222,44 +1257,7 @@ def s3fs_nifti_read(fname, fs=None, anon=False): return img -def write_json(fname, data): - """ - Write data to JSON file. - - Parameters - ---------- - fname : str - Full path to the file to write. - - data : dict - A dict containing the data to write. - - Returns - ------- - None - """ - with open(fname, 'w') as ff: - json.dump(data, ff, default=lambda obj: "Not Serializable") - - -def read_json(fname): - """ - Read data from a JSON file. - - Parameters - ---------- - fname : str - Full path to the data-containing file - - Returns - ------- - dict - """ - with open(fname, 'r') as ff: - out = json.load(ff) - return out - - +@deprecate_function def s3fs_json_read(fname, fs=None, anon=False): """ Reads json directly from S3 @@ -1283,6 +1281,7 @@ def s3fs_json_read(fname, fs=None, anon=False): return data +@deprecate_function def s3fs_json_write(data, fname, fs=None): """ Writes json from a dict directly into S3 diff --git a/AFQ/data/utils.py b/AFQ/data/utils.py index 43913c7a9..116d8bd92 100644 --- a/AFQ/data/utils.py +++ b/AFQ/data/utils.py @@ -1,3 +1,5 @@ +import json + BUNDLE_RECO_2_AFQ = \ { "AF_L": "ARC_L", "AF_R": "ARC_R", @@ -31,3 +33,41 @@ 'RightILF': 'ILF_R', 'LeftILF': 'ILF_L', 'Right SLF': 'SLF_R', 'Left SLF': 'SLF_L', 'RightSLF': 'SLF_R', 'LeftSLF': 'SLF_L'} + + +def write_json(fname, data): + """ + Write data to JSON file. + + Parameters + ---------- + fname : str + Full path to the file to write. + + data : dict + A dict containing the data to write. + + Returns + ------- + None + """ + with open(fname, 'w') as ff: + json.dump(data, ff, default=lambda obj: "Not Serializable") + + +def read_json(fname): + """ + Read data from a JSON file. + + Parameters + ---------- + fname : str + Full path to the data-containing file + + Returns + ------- + dict + """ + with open(fname, 'r') as ff: + out = json.load(ff) + return out diff --git a/AFQ/definitions/mapping.py b/AFQ/definitions/mapping.py index 2d2a15a1c..3205c22dc 100644 --- a/AFQ/definitions/mapping.py +++ b/AFQ/definitions/mapping.py @@ -7,7 +7,7 @@ from AFQ.definitions.utils import Definition, find_file from dipy.align import syn_registration, affine_registration import AFQ.registration as reg -import AFQ.data.s3bids as afs +from AFQ.data.utils import write_json from AFQ.tasks.utils import get_fname from dipy.align.imaffine import AffineMap @@ -320,7 +320,7 @@ def prealign(self, base_fname, reg_subject, reg_template, save=True): np.save(prealign_file, aff) meta_fname = get_fname( base_fname, f'{prealign_file_desc}.json') - afs.write_json(meta_fname, meta) + write_json(meta_fname, meta) return prealign_file if save else np.load(prealign_file) def get_for_subses(self, base_fname, dwi, bids_info, reg_subject, @@ -350,7 +350,7 @@ def get_for_subses(self, base_fname, dwi, bids_info, reg_subject, meta["dependent"] = "dwi" else: meta["dependent"] = "trk" - afs.write_json(meta_fname, meta) + write_json(meta_fname, meta) reg_prealign_inv = np.linalg.inv(reg_prealign) if self.use_prealign\ else None mapping = reg.read_mapping( diff --git a/AFQ/tasks/decorators.py b/AFQ/tasks/decorators.py index 3a6c23652..65f233bcb 100644 --- a/AFQ/tasks/decorators.py +++ b/AFQ/tasks/decorators.py @@ -7,7 +7,7 @@ import nibabel as nib from dipy.io.streamline import save_tractogram from dipy.io.stateful_tractogram import StatefulTractogram -from AFQ.data.s3bids import write_json +from AFQ.data.utils import write_json import numpy as np diff --git a/AFQ/tasks/mapping.py b/AFQ/tasks/mapping.py index 99f79a748..7e8916e5d 100644 --- a/AFQ/tasks/mapping.py +++ b/AFQ/tasks/mapping.py @@ -8,7 +8,7 @@ from AFQ.tasks.decorators import as_file from AFQ.tasks.utils import get_fname, with_name, str_to_desc import AFQ.data.fetch as afd -from AFQ.data.s3bids import write_json +from AFQ.data.utils import write_json from AFQ.utils.path import drop_extension import AFQ.utils.volume as auv from AFQ.definitions.mapping import SynMap diff --git a/AFQ/tasks/segmentation.py b/AFQ/tasks/segmentation.py index 3fc54e5d7..7e0c845e0 100644 --- a/AFQ/tasks/segmentation.py +++ b/AFQ/tasks/segmentation.py @@ -14,7 +14,7 @@ from AFQ.utils.path import drop_extension import AFQ.utils.streamlines as aus from AFQ.tasks.utils import get_default_args -from AFQ.data.s3bids import write_json +from AFQ.data.utils import write_json import AFQ.api.bundle_dict as abd import AFQ.utils.streamlines as aus import AFQ.utils.volume as auv diff --git a/AFQ/tasks/viz.py b/AFQ/tasks/viz.py index be0f04726..e2a56add7 100644 --- a/AFQ/tasks/viz.py +++ b/AFQ/tasks/viz.py @@ -12,7 +12,7 @@ from AFQ.tasks.utils import get_fname, with_name, str_to_desc import AFQ.utils.volume as auv -from AFQ.data.s3bids import write_json +from AFQ.data.utils import write_json from AFQ.viz.utils import Viz from plotly.subplots import make_subplots diff --git a/AFQ/utils/streamlines.py b/AFQ/utils/streamlines.py index f35129f6d..e54ea30e3 100644 --- a/AFQ/utils/streamlines.py +++ b/AFQ/utils/streamlines.py @@ -2,7 +2,7 @@ from dipy.io.streamline import load_tractogram import numpy as np from dipy.io.stateful_tractogram import StatefulTractogram, Space -from AFQ.data.s3bids import read_json +from AFQ.data.utils import read_json import os.path as op from AFQ.utils.path import drop_extension