Skip to content

Commit

Permalink
[DOC] add proper documentation to nimads module (#778)
Browse files Browse the repository at this point in the history
* add proper documentation to nimads module

* add classes to API

* fix grammar
  • Loading branch information
jdkent authored Mar 30, 2023
1 parent 5088944 commit 28ef8f7
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 28 deletions.
23 changes: 23 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,29 @@ For more information about functional characterization analysis, see :doc:`decod
io.convert_neurovault_to_dataset


.. _api_nimads_ref:

:mod:`nimare.nimads`: NeuroImaging Meta-Analysis Data Structure
---------------------------------------------------------------
.. automodule:: nimare.nimads
:no-members:
:no-inherited-members:

.. currentmodule:: nimare

.. autosummary::
:toctree: generated/
:template: class.rst

nimads.Studyset
nimads.Annotation
nimads.Study
nimads.Analysis
nimads.Condition
nimads.Image
nimads.Point


.. _api_transforms_ref:

:mod:`nimare.transforms`: Data transforms
Expand Down
19 changes: 18 additions & 1 deletion nimare/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,24 @@


def convert_nimads_to_dataset(studyset, annotation=None):
"""Convert nimads studyset to a dataset."""
"""Convert nimads studyset to a dataset.
.. versionadded:: 0.0.14
Parameters
----------
studyset : :obj:`str`, :obj:`dict`, :obj:`nimare.nimads.StudySet`
Path to a JSON file containing a nimads studyset, a dictionary containing a nimads
studyset, or a nimads studyset object.
annotation : :obj:`str`, :obj:`dict`, :obj:`nimare.nimads.Annotation`, optional
Optional path to a JSON file containing a nimads annotation, a dictionary containing a
nimads annotation, or a nimads annotation object.
Returns
-------
dset : :obj:`nimare.dataset.Dataset`
NiMARE Dataset object containing experiment information from nimads studyset.
"""

def _analysis_to_dict(study, analysis):
result = {
Expand Down
107 changes: 80 additions & 27 deletions nimare/nimads.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,19 @@
class Studyset:
"""A collection of studies for meta-analysis.
.. versionadded:: 0.0.14
This is the primary target for Estimators and Transformers in NiMARE.
Attributes
----------
studies : list of Study objects
id : str
A unique identifier for the Studyset.
name : str
A human-readable name for the Studyset.
annotations : :obj:`list` of :obj:`nimare.nimads.Annotation` objects
The Annotation objects associated with the Studyset.
studies : :obj:`list` of :obj:`nimare.nimads.Study` objects
The Study objects comprising the Studyset.
"""

Expand All @@ -34,7 +42,7 @@ def __init__(self, source, target_space=None, mask=None, annotations=None):

def __repr__(self):
"""My Simple representation."""
return repr("Studyset: " + self.id)
return repr(f"<Studyset: {self.id}>")

def __str__(self):
"""Give useful information about the Studyset."""
Expand Down Expand Up @@ -73,7 +81,8 @@ def from_nimads(cls, filename):

def to_nimads(self, filename):
"""Write the Studyset to a NIMADS JSON file."""
...
with open(filename, "w+") as fn:
json.dump(self.to_dict(), fn)

def to_dict(self):
"""Return a dictionary representation of the Studyset."""
Expand All @@ -89,11 +98,11 @@ def to_dataset(self):

def load(self, filename):
"""Load a Studyset from a pickled file."""
...
raise NotImplementedError("Loading from pickled files is not yet supported.")

def save(self, filename):
"""Write the Studyset to a pickled file."""
...
raise NotImplementedError("Saving to pickled files is not yet supported.")

def copy(self):
"""Create a copy of the Studyset."""
Expand All @@ -117,66 +126,77 @@ def slice(self, analyses):

def merge(self, right):
"""Merge a separate Studyset into the current one."""
...
raise NotImplementedError("Merging Studysets is not yet supported.")

def update_image_path(self, new_path):
"""Point to a new location for image files on the local filesystem."""
...
raise NotImplementedError("Updating image paths is not yet supported.")

def get_analyses_by_coordinates(self, xyz, r=None, n=None):
"""Extract a list of Analyses with at least one Point near the requested coordinates."""
...
raise NotImplementedError("Getting analyses by coordinates is not yet supported.")

def get_analyses_by_mask(self, img):
"""Extract a list of Analyses with at least one Point in the specified mask."""
...
raise NotImplementedError("Getting analyses by mask is not yet supported.")

def get_analyses_by_annotations(self):
"""Extract a list of Analyses with a given label/annotation."""
...
raise NotImplementedError("Getting analyses by annotations is not yet supported.")

def get_analyses_by_texts(self):
"""Extract a list of Analyses with a given text."""
...
raise NotImplementedError("Getting analyses by texts is not yet supported.")

def get_analyses_by_images(self):
"""Extract a list of Analyses with a given image."""
...
raise NotImplementedError("Getting analyses by images is not yet supported.")

def get_analyses_by_metadata(self):
"""Extract a list of Analyses with a metadata field/value."""
...
raise NotImplementedError("Getting analyses by metadata is not yet supported.")

def get_points(self, analyses):
"""Collect Points associated with specified Analyses."""
...
raise NotImplementedError("Getting points is not yet supported.")

def get_annotations(self, analyses):
"""Collect Annotations associated with specified Analyses."""
...
raise NotImplementedError("Getting annotations is not yet supported.")

def get_texts(self, analyses):
"""Collect texts associated with specified Analyses."""
...
raise NotImplementedError("Getting texts is not yet supported.")

def get_images(self, analyses):
"""Collect image files associated with specified Analyses."""
...
raise NotImplementedError("Getting images is not yet supported.")

def get_metadata(self, analyses):
"""Collect metadata associated with specified Analyses."""
...
raise NotImplementedError("Getting metadata is not yet supported.")


class Study:
"""A collection of Analyses from the same paper.
.. versionadded:: 0.0.14
Attributes
----------
id : str
A unique identifier for the Study.
analyses : list of Analysis objects
name : str
A human readable name of the Study, typically the title of the paper.
authors : str
A string of the authors of the paper.
publication : str
A string of the publication information for the paper, typically a journal name.
metadata : dict
A dictionary of metadata associated with the Study.
analyses : :obj:`list` of :obj:`nimare.nimads.Analysis` objects
The Analysis objects comprising the Study.
An analysis represents a contrast with statistical results.
"""

def __init__(self, source):
Expand All @@ -189,7 +209,7 @@ def __init__(self, source):

def __repr__(self):
"""My Simple representation."""
return repr(self.id)
return repr(f"<Study: {self.id}>")

def __str__(self):
"""My Simple representation."""
Expand Down Expand Up @@ -217,19 +237,21 @@ def to_dict(self):


class Analysis:
"""A single statistical analyses from a Study.
"""A single statistical contrast from a Study.
.. versionadded:: 0.0.14
Attributes
----------
id : str
A unique identifier for the Analysis.
name : str
A human readable name of the Analysis.
conditions : list of Condition objects
The Conditions in the Analysis.
annotations : list of Annotation objects
Any Annotations available for the Analysis.
Each Annotation should come from the same Annotator.
texts : dict
A dictionary of source: text pairs.
images : dict of Image objects
A dictionary of type: Image pairs.
points : list of Point objects
Expand All @@ -238,8 +260,6 @@ class Analysis:
Notes
-----
Should the images attribute be a list instead, if the Images contain type information?
Should the conditions be linked to the annotations, images, and points at all?
"""

def __init__(self, source):
Expand All @@ -254,7 +274,7 @@ def __init__(self, source):

def __repr__(self):
"""My Simple representation."""
return repr(f"Analysis: {self.id}")
return repr(f"<Analysis: {self.id}>")

def __str__(self):
"""My Simple representation."""
Expand All @@ -280,11 +300,16 @@ def to_dict(self):
class Condition:
"""A condition within an Analysis.
.. versionadded:: 0.0.14
Attributes
----------
name
name: str
A human readable name of the Condition. Good examples are from cognitive atlas.
description
A human readable description of the Condition.
weight
The weight of the Condition in the Analysis.
Notes
-----
Expand All @@ -298,6 +323,10 @@ def __init__(self, condition, weight):
self.description = condition["description"]
self.weight = weight

def __repr__(self):
"""My Simple representation."""
return repr(f"<Condition: {self.id}>")

def to_dict(self):
"""Convert the Condition to a dictionary."""
return {"name": self.name, "description": self.description, "weight": self.weight}
Expand All @@ -306,6 +335,8 @@ def to_dict(self):
class Annotation:
"""A collection of labels and associated weights from the same Annotator.
.. versionadded:: 0.0.14
Attributes
----------
term_weights : :obj:`pandas.DataFrame`
Expand Down Expand Up @@ -336,6 +367,10 @@ def __init__(self, source, studyset):
for note in self.notes:
self._analysis_ref[note.analysis.id].annotations[self.id] = note.note

def __repr__(self):
"""My Simple representation."""
return repr(f"<Annotation: {self.id}>")

def to_dict(self):
"""Convert the Annotation to a dictionary."""
return {"name": self.name, "id": self.id, "notes": [note.to_dict() for note in self.notes]}
Expand All @@ -344,6 +379,8 @@ def to_dict(self):
class Note:
"""A Note within an annotation.
.. versionadded:: 0.0.14
Attributes
----------
analysis : Analysis object
Expand All @@ -356,6 +393,10 @@ def __init__(self, analysis, note):
self.analysis = analysis
self.note = note

def __repr__(self):
"""My Simple representation."""
return repr(f"<Note: {self.id}>")

def to_dict(self):
"""Convert the Note to a dictionary."""
return {"analysis": self.analysis.id, "note": self.note}
Expand All @@ -364,6 +405,8 @@ def to_dict(self):
class Image:
"""A single statistical map from an Analysis.
.. versionadded:: 0.0.14
Attributes
----------
filename
Expand All @@ -380,6 +423,10 @@ def __init__(self, source):
self.space = source["space"]
self.value_type = source["value_type"]

def __repr__(self):
"""My Simple representation."""
return repr(f"<Image: {self.id}>")

def to_dict(self):
"""Convert the Image to a dictionary."""
return {
Expand All @@ -393,6 +440,8 @@ def to_dict(self):
class Point:
"""A single peak coordinate from an Analysis.
.. versionadded:: 0.0.14
Attributes
----------
x : float
Expand All @@ -410,6 +459,10 @@ def __init__(self, source):
self.y = source["coordinates"][1]
self.z = source["coordinates"][2]

def __repr__(self):
"""My Simple representation."""
return repr(f"<Point: {self.id}>")

def to_dict(self):
"""Convert the Point to a dictionary."""
return {"space": self.space, "coordinates": [self.x, self.y, self.z]}

0 comments on commit 28ef8f7

Please sign in to comment.