junifer 0.0.5__py3-none-any.whl → 0.0.5.dev24__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. junifer/__init__.py +0 -17
  2. junifer/_version.py +2 -2
  3. junifer/api/__init__.py +1 -4
  4. junifer/api/cli.py +1 -91
  5. junifer/api/decorators.py +0 -9
  6. junifer/api/functions.py +10 -56
  7. junifer/api/parser.py +0 -3
  8. junifer/api/queue_context/__init__.py +1 -4
  9. junifer/api/res/afni/run_afni_docker.sh +1 -1
  10. junifer/api/res/ants/run_ants_docker.sh +1 -1
  11. junifer/api/res/fsl/run_fsl_docker.sh +1 -1
  12. junifer/api/tests/test_api_utils.py +2 -4
  13. junifer/api/tests/test_cli.py +0 -83
  14. junifer/api/tests/test_functions.py +2 -27
  15. junifer/configs/__init__.py +1 -1
  16. junifer/configs/juseless/__init__.py +1 -4
  17. junifer/configs/juseless/datagrabbers/__init__.py +1 -10
  18. junifer/configs/juseless/datagrabbers/aomic_id1000_vbm.py +0 -3
  19. junifer/configs/juseless/datagrabbers/camcan_vbm.py +0 -3
  20. junifer/configs/juseless/datagrabbers/ixi_vbm.py +0 -3
  21. junifer/configs/juseless/datagrabbers/tests/test_ucla.py +3 -1
  22. junifer/configs/juseless/datagrabbers/ucla.py +9 -12
  23. junifer/configs/juseless/datagrabbers/ukb_vbm.py +0 -3
  24. junifer/data/__init__.py +1 -21
  25. junifer/data/coordinates.py +19 -10
  26. junifer/data/masks.py +87 -58
  27. junifer/data/parcellations.py +3 -14
  28. junifer/data/template_spaces.py +1 -4
  29. junifer/data/tests/test_masks.py +37 -26
  30. junifer/data/utils.py +0 -3
  31. junifer/datagrabber/__init__.py +1 -18
  32. junifer/datagrabber/aomic/__init__.py +0 -3
  33. junifer/datagrabber/aomic/id1000.py +37 -70
  34. junifer/datagrabber/aomic/piop1.py +36 -69
  35. junifer/datagrabber/aomic/piop2.py +38 -71
  36. junifer/datagrabber/aomic/tests/test_id1000.py +99 -44
  37. junifer/datagrabber/aomic/tests/test_piop1.py +108 -65
  38. junifer/datagrabber/aomic/tests/test_piop2.py +102 -45
  39. junifer/datagrabber/base.py +6 -13
  40. junifer/datagrabber/datalad_base.py +1 -13
  41. junifer/datagrabber/dmcc13_benchmark.py +53 -36
  42. junifer/datagrabber/hcp1200/__init__.py +0 -3
  43. junifer/datagrabber/hcp1200/datalad_hcp1200.py +0 -3
  44. junifer/datagrabber/hcp1200/hcp1200.py +1 -4
  45. junifer/datagrabber/multiple.py +6 -45
  46. junifer/datagrabber/pattern.py +62 -170
  47. junifer/datagrabber/pattern_datalad.py +12 -25
  48. junifer/datagrabber/tests/test_datagrabber_utils.py +218 -0
  49. junifer/datagrabber/tests/test_datalad_base.py +4 -4
  50. junifer/datagrabber/tests/test_dmcc13_benchmark.py +19 -46
  51. junifer/datagrabber/tests/test_multiple.py +84 -161
  52. junifer/datagrabber/tests/test_pattern.py +0 -45
  53. junifer/datagrabber/tests/test_pattern_datalad.py +4 -4
  54. junifer/datagrabber/utils.py +230 -0
  55. junifer/datareader/__init__.py +1 -4
  56. junifer/datareader/default.py +43 -95
  57. junifer/external/__init__.py +1 -1
  58. junifer/external/nilearn/__init__.py +1 -5
  59. junifer/external/nilearn/junifer_nifti_spheres_masker.py +9 -23
  60. junifer/external/nilearn/tests/test_junifer_nifti_spheres_masker.py +1 -76
  61. junifer/markers/__init__.py +1 -23
  62. junifer/markers/base.py +28 -68
  63. junifer/markers/collection.py +2 -10
  64. junifer/markers/complexity/__init__.py +0 -10
  65. junifer/markers/complexity/complexity_base.py +43 -26
  66. junifer/markers/complexity/hurst_exponent.py +0 -3
  67. junifer/markers/complexity/multiscale_entropy_auc.py +0 -3
  68. junifer/markers/complexity/perm_entropy.py +0 -3
  69. junifer/markers/complexity/range_entropy.py +0 -3
  70. junifer/markers/complexity/range_entropy_auc.py +0 -3
  71. junifer/markers/complexity/sample_entropy.py +0 -3
  72. junifer/markers/complexity/tests/test_hurst_exponent.py +3 -11
  73. junifer/markers/complexity/tests/test_multiscale_entropy_auc.py +3 -11
  74. junifer/markers/complexity/tests/test_perm_entropy.py +3 -11
  75. junifer/markers/complexity/tests/test_range_entropy.py +3 -11
  76. junifer/markers/complexity/tests/test_range_entropy_auc.py +3 -11
  77. junifer/markers/complexity/tests/test_sample_entropy.py +3 -11
  78. junifer/markers/complexity/tests/test_weighted_perm_entropy.py +3 -11
  79. junifer/markers/complexity/weighted_perm_entropy.py +0 -3
  80. junifer/markers/ets_rss.py +42 -27
  81. junifer/markers/falff/__init__.py +0 -3
  82. junifer/markers/falff/_afni_falff.py +2 -5
  83. junifer/markers/falff/_junifer_falff.py +0 -3
  84. junifer/markers/falff/falff_base.py +46 -20
  85. junifer/markers/falff/falff_parcels.py +27 -56
  86. junifer/markers/falff/falff_spheres.py +29 -60
  87. junifer/markers/falff/tests/test_falff_parcels.py +23 -39
  88. junifer/markers/falff/tests/test_falff_spheres.py +23 -39
  89. junifer/markers/functional_connectivity/__init__.py +0 -9
  90. junifer/markers/functional_connectivity/crossparcellation_functional_connectivity.py +60 -63
  91. junifer/markers/functional_connectivity/edge_functional_connectivity_parcels.py +32 -45
  92. junifer/markers/functional_connectivity/edge_functional_connectivity_spheres.py +36 -49
  93. junifer/markers/functional_connectivity/functional_connectivity_base.py +70 -71
  94. junifer/markers/functional_connectivity/functional_connectivity_parcels.py +25 -34
  95. junifer/markers/functional_connectivity/functional_connectivity_spheres.py +30 -40
  96. junifer/markers/functional_connectivity/tests/test_crossparcellation_functional_connectivity.py +7 -11
  97. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_parcels.py +7 -27
  98. junifer/markers/functional_connectivity/tests/test_edge_functional_connectivity_spheres.py +12 -28
  99. junifer/markers/functional_connectivity/tests/test_functional_connectivity_parcels.py +11 -35
  100. junifer/markers/functional_connectivity/tests/test_functional_connectivity_spheres.py +62 -36
  101. junifer/markers/parcel_aggregation.py +61 -47
  102. junifer/markers/reho/__init__.py +0 -3
  103. junifer/markers/reho/_afni_reho.py +2 -5
  104. junifer/markers/reho/_junifer_reho.py +1 -4
  105. junifer/markers/reho/reho_base.py +27 -8
  106. junifer/markers/reho/reho_parcels.py +17 -28
  107. junifer/markers/reho/reho_spheres.py +18 -27
  108. junifer/markers/reho/tests/test_reho_parcels.py +3 -8
  109. junifer/markers/reho/tests/test_reho_spheres.py +3 -8
  110. junifer/markers/sphere_aggregation.py +59 -43
  111. junifer/markers/temporal_snr/__init__.py +0 -3
  112. junifer/markers/temporal_snr/temporal_snr_base.py +32 -23
  113. junifer/markers/temporal_snr/temporal_snr_parcels.py +6 -9
  114. junifer/markers/temporal_snr/temporal_snr_spheres.py +6 -9
  115. junifer/markers/temporal_snr/tests/test_temporal_snr_parcels.py +3 -6
  116. junifer/markers/temporal_snr/tests/test_temporal_snr_spheres.py +3 -6
  117. junifer/markers/tests/test_collection.py +8 -9
  118. junifer/markers/tests/test_ets_rss.py +9 -15
  119. junifer/markers/tests/test_markers_base.py +18 -17
  120. junifer/markers/tests/test_parcel_aggregation.py +32 -93
  121. junifer/markers/tests/test_sphere_aggregation.py +19 -72
  122. junifer/onthefly/__init__.py +1 -4
  123. junifer/onthefly/read_transform.py +0 -3
  124. junifer/pipeline/__init__.py +1 -9
  125. junifer/pipeline/pipeline_step_mixin.py +4 -21
  126. junifer/pipeline/registry.py +0 -3
  127. junifer/pipeline/singleton.py +0 -3
  128. junifer/pipeline/tests/test_registry.py +1 -1
  129. junifer/pipeline/update_meta_mixin.py +0 -3
  130. junifer/pipeline/utils.py +1 -67
  131. junifer/pipeline/workdir_manager.py +0 -3
  132. junifer/preprocess/__init__.py +2 -9
  133. junifer/preprocess/ants/__init__.py +4 -0
  134. junifer/preprocess/ants/ants_apply_transforms_warper.py +185 -0
  135. junifer/preprocess/ants/tests/test_ants_apply_transforms_warper.py +56 -0
  136. junifer/preprocess/base.py +3 -6
  137. junifer/preprocess/bold_warper.py +265 -0
  138. junifer/preprocess/confounds/__init__.py +0 -3
  139. junifer/preprocess/confounds/fmriprep_confound_remover.py +60 -47
  140. junifer/preprocess/confounds/tests/test_fmriprep_confound_remover.py +113 -72
  141. junifer/preprocess/fsl/__init__.py +4 -0
  142. junifer/preprocess/fsl/apply_warper.py +179 -0
  143. junifer/preprocess/fsl/tests/test_apply_warper.py +45 -0
  144. junifer/preprocess/smoothing/__init__.py +0 -3
  145. junifer/preprocess/smoothing/_afni_smoothing.py +1 -1
  146. junifer/preprocess/tests/test_bold_warper.py +159 -0
  147. junifer/preprocess/warping/__init__.py +0 -3
  148. junifer/preprocess/warping/_ants_warper.py +0 -3
  149. junifer/preprocess/warping/_fsl_warper.py +0 -3
  150. junifer/stats.py +1 -4
  151. junifer/storage/__init__.py +1 -9
  152. junifer/storage/base.py +1 -40
  153. junifer/storage/hdf5.py +9 -71
  154. junifer/storage/pandas_base.py +0 -3
  155. junifer/storage/sqlite.py +0 -3
  156. junifer/storage/tests/test_hdf5.py +10 -82
  157. junifer/storage/utils.py +0 -9
  158. junifer/testing/__init__.py +1 -4
  159. junifer/testing/datagrabbers.py +6 -13
  160. junifer/testing/tests/test_partlycloudytesting_datagrabber.py +7 -7
  161. junifer/testing/utils.py +0 -3
  162. junifer/utils/__init__.py +2 -13
  163. junifer/utils/fs.py +0 -3
  164. junifer/utils/helpers.py +1 -32
  165. junifer/utils/logging.py +4 -33
  166. junifer/utils/tests/test_logging.py +0 -8
  167. {junifer-0.0.5.dist-info → junifer-0.0.5.dev24.dist-info}/METADATA +16 -17
  168. junifer-0.0.5.dev24.dist-info/RECORD +265 -0
  169. {junifer-0.0.5.dist-info → junifer-0.0.5.dev24.dist-info}/WHEEL +1 -1
  170. junifer/api/res/freesurfer/mri_binarize +0 -3
  171. junifer/api/res/freesurfer/mri_mc +0 -3
  172. junifer/api/res/freesurfer/mri_pretess +0 -3
  173. junifer/api/res/freesurfer/mris_convert +0 -3
  174. junifer/api/res/freesurfer/run_freesurfer_docker.sh +0 -61
  175. junifer/data/masks/ukb/UKB_15K_GM_template.nii.gz +0 -0
  176. junifer/datagrabber/pattern_validation_mixin.py +0 -388
  177. junifer/datagrabber/tests/test_pattern_validation_mixin.py +0 -249
  178. junifer/external/BrainPrint/brainprint/__init__.py +0 -4
  179. junifer/external/BrainPrint/brainprint/_version.py +0 -3
  180. junifer/external/BrainPrint/brainprint/asymmetry.py +0 -91
  181. junifer/external/BrainPrint/brainprint/brainprint.py +0 -441
  182. junifer/external/BrainPrint/brainprint/surfaces.py +0 -258
  183. junifer/external/BrainPrint/brainprint/utils/__init__.py +0 -1
  184. junifer/external/BrainPrint/brainprint/utils/_config.py +0 -112
  185. junifer/external/BrainPrint/brainprint/utils/utils.py +0 -188
  186. junifer/external/nilearn/junifer_connectivity_measure.py +0 -483
  187. junifer/external/nilearn/tests/test_junifer_connectivity_measure.py +0 -1089
  188. junifer/markers/brainprint.py +0 -459
  189. junifer/markers/tests/test_brainprint.py +0 -58
  190. junifer-0.0.5.dist-info/RECORD +0 -275
  191. {junifer-0.0.5.dist-info → junifer-0.0.5.dev24.dist-info}/AUTHORS.rst +0 -0
  192. {junifer-0.0.5.dist-info → junifer-0.0.5.dev24.dist-info}/LICENSE.md +0 -0
  193. {junifer-0.0.5.dist-info → junifer-0.0.5.dev24.dist-info}/entry_points.txt +0 -0
  194. {junifer-0.0.5.dist-info → junifer-0.0.5.dev24.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- """Markers for feature extraction."""
1
+ """Provide imports for markers sub-package."""
2
2
 
3
3
  # Authors: Federico Raimondo <f.raimondo@fz-juelich.de>
4
4
  # Leonard Sasse <l.sasse@fz-juelich.de>
@@ -23,25 +23,3 @@ from .temporal_snr import (
23
23
  TemporalSNRParcels,
24
24
  TemporalSNRSpheres,
25
25
  )
26
- from .brainprint import BrainPrint
27
-
28
-
29
- __all__ = [
30
- "BaseMarker",
31
- "MarkerCollection",
32
- "RSSETSMarker",
33
- "ParcelAggregation",
34
- "SphereAggregation",
35
- "FunctionalConnectivityParcels",
36
- "FunctionalConnectivitySpheres",
37
- "CrossParcellationFC",
38
- "EdgeCentricFCParcels",
39
- "EdgeCentricFCSpheres",
40
- "ReHoParcels",
41
- "ReHoSpheres",
42
- "ALFFParcels",
43
- "ALFFSpheres",
44
- "TemporalSNRParcels",
45
- "TemporalSNRSpheres",
46
- "BrainPrint",
47
- ]
junifer/markers/base.py CHANGED
@@ -5,7 +5,6 @@
5
5
  # License: AGPL
6
6
 
7
7
  from abc import ABC, abstractmethod
8
- from copy import deepcopy
9
8
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
10
9
 
11
10
  from ..pipeline import PipelineStepMixin, UpdateMetaMixin
@@ -16,28 +15,20 @@ if TYPE_CHECKING:
16
15
  from junifer.storage import BaseFeatureStorage
17
16
 
18
17
 
19
- __all__ = ["BaseMarker"]
20
-
21
-
22
18
  class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin):
23
19
  """Abstract base class for all markers.
24
20
 
25
- For every interface that is required, one needs to provide a concrete
26
- implementation of this abstract class.
27
-
28
21
  Parameters
29
22
  ----------
30
- on : str or list of str or None, optional
31
- The data type to apply the marker on. If None,
32
- will work on all available data types (default None).
23
+ on : str or list of str
24
+ The kind of data to apply the marker to. By default, will work on all
25
+ available data.
33
26
  name : str, optional
34
- The name of the marker. If None, will use the class name as the
27
+ The name of the marker. By default, it will use the class name as the
35
28
  name of the marker (default None).
36
29
 
37
30
  Raises
38
31
  ------
39
- AttributeError
40
- If the marker does not have `_MARKER_INOUT_MAPPINGS` attribute.
41
32
  ValueError
42
33
  If required input data type(s) is(are) not found.
43
34
 
@@ -48,12 +39,6 @@ class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin):
48
39
  on: Optional[Union[List[str], str]] = None,
49
40
  name: Optional[str] = None,
50
41
  ) -> None:
51
- # Check for missing mapping attribute
52
- if not hasattr(self, "_MARKER_INOUT_MAPPINGS"):
53
- raise_error(
54
- msg=("Missing `_MARKER_INOUT_MAPPINGS` for the marker"),
55
- klass=AttributeError,
56
- )
57
42
  # Use all data types if not provided
58
43
  if on is None:
59
44
  on = self.get_valid_inputs()
@@ -97,6 +82,7 @@ class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin):
97
82
  )
98
83
  return [x for x in self._on if x in input]
99
84
 
85
+ @abstractmethod
100
86
  def get_valid_inputs(self) -> List[str]:
101
87
  """Get valid data types for input.
102
88
 
@@ -106,25 +92,30 @@ class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin):
106
92
  The list of data types that can be used as input for this marker.
107
93
 
108
94
  """
109
- return list(self._MARKER_INOUT_MAPPINGS.keys())
95
+ raise_error(
96
+ msg="Concrete classes need to implement get_valid_inputs().",
97
+ klass=NotImplementedError,
98
+ )
110
99
 
111
- def get_output_type(self, input_type: str, output_feature: str) -> str:
100
+ @abstractmethod
101
+ def get_output_type(self, input_type: str) -> str:
112
102
  """Get output type.
113
103
 
114
104
  Parameters
115
105
  ----------
116
106
  input_type : str
117
107
  The data type input to the marker.
118
- output_feature : str
119
- The feature output of the marker.
120
108
 
121
109
  Returns
122
110
  -------
123
111
  str
124
- The storage type output of the marker.
112
+ The storage type output by the marker.
125
113
 
126
114
  """
127
- return self._MARKER_INOUT_MAPPINGS[input_type][output_feature]
115
+ raise_error(
116
+ msg="Concrete classes need to implement get_output_type().",
117
+ klass=NotImplementedError,
118
+ )
128
119
 
129
120
  @abstractmethod
130
121
  def compute(self, input: Dict, extra_input: Optional[Dict] = None) -> Dict:
@@ -157,7 +148,6 @@ class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin):
157
148
  def store(
158
149
  self,
159
150
  type_: str,
160
- feature: str,
161
151
  out: Dict[str, Any],
162
152
  storage: "BaseFeatureStorage",
163
153
  ) -> None:
@@ -167,15 +157,13 @@ class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin):
167
157
  ----------
168
158
  type_ : str
169
159
  The data type to store.
170
- feature : str
171
- The feature to store.
172
160
  out : dict
173
161
  The computed result as a dictionary to store.
174
162
  storage : storage-like
175
163
  The storage class, for example, SQLiteFeatureStorage.
176
164
 
177
165
  """
178
- output_type_ = self.get_output_type(type_, feature)
166
+ output_type_ = self.get_output_type(type_)
179
167
  logger.debug(f"Storing {output_type_} in {storage}")
180
168
  storage.store(kind=output_type_, **out)
181
169
 
@@ -204,50 +192,22 @@ class BaseMarker(ABC, PipelineStepMixin, UpdateMetaMixin):
204
192
  for type_ in self._on:
205
193
  if type_ in input.keys():
206
194
  logger.info(f"Computing {type_}")
207
- # Get data dict for data type
208
195
  t_input = input[type_]
209
- # Pass the other data types as extra input, removing
210
- # the current type
211
196
  extra_input = input.copy()
212
197
  extra_input.pop(type_)
213
- logger.debug(
214
- f"Extra data type for feature extraction: "
215
- f"{extra_input.keys()}"
216
- )
217
- # Copy metadata
218
198
  t_meta = t_input["meta"].copy()
219
199
  t_meta["type"] = type_
220
- # Compute marker
200
+
221
201
  t_out = self.compute(input=t_input, extra_input=extra_input)
222
- # Initialize empty dictionary if no storage object is provided
223
- if storage is None:
224
- out[type_] = {}
225
- # Store individual features
226
- for feature_name, feature_data in t_out.items():
227
- # Make deep copy of the feature data for manipulation
228
- feature_data_copy = deepcopy(feature_data)
229
- # Make deep copy of metadata and add to feature data
230
- feature_data_copy["meta"] = deepcopy(t_meta)
231
- # Update metadata for the feature,
232
- # feature data is not manipulated, only meta
233
- self.update_meta(feature_data_copy, "marker")
234
- # Update marker feature's metadata name
235
- feature_data_copy["meta"]["marker"][
236
- "name"
237
- ] += f"_{feature_name}"
238
-
239
- if storage is not None:
240
- logger.info(f"Storing in {storage}")
241
- self.store(
242
- type_=type_,
243
- feature=feature_name,
244
- out=feature_data_copy,
245
- storage=storage,
246
- )
247
- else:
248
- logger.info(
249
- "No storage specified, returning dictionary"
250
- )
251
- out[type_][feature_name] = feature_data_copy
202
+ t_out["meta"] = t_meta
203
+
204
+ self.update_meta(t_out, "marker")
205
+
206
+ if storage is not None:
207
+ logger.info(f"Storing in {storage}")
208
+ self.store(type_=type_, out=t_out, storage=storage)
209
+ else:
210
+ logger.info("No storage specified, returning dictionary")
211
+ out[type_] = t_out
252
212
 
253
213
  return out
@@ -19,9 +19,6 @@ if TYPE_CHECKING:
19
19
  from junifer.datagrabber import BaseDataGrabber
20
20
 
21
21
 
22
- __all__ = ["MarkerCollection"]
23
-
24
-
25
22
  class MarkerCollection:
26
23
  """Class for marker collection.
27
24
 
@@ -139,14 +136,9 @@ class MarkerCollection:
139
136
  "Validating Preprocessor: "
140
137
  f"{preprocessor.__class__.__name__}"
141
138
  )
142
- # Copy existing data types
143
- old_t_data = t_data.copy()
144
- logger.info(f"Preprocessor input type: {t_data}")
145
139
  # Validate preprocessor
146
- new_t_data = preprocessor.validate(old_t_data)
147
- # Set new data types
148
- t_data = list(set(old_t_data) | set(new_t_data))
149
- logger.info(f"Preprocessor output type: {t_data}")
140
+ t_data = preprocessor.validate(t_data)
141
+ logger.info(f"Preprocess output type: {t_data}")
150
142
 
151
143
  for marker in self._markers:
152
144
  logger.info(f"Validating Marker: {marker.name}")
@@ -25,13 +25,3 @@ else:
25
25
  from .weighted_perm_entropy import WeightedPermEntropy
26
26
  from .sample_entropy import SampleEntropy
27
27
  from .multiscale_entropy_auc import MultiscaleEntropyAUC
28
-
29
- __all__ = [
30
- "HurstExponent",
31
- "RangeEntropy",
32
- "RangeEntropyAUC",
33
- "PermEntropy",
34
- "WeightedPermEntropy",
35
- "SampleEntropy",
36
- "MultiscaleEntropyAUC",
37
- ]
@@ -24,9 +24,6 @@ if TYPE_CHECKING:
24
24
  import numpy as np
25
25
 
26
26
 
27
- __all__ = ["ComplexityBase"]
28
-
29
-
30
27
  class ComplexityBase(BaseMarker):
31
28
  """Base class for complexity computation.
32
29
 
@@ -53,12 +50,6 @@ class ComplexityBase(BaseMarker):
53
50
 
54
51
  _DEPENDENCIES: ClassVar[Set[str]] = {"nilearn", "neurokit2"}
55
52
 
56
- _MARKER_INOUT_MAPPINGS: ClassVar[Dict[str, Dict[str, str]]] = {
57
- "BOLD": {
58
- "complexity": "vector",
59
- },
60
- }
61
-
62
53
  def __init__(
63
54
  self,
64
55
  parcellation: Union[str, List[str]],
@@ -84,6 +75,33 @@ class ComplexityBase(BaseMarker):
84
75
  klass=NotImplementedError,
85
76
  )
86
77
 
78
+ def get_valid_inputs(self) -> List[str]:
79
+ """Get valid data types for input.
80
+
81
+ Returns
82
+ -------
83
+ list of str
84
+ The list of data types that can be used as input for this marker.
85
+
86
+ """
87
+ return ["BOLD"]
88
+
89
+ def get_output_type(self, input_type: str) -> str:
90
+ """Get output type.
91
+
92
+ Parameters
93
+ ----------
94
+ input_type : str
95
+ The data type input to the marker.
96
+
97
+ Returns
98
+ -------
99
+ str
100
+ The storage type output by the marker.
101
+
102
+ """
103
+ return "vector"
104
+
87
105
  def compute(
88
106
  self,
89
107
  input: Dict[str, Any],
@@ -103,30 +121,29 @@ class ComplexityBase(BaseMarker):
103
121
  Returns
104
122
  -------
105
123
  dict
106
- The computed result as dictionary. This will be either returned
107
- to the user or stored in the storage by calling the store method
108
- with this as a parameter. The dictionary has the following keys:
124
+ The computed result as dictionary. The following keys will be
125
+ included in the dictionary:
109
126
 
110
- * ``complexity`` : dictionary with the following keys:
111
-
112
- - ``data`` : ROI-wise complexity measures as ``numpy.ndarray``
113
- - ``col_names`` : ROI labels as list of str
127
+ * ``data`` : ROI-wise complexity measures as ``numpy.ndarray``
128
+ * ``col_names`` : ROI labels for the complexity measures as list
114
129
 
115
130
  """
116
- # Extract the 2D time series using ParcelAggregation
131
+ # Initialize a ParcelAggregation
117
132
  parcel_aggregation = ParcelAggregation(
118
133
  parcellation=self.parcellation,
119
134
  method=self.agg_method,
120
135
  method_params=self.agg_method_params,
121
136
  masks=self.masks,
122
137
  on="BOLD",
123
- ).compute(input=input, extra_input=extra_input)
138
+ )
139
+ # Extract the 2D time series using parcel aggregation
140
+ parcel_aggregation_map = parcel_aggregation.compute(
141
+ input=input, extra_input=extra_input
142
+ )
143
+
124
144
  # Compute complexity measure
125
- return {
126
- "complexity": {
127
- "data": self.compute_complexity(
128
- parcel_aggregation["aggregation"]["data"]
129
- ),
130
- "col_names": parcel_aggregation["aggregation"]["col_names"],
131
- }
132
- }
145
+ parcel_aggregation_map["data"] = self.compute_complexity(
146
+ parcel_aggregation_map["data"]
147
+ )
148
+
149
+ return parcel_aggregation_map
@@ -14,9 +14,6 @@ from ...utils import logger, warn_with_log
14
14
  from .complexity_base import ComplexityBase
15
15
 
16
16
 
17
- __all__ = ["HurstExponent"]
18
-
19
-
20
17
  @register_marker
21
18
  class HurstExponent(ComplexityBase):
22
19
  """Class for Hurst exponent of a time series.
@@ -14,9 +14,6 @@ from ...utils import logger, warn_with_log
14
14
  from .complexity_base import ComplexityBase
15
15
 
16
16
 
17
- __all__ = ["MultiscaleEntropyAUC"]
18
-
19
-
20
17
  @register_marker
21
18
  class MultiscaleEntropyAUC(ComplexityBase):
22
19
  """Class for AUC of multiscale entropy of a time series.
@@ -14,9 +14,6 @@ from ...utils import logger, warn_with_log
14
14
  from .complexity_base import ComplexityBase
15
15
 
16
16
 
17
- __all__ = ["PermEntropy"]
18
-
19
-
20
17
  @register_marker
21
18
  class PermEntropy(ComplexityBase):
22
19
  """Class for permutation entropy of a time series.
@@ -14,9 +14,6 @@ from ...utils import logger, warn_with_log
14
14
  from .complexity_base import ComplexityBase
15
15
 
16
16
 
17
- __all__ = ["RangeEntropy"]
18
-
19
-
20
17
  @register_marker
21
18
  class RangeEntropy(ComplexityBase):
22
19
  """Class for range entropy of a time series.
@@ -14,9 +14,6 @@ from ...utils import logger, warn_with_log
14
14
  from .complexity_base import ComplexityBase
15
15
 
16
16
 
17
- __all__ = ["RangeEntropyAUC"]
18
-
19
-
20
17
  @register_marker
21
18
  class RangeEntropyAUC(ComplexityBase):
22
19
  """Class for AUC of range entropy values of a time series over r = 0 to 1.
@@ -14,9 +14,6 @@ from ...utils import logger, warn_with_log
14
14
  from .complexity_base import ComplexityBase
15
15
 
16
16
 
17
- __all__ = ["SampleEntropy"]
18
-
19
-
20
17
  @register_marker
21
18
  class SampleEntropy(ComplexityBase):
22
19
  """Class for sample entropy of a time series.
@@ -14,7 +14,6 @@ pytest.importorskip("neurokit2")
14
14
 
15
15
  from junifer.datareader import DefaultDataReader # noqa: E402
16
16
  from junifer.markers.complexity import HurstExponent # noqa: E402
17
- from junifer.pipeline.utils import _check_ants # noqa: E402
18
17
  from junifer.storage import SQLiteFeatureStorage # noqa: E402
19
18
  from junifer.testing.datagrabbers import ( # noqa: E402
20
19
  SPMAuditoryTestingDataGrabber,
@@ -25,9 +24,6 @@ from junifer.testing.datagrabbers import ( # noqa: E402
25
24
  PARCELLATION = "Schaefer100x17"
26
25
 
27
26
 
28
- @pytest.mark.skipif(
29
- _check_ants() is False, reason="requires ANTs to be in PATH"
30
- )
31
27
  def test_compute() -> None:
32
28
  """Test HurstExponent compute()."""
33
29
  with SPMAuditoryTestingDataGrabber() as dg:
@@ -40,19 +36,15 @@ def test_compute() -> None:
40
36
  # Compute the marker
41
37
  feature_map = marker.fit_transform(element_data)
42
38
  # Assert the dimension of timeseries
43
- assert feature_map["BOLD"]["complexity"]["data"].ndim == 2
39
+ assert feature_map["BOLD"]["data"].ndim == 2
44
40
 
45
41
 
46
42
  def test_get_output_type() -> None:
47
43
  """Test HurstExponent get_output_type()."""
48
- assert "vector" == HurstExponent(
49
- parcellation=PARCELLATION
50
- ).get_output_type(input_type="BOLD", output_feature="complexity")
44
+ marker = HurstExponent(parcellation=PARCELLATION)
45
+ assert marker.get_output_type("BOLD") == "vector"
51
46
 
52
47
 
53
- @pytest.mark.skipif(
54
- _check_ants() is False, reason="requires ANTs to be in PATH"
55
- )
56
48
  def test_store(tmp_path: Path) -> None:
57
49
  """Test HurstExponent store().
58
50
 
@@ -13,7 +13,6 @@ pytest.importorskip("neurokit2")
13
13
 
14
14
  from junifer.datareader import DefaultDataReader # noqa: E402
15
15
  from junifer.markers.complexity import MultiscaleEntropyAUC # noqa: E402
16
- from junifer.pipeline.utils import _check_ants # noqa: E402
17
16
  from junifer.storage import SQLiteFeatureStorage # noqa: E402
18
17
  from junifer.testing.datagrabbers import ( # noqa: E402
19
18
  SPMAuditoryTestingDataGrabber,
@@ -24,9 +23,6 @@ from junifer.testing.datagrabbers import ( # noqa: E402
24
23
  PARCELLATION = "Schaefer100x17"
25
24
 
26
25
 
27
- @pytest.mark.skipif(
28
- _check_ants() is False, reason="requires ANTs to be in PATH"
29
- )
30
26
  def test_compute() -> None:
31
27
  """Test MultiscaleEntropyAUC compute()."""
32
28
  with SPMAuditoryTestingDataGrabber() as dg:
@@ -39,19 +35,15 @@ def test_compute() -> None:
39
35
  # Compute the marker
40
36
  feature_map = marker.fit_transform(element_data)
41
37
  # Assert the dimension of timeseries
42
- assert feature_map["BOLD"]["complexity"]["data"].ndim == 2
38
+ assert feature_map["BOLD"]["data"].ndim == 2
43
39
 
44
40
 
45
41
  def test_get_output_type() -> None:
46
42
  """Test MultiscaleEntropyAUC get_output_type()."""
47
- assert "vector" == MultiscaleEntropyAUC(
48
- parcellation=PARCELLATION
49
- ).get_output_type(input_type="BOLD", output_feature="complexity")
43
+ marker = MultiscaleEntropyAUC(parcellation=PARCELLATION)
44
+ assert marker.get_output_type("BOLD") == "vector"
50
45
 
51
46
 
52
- @pytest.mark.skipif(
53
- _check_ants() is False, reason="requires ANTs to be in PATH"
54
- )
55
47
  def test_store(tmp_path: Path) -> None:
56
48
  """Test MultiscaleEntropyAUC store().
57
49
 
@@ -13,7 +13,6 @@ pytest.importorskip("neurokit2")
13
13
 
14
14
  from junifer.datareader import DefaultDataReader # noqa: E402
15
15
  from junifer.markers.complexity import PermEntropy # noqa: E402
16
- from junifer.pipeline.utils import _check_ants # noqa: E402
17
16
  from junifer.storage import SQLiteFeatureStorage # noqa: E402
18
17
  from junifer.testing.datagrabbers import ( # noqa: E402
19
18
  SPMAuditoryTestingDataGrabber,
@@ -24,9 +23,6 @@ from junifer.testing.datagrabbers import ( # noqa: E402
24
23
  PARCELLATION = "Schaefer100x17"
25
24
 
26
25
 
27
- @pytest.mark.skipif(
28
- _check_ants() is False, reason="requires ANTs to be in PATH"
29
- )
30
26
  def test_compute() -> None:
31
27
  """Test PermEntropy compute()."""
32
28
  with SPMAuditoryTestingDataGrabber() as dg:
@@ -39,19 +35,15 @@ def test_compute() -> None:
39
35
  # Compute the marker
40
36
  feature_map = marker.fit_transform(element_data)
41
37
  # Assert the dimension of timeseries
42
- assert feature_map["BOLD"]["complexity"]["data"].ndim == 2
38
+ assert feature_map["BOLD"]["data"].ndim == 2
43
39
 
44
40
 
45
41
  def test_get_output_type() -> None:
46
42
  """Test PermEntropy get_output_type()."""
47
- assert "vector" == PermEntropy(parcellation=PARCELLATION).get_output_type(
48
- input_type="BOLD", output_feature="complexity"
49
- )
43
+ marker = PermEntropy(parcellation=PARCELLATION)
44
+ assert marker.get_output_type("BOLD") == "vector"
50
45
 
51
46
 
52
- @pytest.mark.skipif(
53
- _check_ants() is False, reason="requires ANTs to be in PATH"
54
- )
55
47
  def test_store(tmp_path: Path) -> None:
56
48
  """Test PermEntropy store().
57
49
 
@@ -14,7 +14,6 @@ pytest.importorskip("neurokit2")
14
14
 
15
15
  from junifer.datareader import DefaultDataReader # noqa: E402
16
16
  from junifer.markers.complexity import RangeEntropy # noqa: E402
17
- from junifer.pipeline.utils import _check_ants # noqa: E402
18
17
  from junifer.storage import SQLiteFeatureStorage # noqa: E402
19
18
  from junifer.testing.datagrabbers import ( # noqa: E402
20
19
  SPMAuditoryTestingDataGrabber,
@@ -25,9 +24,6 @@ from junifer.testing.datagrabbers import ( # noqa: E402
25
24
  PARCELLATION = "Schaefer100x17"
26
25
 
27
26
 
28
- @pytest.mark.skipif(
29
- _check_ants() is False, reason="requires ANTs to be in PATH"
30
- )
31
27
  def test_compute() -> None:
32
28
  """Test RangeEntropy compute()."""
33
29
  with SPMAuditoryTestingDataGrabber() as dg:
@@ -40,19 +36,15 @@ def test_compute() -> None:
40
36
  # Compute the marker
41
37
  feature_map = marker.fit_transform(element_data)
42
38
  # Assert the dimension of timeseries
43
- assert feature_map["BOLD"]["complexity"]["data"].ndim == 2
39
+ assert feature_map["BOLD"]["data"].ndim == 2
44
40
 
45
41
 
46
42
  def test_get_output_type() -> None:
47
43
  """Test RangeEntropy get_output_type()."""
48
- assert "vector" == RangeEntropy(parcellation=PARCELLATION).get_output_type(
49
- input_type="BOLD", output_feature="complexity"
50
- )
44
+ marker = RangeEntropy(parcellation=PARCELLATION)
45
+ assert marker.get_output_type("BOLD") == "vector"
51
46
 
52
47
 
53
- @pytest.mark.skipif(
54
- _check_ants() is False, reason="requires ANTs to be in PATH"
55
- )
56
48
  def test_store(tmp_path: Path) -> None:
57
49
  """Test RangeEntropy store().
58
50
 
@@ -14,7 +14,6 @@ pytest.importorskip("neurokit2")
14
14
 
15
15
  from junifer.datareader import DefaultDataReader # noqa: E402
16
16
  from junifer.markers.complexity import RangeEntropyAUC # noqa: E402
17
- from junifer.pipeline.utils import _check_ants # noqa: E402
18
17
  from junifer.storage import SQLiteFeatureStorage # noqa: E402
19
18
  from junifer.testing.datagrabbers import ( # noqa: E402
20
19
  SPMAuditoryTestingDataGrabber,
@@ -25,9 +24,6 @@ from junifer.testing.datagrabbers import ( # noqa: E402
25
24
  PARCELLATION = "Schaefer100x17"
26
25
 
27
26
 
28
- @pytest.mark.skipif(
29
- _check_ants() is False, reason="requires ANTs to be in PATH"
30
- )
31
27
  def test_compute() -> None:
32
28
  """Test RangeEntropyAUC compute()."""
33
29
  with SPMAuditoryTestingDataGrabber() as dg:
@@ -40,19 +36,15 @@ def test_compute() -> None:
40
36
  # Compute the marker
41
37
  feature_map = marker.fit_transform(element_data)
42
38
  # Assert the dimension of timeseries
43
- assert feature_map["BOLD"]["complexity"]["data"].ndim == 2
39
+ assert feature_map["BOLD"]["data"].ndim == 2
44
40
 
45
41
 
46
42
  def test_get_output_type() -> None:
47
43
  """Test RangeEntropyAUC get_output_type()."""
48
- assert "vector" == RangeEntropyAUC(
49
- parcellation=PARCELLATION
50
- ).get_output_type(input_type="BOLD", output_feature="complexity")
44
+ marker = RangeEntropyAUC(parcellation=PARCELLATION)
45
+ assert marker.get_output_type("BOLD") == "vector"
51
46
 
52
47
 
53
- @pytest.mark.skipif(
54
- _check_ants() is False, reason="requires ANTs to be in PATH"
55
- )
56
48
  def test_store(tmp_path: Path) -> None:
57
49
  """Test RangeEntropyAUC store().
58
50
 
@@ -13,7 +13,6 @@ pytest.importorskip("neurokit2")
13
13
 
14
14
  from junifer.datareader import DefaultDataReader # noqa: E402
15
15
  from junifer.markers.complexity import SampleEntropy # noqa: E402
16
- from junifer.pipeline.utils import _check_ants # noqa: E402
17
16
  from junifer.storage import SQLiteFeatureStorage # noqa: E402
18
17
  from junifer.testing.datagrabbers import ( # noqa: E402
19
18
  SPMAuditoryTestingDataGrabber,
@@ -24,9 +23,6 @@ from junifer.testing.datagrabbers import ( # noqa: E402
24
23
  PARCELLATION = "Schaefer100x17"
25
24
 
26
25
 
27
- @pytest.mark.skipif(
28
- _check_ants() is False, reason="requires ANTs to be in PATH"
29
- )
30
26
  def test_compute() -> None:
31
27
  """Test SampleEntropy compute()."""
32
28
  with SPMAuditoryTestingDataGrabber() as dg:
@@ -39,19 +35,15 @@ def test_compute() -> None:
39
35
  # Compute the marker
40
36
  feature_map = marker.fit_transform(element_data)
41
37
  # Assert the dimension of timeseries
42
- assert feature_map["BOLD"]["complexity"]["data"].ndim == 2
38
+ assert feature_map["BOLD"]["data"].ndim == 2
43
39
 
44
40
 
45
41
  def test_get_output_type() -> None:
46
42
  """Test SampleEntropy get_output_type()."""
47
- assert "vector" == SampleEntropy(
48
- parcellation=PARCELLATION
49
- ).get_output_type(input_type="BOLD", output_feature="complexity")
43
+ marker = SampleEntropy(parcellation=PARCELLATION)
44
+ assert marker.get_output_type("BOLD") == "vector"
50
45
 
51
46
 
52
- @pytest.mark.skipif(
53
- _check_ants() is False, reason="requires ANTs to be in PATH"
54
- )
55
47
  def test_store(tmp_path: Path) -> None:
56
48
  """Test SampleEntropy store().
57
49