Skip to content

Commit 0eed021

Browse files
committed
migrate bids importer from str to path
1 parent 5017156 commit 0eed021

File tree

12 files changed

+108
-99
lines changed

12 files changed

+108
-99
lines changed

python/lib/imaging_lib/bids/dataset.py

Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import os
21
import re
32
from collections.abc import Iterator
43
from functools import cached_property
4+
from pathlib import Path
55

66
from bids import BIDSLayout
77

88
from lib.imaging_lib.bids.dataset_description import BidsDatasetDescription
99
from lib.imaging_lib.bids.tsv_participants import BidsTsvParticipant, read_bids_participants_tsv_file
1010
from lib.imaging_lib.bids.tsv_scans import BidsTsvScan, read_bids_scans_tsv_file
11-
from lib.imaging_lib.nifti import find_dir_nifti_names
11+
from lib.imaging_lib.nifti import find_dir_nifti_files
1212
from lib.util.fs import replace_file_extension, search_dir_file_with_regex
1313
from lib.util.iter import find
1414

@@ -18,10 +18,10 @@
1818

1919

2020
class BIDSDataset:
21-
path: str
21+
path: Path
2222
validate: bool
2323

24-
def __init__(self, bids_path: str, validate: bool):
24+
def __init__(self, bids_path: Path, validate: bool):
2525
self.path = bids_path
2626
self.validate = validate
2727

@@ -48,12 +48,12 @@ def subjects(self) -> list['BIDSSubject']:
4848

4949
subjects: list[BIDSSubject] = []
5050

51-
for file in os.scandir(self.path):
51+
for file in self.path.iterdir():
5252
subject_match = re.match(r'sub-([a-zA-Z0-9]+)', file.name)
5353
if subject_match is None:
5454
continue
5555

56-
if not os.path.isdir(file):
56+
if not file.is_dir():
5757
continue
5858

5959
subject_label = subject_match.group(1)
@@ -68,8 +68,8 @@ def get_dataset_description(self) -> 'BidsDatasetDescription | None':
6868
does contains incorrect data.
6969
"""
7070

71-
dataset_description_path = os.path.join(self.path, 'dataset_description.json')
72-
if not os.path.exists(dataset_description_path):
71+
dataset_description_path = self.path / 'dataset_description.json'
72+
if not dataset_description_path.exists():
7373
return None
7474

7575
return BidsDatasetDescription(dataset_description_path)
@@ -81,8 +81,8 @@ def tsv_participants(self) -> dict[str, BidsTsvParticipant] | None:
8181
present. This property might raise an exception if the file is present but incorrect.
8282
"""
8383

84-
tsv_participants_path = os.path.join(self.path, 'participants.tsv')
85-
if not os.path.exists(tsv_participants_path):
84+
tsv_participants_path = self.path / 'participants.tsv'
85+
if not tsv_participants_path.exists():
8686
return None
8787

8888
return read_bids_participants_tsv_file(tsv_participants_path)
@@ -143,13 +143,13 @@ def layout(self) -> BIDSLayout:
143143

144144
class BIDSSubject:
145145
root_dataset: BIDSDataset
146+
path: Path
146147
label: str
147-
path: str
148148

149149
def __init__(self, root_dataset: BIDSDataset, label: str):
150150
self.root_dataset = root_dataset
151151
self.label = label
152-
self.path = os.path.join(self.root_dataset.path, f'sub-{self.label}')
152+
self.path = self.root_dataset.path / f'sub-{self.label}'
153153

154154
@property
155155
def data_types(self) -> Iterator['BIDSDataType']:
@@ -169,8 +169,8 @@ def sessions(self) -> list['BIDSSession']:
169169

170170
sessions: list[BIDSSession] = []
171171

172-
for file in os.scandir(self.path):
173-
if not os.path.isdir(file):
172+
for file in self.path.iterdir():
173+
if not file.is_dir():
174174
continue
175175

176176
session_match = re.match(r'ses-([a-zA-Z0-9]+)', file.name)
@@ -195,23 +195,19 @@ def get_session(self, session_label: str) -> 'BIDSSession | None':
195195

196196
class BIDSSession:
197197
subject: BIDSSubject
198+
path: Path
198199
label: str | None
199-
path: str
200-
tsv_scans_path: str | None
200+
tsv_scans_path: Path | None
201201

202202
def __init__(self, subject: BIDSSubject, label: str | None):
203203
self.subject = subject
204204
self.label = label
205-
if label is None:
206-
self.path = self.subject.path
205+
if label is not None:
206+
self.path = subject.path / f'ses-{self.label}'
207207
else:
208-
self.path = os.path.join(self.subject.path, f'ses-{self.label}')
208+
self.path = subject.path
209209

210-
tsv_scans_name = search_dir_file_with_regex(self.path, r'scans.tsv$')
211-
if tsv_scans_name is not None:
212-
self.tsv_scans_path = os.path.join(self.path, tsv_scans_name)
213-
else:
214-
self.tsv_scans_path = None
210+
self.tsv_scans_path = search_dir_file_with_regex(self.path, r'scans.tsv$')
215211

216212
@property
217213
def root_dataset(self) -> BIDSDataset:
@@ -230,8 +226,8 @@ def data_types(self) -> list['BIDSDataType']:
230226

231227
data_types: list[BIDSDataType] = []
232228

233-
for file in os.scandir(self.path):
234-
if not os.path.isdir(file):
229+
for file in self.path.iterdir():
230+
if not file.is_dir():
235231
continue
236232

237233
data_types.append(BIDSDataType(self, file.name))
@@ -264,13 +260,15 @@ def get_tsv_scan(self, file_name: str) -> 'BidsTsvScan | None':
264260

265261
class BIDSDataType:
266262
session: BIDSSession
267-
name: str
268-
path: str
263+
path: Path
269264

270265
def __init__(self, session: BIDSSession, name: str):
271266
self.session = session
272-
self.name = name
273-
self.path = os.path.join(self.session.path, self.name)
267+
self.path = session.path / name
268+
269+
@property
270+
def name(self) -> str:
271+
return self.path.name
274272

275273
@property
276274
def root_dataset(self) -> BIDSDataset:
@@ -288,29 +286,31 @@ def niftis(self) -> list['BIDSNifti']:
288286

289287
niftis: list[BIDSNifti] = []
290288

291-
for nifti_name in find_dir_nifti_names(self.path):
292-
niftis.append(BIDSNifti(self, nifti_name))
289+
for nifti_path in find_dir_nifti_files(self.path):
290+
niftis.append(BIDSNifti(self, nifti_path.name))
293291

294292
return niftis
295293

296294

297295
class BIDSNifti:
298296
data_type: BIDSDataType
299-
name: str
300-
path: str
297+
path: Path
301298
suffix: str | None
302299

303300
def __init__(self, data_type: BIDSDataType, name: str):
304301
self.data_type = data_type
305-
self.path = os.path.join(self.data_type.path, name)
306-
self.name = name
302+
self.path = data_type.path / name
307303

308304
suffix_match = re.search(r'_([a-zA-Z0-9]+)\.nii(\.gz)?$', self.name)
309305
if suffix_match is not None:
310306
self.suffix = suffix_match.group(1)
311307
else:
312308
self.suffix = None
313309

310+
@property
311+
def name(self) -> str:
312+
return self.path.name
313+
314314
@property
315315
def root_dataset(self) -> BIDSDataset:
316316
return self.data_type.root_dataset
@@ -323,38 +323,38 @@ def subject(self) -> BIDSSubject:
323323
def session(self) -> BIDSSession:
324324
return self.data_type.session
325325

326-
def get_json_path(self) -> str | None:
326+
def get_json_path(self) -> Path | None:
327327
"""
328328
Get the JSON sidecar file path of this NIfTI file if it exists.
329329
"""
330330

331331
json_name = replace_file_extension(self.name, 'json')
332-
json_path = os.path.join(self.data_type.path, json_name)
333-
if not os.path.exists(json_path):
332+
json_path = self.data_type.path / json_name
333+
if not json_path.exists():
334334
return None
335335

336336
return json_path
337337

338-
def get_bval_path(self) -> str | None:
338+
def get_bval_path(self) -> Path | None:
339339
"""
340340
Get the BVAL file path of this NIfTI file if it exists.
341341
"""
342342

343343
bval_name = replace_file_extension(self.name, 'bval')
344-
bval_path = os.path.join(self.data_type.path, bval_name)
345-
if not os.path.exists(bval_path):
344+
bval_path = self.data_type.path / bval_name
345+
if not bval_path.exists():
346346
return None
347347

348348
return bval_path
349349

350-
def get_bvec_path(self) -> str | None:
350+
def get_bvec_path(self) -> Path | None:
351351
"""
352352
Get the BVEC file path of this NIfTI file if it exists.
353353
"""
354354

355355
bvec_name = replace_file_extension(self.name, 'bvec')
356-
bvec_path = os.path.join(self.data_type.path, bvec_name)
357-
if not os.path.exists(bvec_path):
356+
bvec_path = self.data_type.path / bvec_name
357+
if not bvec_path.exists():
358358
return None
359359

360360
return bvec_path

python/lib/imaging_lib/bids/dataset_description.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import json
2+
from pathlib import Path
23
from typing import Any
34

45

@@ -31,7 +32,7 @@ class BidsDatasetDescription:
3132
The BIDS dataset description JSON data.
3233
"""
3334

34-
def __init__(self, dataset_descrption_path: str):
35+
def __init__(self, dataset_descrption_path: Path):
3536
"""
3637
Read a BIDS dataset description file, or raise an exception if that file contains incorrect
3738
data.

python/lib/imaging_lib/bids/json.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import json
2+
from pathlib import Path
23
from typing import Any
34

45
from lib.config import get_patient_id_dicom_header_config
@@ -41,7 +42,7 @@ def get_bids_json_session_info(env: Env, bids_json: dict[str, Any]) -> SessionIn
4142
return get_session_info(env, patient_id, scanner_info)
4243

4344

44-
def add_bids_json_file_parameters(env: Env, bids_json_path: str, rel_json_path: str, file_parameters: dict[str, Any]):
45+
def add_bids_json_file_parameters(env: Env, bids_json_path: Path, rel_json_path: str, file_parameters: dict[str, Any]):
4546
"""
4647
Read a BIDS JSON sidecar file and add its parameters to a LORIS file parameters dictionary.
4748
"""

python/lib/imaging_lib/bids/tsv_participants.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import csv
22
import re
33
from dataclasses import dataclass
4+
from pathlib import Path
45

56
from dateutil.parser import ParserError, parse
67

@@ -21,7 +22,7 @@ class BidsTsvParticipant:
2122
project: str | None = None
2223

2324

24-
def read_bids_participants_tsv_file(participants_tsv_path: str) -> dict[str, BidsTsvParticipant]:
25+
def read_bids_participants_tsv_file(participants_tsv_path: Path) -> dict[str, BidsTsvParticipant]:
2526
"""
2627
Read the `participants.tsv` file of a BIDS dataset and get the participant rows indexed by
2728
participant ID. Raise an exception if the `participants.tsv` file is incorrect.
@@ -42,7 +43,7 @@ def read_bids_participants_tsv_file(participants_tsv_path: str) -> dict[str, Bid
4243

4344
def read_bids_participants_tsv_row(
4445
tsv_participant_row: dict[str, str],
45-
participants_tsv_path: str,
46+
participants_tsv_path: Path,
4647
) -> BidsTsvParticipant:
4748
"""
4849
Read a `participants.tsv` row, or raise an exception if that row is incorrect.
@@ -70,7 +71,7 @@ def read_bids_participants_tsv_row(
7071
)
7172

7273

73-
def write_bids_participants_tsv_file(tsv_participants: dict[str, BidsTsvParticipant], participants_file_path: str):
74+
def write_bids_participants_tsv_file(tsv_participants: dict[str, BidsTsvParticipant], participants_file_path: Path):
7475
"""
7576
Write the `participants.tsv` file based from a set of participant rows.
7677
"""

python/lib/imaging_lib/bids/tsv_scans.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import csv
22
from dataclasses import dataclass
33
from datetime import datetime
4+
from pathlib import Path
45
from typing import Any
56

67
from dateutil.parser import ParserError, parse
@@ -19,7 +20,7 @@ class BidsTsvScan:
1920
age_at_scan : str | None
2021

2122

22-
def read_bids_scans_tsv_file(scans_tsv_path: str) -> dict[str, BidsTsvScan]:
23+
def read_bids_scans_tsv_file(scans_tsv_path: Path) -> dict[str, BidsTsvScan]:
2324
"""
2425
Read a `scans.tsv` file of a BIDS dataset and get the scan rows indexed by file name. Raise an
2526
exception if the `scans.tsv` file is incorrect.
@@ -38,7 +39,7 @@ def read_bids_scans_tsv_file(scans_tsv_path: str) -> dict[str, BidsTsvScan]:
3839
return tsv_scans
3940

4041

41-
def read_bids_scans_tsv_row(tsv_scan_row: dict[str, str], scans_tsv_path: str) -> BidsTsvScan:
42+
def read_bids_scans_tsv_row(tsv_scan_row: dict[str, str], scans_tsv_path: Path) -> BidsTsvScan:
4243
"""
4344
Read a `scans.tsv` row, or raise an exception if that row is incorrect.
4445
"""
@@ -57,7 +58,7 @@ def read_bids_scans_tsv_row(tsv_scan_row: dict[str, str], scans_tsv_path: str) -
5758
)
5859

5960

60-
def write_bids_scans_tsv_file(tsv_scans: dict[str, BidsTsvScan], scans_tsv_path: str):
61+
def write_bids_scans_tsv_file(tsv_scans: dict[str, BidsTsvScan], scans_tsv_path: Path):
6162
"""
6263
Write the `scans.tsv` file from a set of scan rows.
6364
"""
@@ -115,7 +116,7 @@ def _read_age_at_scan(tsv_scan_row: dict[str, str]) -> str | None:
115116
return None
116117

117118

118-
def add_scan_tsv_file_parameters(scan_tsv: BidsTsvScan, scans_tsv_path: str, file_parameters: dict[str, Any]):
119+
def add_scan_tsv_file_parameters(scan_tsv: BidsTsvScan, scans_tsv_path: Path, file_parameters: dict[str, Any]):
119120
"""
120121
Add a scans.tsv file and row parameters to a LORIS file parameters dictionary.
121122
"""

python/lib/imaging_lib/nifti.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import os
21
from collections.abc import Iterator
2+
from pathlib import Path
33
from typing import Any, cast
44

55
import nibabel as nib
66

77

8-
def add_nifti_file_parameters(nifti_path: str, nifti_file_hash: str, file_parameters: dict[str, Any]):
8+
def add_nifti_file_parameters(nifti_path: Path, nifti_file_hash: str, file_parameters: dict[str, Any]):
99
"""
1010
Read a NIfTI image and add some of its properties to the file parameters.
1111
"""
@@ -34,11 +34,11 @@ def add_nifti_file_parameters(nifti_path: str, nifti_file_hash: str, file_parame
3434
file_parameters['file_blake2b_hash'] = nifti_file_hash
3535

3636

37-
def find_dir_nifti_names(dir_path: str) -> Iterator[str]:
37+
def find_dir_nifti_files(dir_path: Path) -> Iterator[Path]:
3838
"""
39-
Iterate over the names of the NIfTI files found in a directory.
39+
Iterate over the Path objects of the NIfTI files found in a directory.
4040
"""
4141

42-
for file_name in os.listdir(dir_path):
43-
if file_name.endswith(('.nii', '.nii.gz')):
44-
yield file_name
42+
for item_path in dir_path.iterdir():
43+
if item_path.name.endswith(('.nii', '.nii.gz')):
44+
yield item_path

0 commit comments

Comments
 (0)