Skip to content

Commit 3bb6c14

Browse files
authored
Merge pull request #34 from Peyman-N/deleting_globals
Resolve Issue of Global Object Dependency by Implementing Local Collection in Converter Function
2 parents 262feaa + 1dcf54d commit 3bb6c14

File tree

3 files changed

+95
-76
lines changed

3 files changed

+95
-76
lines changed

bids2openminds/converter.py

+21-19
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
from warnings import warn
22
from bids import BIDSLayout, BIDSValidator
3+
from openminds import Collection
34
import os
45
import click
56
from . import main
67
from . import utility
7-
from . import globals
88

9-
def convert(input_path, output_path=None, multiple_files=False, include_empty_properties=False):
9+
10+
def convert(input_path, output_path=None, multiple_files=False, include_empty_properties=False):
1011
if not (os.path.isdir(input_path)):
1112
raise NotADirectoryError(
1213
f"The input directory is not valid, you have specified {input_path} which is not a directory."
1314
)
1415
# if not(BIDSValidator().is_bids(input_path)):
1516
# raise NotADirectoryError(f"The input directory is not valid, you have specified {input_path} which is not a BIDS directory.")
16-
17+
collection = Collection()
1718
bids_layout = BIDSLayout(input_path)
1819

1920
layout_df = bids_layout.to_df()
@@ -27,42 +28,43 @@ def convert(input_path, output_path=None, multiple_files=False, include_empty_pr
2728

2829
dataset_description = utility.read_json(dataset_description_path.iat[0, 0])
2930

30-
[subjects_dict, subject_state_dict, subjects_list] = main.create_subjects(subjects_id, layout_df, bids_layout)
31+
[subjects_dict, subject_state_dict, subjects_list] = main.create_subjects(
32+
subjects_id, layout_df, bids_layout, collection)
3133

32-
[files_list, file_repository] = main.create_file(layout_df, input_path)
34+
[files_list, file_repository] = main.create_file(
35+
layout_df, input_path, collection)
3336

3437
dataset_version = main.create_dataset_version(
35-
bids_layout, dataset_description, layout_df, subjects_list, file_repository
36-
)
38+
bids_layout, dataset_description, layout_df, subjects_list, file_repository, collection)
39+
40+
dataset = main.create_dataset(
41+
dataset_description, dataset_version, collection)
3742

38-
dataset = main.create_dataset(dataset_description, dataset_version)
39-
40-
failures = globals.collection.validate(ignore=["required", "value"])
43+
failures = collection.validate(ignore=["required", "value"])
4144
assert len(failures) == 0
4245

4346
if output_path is None:
4447
if multiple_files:
45-
output_path=os.path.join(input_path, "openminds")
48+
output_path = os.path.join(input_path, "openminds")
4649
else:
4750
output_path = os.path.join(input_path, "openminds.jsonld")
4851

49-
globals.collection.save(output_path,individual_files=multiple_files,include_empty_properties=include_empty_properties)
52+
collection.save(output_path, individual_files=multiple_files,
53+
include_empty_properties=include_empty_properties)
5054

5155
print(f"Conversion was successful, the openMINDS file is in {output_path}")
5256

5357

54-
5558
@click.command()
56-
@click.argument("input-path", type=click.Path(file_okay=False,exists=True))
57-
@click.option("-o","--output-path",default=None,type=click.Path(file_okay=True,writable=True),help="The output path or filename for OpenMINDS file/files.")
58-
@click.option("--single-file","multiple_files",flag_value=False,default=False,help="Save the entire collection into a single file (default).")
59-
@click.option("--multiple-files","multiple_files",flag_value=True,help="Each node is saved into a separate file within the specified directory. 'output-path' if specified, must be a directory.")
60-
@click.option("-e","--include-empty-properties",is_flag=True,default=False,help="Whether to include empty properties in the final file.")
59+
@click.argument("input-path", type=click.Path(file_okay=False, exists=True))
60+
@click.option("-o", "--output-path", default=None, type=click.Path(file_okay=True, writable=True), help="The output path or filename for OpenMINDS file/files.")
61+
@click.option("--single-file", "multiple_files", flag_value=False, default=False, help="Save the entire collection into a single file (default).")
62+
@click.option("--multiple-files", "multiple_files", flag_value=True, help="Each node is saved into a separate file within the specified directory. 'output-path' if specified, must be a directory.")
63+
@click.option("-e", "--include-empty-properties", is_flag=True, default=False, help="Whether to include empty properties in the final file.")
6164
def convert_click(input_path, output_path, multiple_files, include_empty_properties):
6265
convert(input_path, output_path, multiple_files, include_empty_properties)
6366

6467

65-
6668
if __name__ == "__main__":
6769
input_path = input("Enter the BIDS directory path: ")
6870
convert(input_path)

bids2openminds/globals.py

-4
This file was deleted.

bids2openminds/main.py

+74-53
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,23 @@
1010

1111
from .utility import table_filter, pd_table_value, file_hash, file_storage_size
1212
from .mapping import bids2openminds_instance
13-
from . import globals
1413

1514

1615
def create_techniques(layout_df):
1716
suffixs = layout_df["suffix"].unique().tolist()
1817
techniques = []
1918
not_techniques_index = ["description", "participants", "events"]
2019
for suffix in suffixs:
21-
#excluding the None and non thechnique indexes
20+
# excluding the None and non thechnique indexes
2221
if not (pd.isna(suffix) or (suffix in not_techniques_index)):
23-
openminds_techniques_cache=bids2openminds_instance(suffix, "MAP_2_TECHNIQUES")
24-
#Excluding the suffixs that are not in the library or flagged as non technique suffixes
22+
openminds_techniques_cache = bids2openminds_instance(
23+
suffix, "MAP_2_TECHNIQUES")
24+
# Excluding the suffixs that are not in the library or flagged as non technique suffixes
2525
if not pd.isna(openminds_techniques_cache):
2626
techniques.extend(openminds_techniques_cache)
2727
else:
28-
warn(f"The {suffix} suffix is currently considered an auxiliary file for already existing techniques or a non technique file.")
28+
warn(
29+
f"The {suffix} suffix is currently considered an auxiliary file for already existing techniques or a non technique file.")
2930

3031
return techniques or None
3132

@@ -35,12 +36,13 @@ def create_approaches(layout_df):
3536
approaches = set([])
3637
for datatype in datatypes:
3738
if not (pd.isna(datatype)):
38-
approaches.update(bids2openminds_instance(datatype, "MAP_2_EXPERIMENTAL_APPROACHES"))
39+
approaches.update(bids2openminds_instance(
40+
datatype, "MAP_2_EXPERIMENTAL_APPROACHES"))
3941

4042
return list(approaches) or None
4143

4244

43-
def create_dataset_version(bids_layout, dataset_description, layout_df, studied_specimens, file_repository):
45+
def create_dataset_version(bids_layout, dataset_description, layout_df, studied_specimens, file_repository, collection):
4446

4547
# Fetch the dataset type from dataset description file
4648

@@ -49,7 +51,8 @@ def create_dataset_version(bids_layout, dataset_description, layout_df, studied_
4951
# Fetch the digitalIdentifier from dataset description file
5052

5153
if "DatasetDOI" in dataset_description:
52-
digital_identifier = omcore.DOI(identifier=dataset_description["DatasetDOI"])
54+
digital_identifier = omcore.DOI(
55+
identifier=dataset_description["DatasetDOI"])
5356
else:
5457
digital_identifier = None
5558

@@ -92,32 +95,34 @@ def create_dataset_version(bids_layout, dataset_description, layout_df, studied_
9295
techniques=techniques,
9396
how_to_cite=how_to_cite,
9497
repository=file_repository,
95-
#other_contributions=other_contribution # needs to be a Contribution object
98+
# other_contributions=other_contribution # needs to be a Contribution object
9699
# version_identifier
97100
)
98101

99-
globals.collection.add(dataset_version)
102+
collection.add(dataset_version)
100103

101104
return dataset_version
102105

103106

104-
def create_dataset(dataset_description, dataset_version):
107+
def create_dataset(dataset_description, dataset_version, collection):
105108

106109
if "DatasetDOI" in dataset_description:
107-
digital_identifier = omcore.DOI(identifier=dataset_description["DatasetDOI"])
110+
digital_identifier = omcore.DOI(
111+
identifier=dataset_description["DatasetDOI"])
108112
else:
109113
digital_identifier = None
110114

111115
dataset = omcore.Dataset(
112-
digital_identifier=digital_identifier, full_name=dataset_description["Name"], has_versions=dataset_version
116+
digital_identifier=digital_identifier, full_name=dataset_description[
117+
"Name"], has_versions=dataset_version
113118
)
114119

115-
globals.collection.add(dataset)
120+
collection.add(dataset)
116121

117122
return dataset
118123

119124

120-
def create_subjects(subject_id, layout_df, layout):
125+
def create_subjects(subject_id, layout_df, layout, collection):
121126

122127
sessions = layout.get_sessions()
123128
subjects_dict = {}
@@ -126,30 +131,33 @@ def create_subjects(subject_id, layout_df, layout):
126131

127132
# Find the participants files in the files table
128133
participants_paths = table_filter(layout_df, "participants")
129-
if participants_paths.empty:
130-
#creating emphty subjects just based on file structure
134+
if participants_paths.empty:
135+
# creating emphty subjects just based on file structure
131136
for subject in subject_id:
132137
subject_name = f"sub-{subject}"
133138
state_cache_dict = {}
134139
state_cache = []
135-
#dealing with condition that have no seasion
140+
# dealing with condition that have no seasion
136141
if not sessions:
137142
state = omcore.SubjectState(
138-
internal_identifier=f"Studied state {subject_name}".strip(),
143+
internal_identifier=f"Studied state {subject_name}".strip(
144+
),
139145
lookup_label=f"Studied state {subject_name}".strip()
140146
)
141-
globals.collection.add(state)
147+
collection.add(state)
142148
state_cache_dict[""] = state
143149
state_cache.append(state)
144150
else:
145-
#create a subject state for each state
151+
# create a subject state for each state
146152
for session in sessions:
147-
if not(table_filter(table_filter(layout_df,session,"session"),subject,"subject").empty):
153+
if not (table_filter(table_filter(layout_df, session, "session"), subject, "subject").empty):
148154
state = omcore.SubjectState(
149-
internal_identifier=f"Studied state {subject_name} {session}".strip(),
150-
lookup_label=f"Studied state {subject_name} {session}".strip()
155+
internal_identifier=f"Studied state {subject_name} {session}".strip(
156+
),
157+
lookup_label=f"Studied state {subject_name} {session}".strip(
158+
)
151159
)
152-
globals.collection.add(state)
160+
collection.add(state)
153161
state_cache_dict[f"{session}"] = state
154162
state_cache.append(state)
155163
subject_state_dict[f"{subject}"] = state_cache_dict
@@ -159,20 +167,21 @@ def create_subjects(subject_id, layout_df, layout):
159167
)
160168
subjects_dict[f"{subject}"] = subject_cache
161169
subjects_list.append(subject_cache)
162-
globals.collection.add(subject_cache)
163-
170+
collection.add(subject_cache)
164171

165172
return subjects_dict, subject_state_dict, subjects_list
166173

167-
168174
# Select the tsv file of the table
169-
participants_path_tsv = pd_table_value(table_filter(participants_paths, ".tsv", "extension"), "path")
170-
participants_path_json = pd_table_value(table_filter(participants_paths, ".json", "extension"), "path")
175+
participants_path_tsv = pd_table_value(table_filter(
176+
participants_paths, ".tsv", "extension"), "path")
177+
participants_path_json = pd_table_value(table_filter(
178+
participants_paths, ".json", "extension"), "path")
171179

172180
participants_table = pd.read_csv(participants_path_tsv, sep="\t", header=0)
173181
for subject in subject_id:
174182
subject_name = f"sub-{subject}"
175-
data_subject = table_filter(participants_table, subject_name, "participant_id")
183+
data_subject = table_filter(
184+
participants_table, subject_name, "participant_id")
176185
state_cache_dict = {}
177186
state_cache = []
178187
if not sessions:
@@ -181,74 +190,84 @@ def create_subjects(subject_id, layout_df, layout):
181190
value=pd_table_value(data_subject, "age"),
182191
unit=controlled_terms.UnitOfMeasurement.year
183192
),
184-
handedness=bids2openminds_instance(pd_table_value(data_subject, "handedness"), "MAP_2_HANDEDNESS", is_list=False),
193+
handedness=bids2openminds_instance(pd_table_value(
194+
data_subject, "handedness"), "MAP_2_HANDEDNESS", is_list=False),
185195
internal_identifier=f"Studied state {subject_name}".strip(),
186196
lookup_label=f"Studied state {subject_name}".strip()
187-
)
188-
globals.collection.add(state)
197+
)
198+
collection.add(state)
189199
state_cache_dict[""] = state
190200
state_cache.append(state)
191201
else:
192202
for session in sessions:
193-
if not(table_filter(table_filter(layout_df,session,"session"),subject,"subject").empty):
203+
if not (table_filter(table_filter(layout_df, session, "session"), subject, "subject").empty):
194204
state = omcore.SubjectState(
195205
age=omcore.QuantitativeValue(
196206
value=pd_table_value(data_subject, "age"),
197207
unit=controlled_terms.UnitOfMeasurement.year
198208
),
199-
handedness=bids2openminds_instance(pd_table_value(data_subject, "handedness"), "MAP_2_HANDEDNESS", is_list=False),
200-
internal_identifier=f"Studied state {subject_name} {session}".strip(),
201-
lookup_label=f"Studied state {subject_name} {session}".strip()
209+
handedness=bids2openminds_instance(pd_table_value(
210+
data_subject, "handedness"), "MAP_2_HANDEDNESS", is_list=False),
211+
internal_identifier=f"Studied state {subject_name} {session}".strip(
212+
),
213+
lookup_label=f"Studied state {subject_name} {session}".strip(
214+
)
202215
)
203-
globals.collection.add(state)
216+
collection.add(state)
204217
state_cache_dict[f"{session}"] = state
205218
state_cache.append(state)
206219
subject_state_dict[f"{subject}"] = state_cache_dict
207220
subject_cache = omcore.Subject(
208-
biological_sex=bids2openminds_instance(pd_table_value(data_subject, "sex"), "MAP_2_SEX", is_list=False),
221+
biological_sex=bids2openminds_instance(pd_table_value(
222+
data_subject, "sex"), "MAP_2_SEX", is_list=False),
209223
lookup_label=f"{subject_name}",
210224
internal_identifier=f"{subject_name}",
211225
# TODO species should default to homo sapiens
212-
species=bids2openminds_instance(pd_table_value(data_subject, "species"), "MAP_2_SPECIES", is_list=False),
226+
species=bids2openminds_instance(pd_table_value(
227+
data_subject, "species"), "MAP_2_SPECIES", is_list=False),
213228
studied_states=state_cache
214229
)
215230
subjects_dict[f"{subject}"] = subject_cache
216231
subjects_list.append(subject_cache)
217-
globals.collection.add(subject_cache)
232+
collection.add(subject_cache)
218233

219234
return subjects_dict, subject_state_dict, subjects_list
220235

221236

222-
def create_file(layout_df, BIDS_path):
237+
def create_file(layout_df, BIDS_path, collection):
223238

224239
BIDS_directory_path = os.path.dirname(BIDS_path)
225240
file_repository = omcore.FileRepository()
226-
globals.collection.add(file_repository)
241+
collection.add(file_repository)
227242
files_list = []
228243
for index, file in layout_df.iterrows():
229244
file_format = None
230245
content_description = None
231246
data_types = None
232247
extension = file["extension"]
233248
path = file["path"]
234-
iri=IRI(pathlib.Path(path).as_uri())
235-
name=os.path.basename(path)
249+
iri = IRI(pathlib.Path(path).as_uri())
250+
name = os.path.basename(path)
236251
hashes = file_hash(path)
237252
storage_size = file_storage_size(path)
238253
if pd.isna(file["subject"]):
239254
if file["suffix"] == "participants":
240255
if extension == ".json":
241256
content_description = f"A JSON metadata file of participants TSV."
242-
data_types = controlled_terms.DataType.by_name("associative array")
243-
file_format = omcore.ContentType.by_name("application/json")
257+
data_types = controlled_terms.DataType.by_name(
258+
"associative array")
259+
file_format = omcore.ContentType.by_name(
260+
"application/json")
244261
elif extension == [".tsv"]:
245262
content_description = f"A metadata table for participants."
246263
data_types = controlled_terms.DataType.by_name("table")
247-
file_format = omcore.ContentType.by_name("text/tab-separated-values")
264+
file_format = omcore.ContentType.by_name(
265+
"text/tab-separated-values")
248266
else:
249267
if extension == ".json":
250268
content_description = f"A JSON metadata file for {file['suffix']} of subject {file['subject']}"
251-
data_types = controlled_terms.DataType.by_name("associative array")
269+
data_types = controlled_terms.DataType.by_name(
270+
"associative array")
252271
file_format = omcore.ContentType.by_name("application/json")
253272
elif extension in [".nii", ".nii.gz"]:
254273
content_description = f"Data file for {file['suffix']} of subject {file['subject']}"
@@ -257,8 +276,10 @@ def create_file(layout_df, BIDS_path):
257276
elif extension == [".tsv"]:
258277
if file["suffix"] == "events":
259278
content_description = f"Event file for {file['suffix']} of subject {file['subject']}"
260-
data_types = controlled_terms.DataType.by_name("event sequence")
261-
file_format = omcore.ContentType.by_name("text/tab-separated-values")
279+
data_types = controlled_terms.DataType.by_name(
280+
"event sequence")
281+
file_format = omcore.ContentType.by_name(
282+
"text/tab-separated-values")
262283
file = omcore.File(
263284
iri=iri,
264285
content_description=content_description,
@@ -271,7 +292,7 @@ def create_file(layout_df, BIDS_path):
271292
# special_usage_role
272293
storage_size=storage_size,
273294
)
274-
globals.collection.add(file)
295+
collection.add(file)
275296
files_list.append(file)
276297

277298
return files_list, file_repository

0 commit comments

Comments
 (0)