brkraw-sordino 0.1.3__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.
@@ -0,0 +1,164 @@
1
+ __meta__:
2
+ name: "sordino_info"
3
+ version: "0.2.0"
4
+ description: "Scan info spec for SORDINO, based on brkraw scan.yaml plus tuning parameters."
5
+ category: "info_spec"
6
+ transforms_source: "./utils.py"
7
+
8
+ Method:
9
+ sources:
10
+ - file: acqp
11
+ key: ACQ_method
12
+ transform: strip_jcamp_string
13
+
14
+ Protocol:
15
+ sources:
16
+ - file: acqp
17
+ key: ACQ_protocol_name
18
+ transform: strip_jcamp_string
19
+
20
+ Dim:
21
+ sources:
22
+ - file: acqp
23
+ key: ACQ_dim
24
+
25
+ DimDesc:
26
+ sources:
27
+ - file: acqp
28
+ key: ACQ_dim_desc
29
+ transform: convert_to_list
30
+
31
+ NumEchoes:
32
+ sources:
33
+ - file: acqp
34
+ key: NECHOES
35
+
36
+ TE (ms):
37
+ sources:
38
+ - file: method
39
+ key: PVM_EchoTime
40
+ - file: acqp
41
+ key: ACQ_echo_time
42
+ transform: convert_to_list
43
+
44
+ TR (ms):
45
+ sources:
46
+ - file: method
47
+ key: PVM_RepetitionTime
48
+ - file: method
49
+ key: RepetitionTime
50
+ - file: acqp
51
+ key: ACQ_repetition_time
52
+ transform: convert_to_list
53
+
54
+ FlipAngle (degree):
55
+ sources:
56
+ - file: acqp
57
+ key: ACQ_flip_angle
58
+
59
+ Shape:
60
+ sources:
61
+ - file: method
62
+ key: PVM_Matrix
63
+ transform: convert_to_list
64
+
65
+ FOV (mm):
66
+ sources:
67
+ - file: method
68
+ key: PVM_Fov
69
+ transform: convert_to_list
70
+
71
+ NumSlicePack:
72
+ sources:
73
+ - file: method
74
+ key: PVM_NSPacks
75
+
76
+ SliceOrient:
77
+ sources:
78
+ - file: method
79
+ key: PVM_SPackArrSliceOrient
80
+ transform: convert_to_list
81
+
82
+ ReadOrient:
83
+ sources:
84
+ - file: method
85
+ key: PVM_SPackArrReadOrient
86
+ transform: convert_to_list
87
+
88
+ SliceDistance (mm):
89
+ sources:
90
+ - file: method
91
+ key: PVM_SPackArrSliceDistance
92
+ transform: convert_to_list
93
+
94
+ SliceGap (mm):
95
+ sources:
96
+ - file: method
97
+ key: PVM_SPackArrSliceGap
98
+ transform: convert_to_list
99
+
100
+ NumAverage:
101
+ sources:
102
+ - file: method
103
+ key: PVM_NAverages
104
+
105
+ NumRepeat:
106
+ sources:
107
+ - file: method
108
+ key: PVM_NRepetitions
109
+
110
+ EncNReceivers:
111
+ sources:
112
+ - file: method
113
+ key: PVM_EncNReceivers
114
+
115
+ NPoints:
116
+ sources:
117
+ - file: method
118
+ key: NPoints
119
+
120
+ NPro:
121
+ sources:
122
+ - file: method
123
+ key: NPro
124
+
125
+ EffBandwidth (Hz):
126
+ sources:
127
+ - file: method
128
+ key: PVM_EffSWh
129
+
130
+ OverSampling:
131
+ sources:
132
+ - file: method
133
+ key: OverSampling
134
+
135
+ AcqDelayTotal (us):
136
+ sources:
137
+ - file: method
138
+ key: AcqDelayTotal
139
+
140
+ UnderSampling:
141
+ sources:
142
+ - file: method
143
+ key: ProUnderSampling
144
+
145
+ SpatialResolution (mm):
146
+ sources:
147
+ - file: method
148
+ key: PVM_SpatResol
149
+ transform: convert_to_list
150
+
151
+ HalfAcquisition:
152
+ sources:
153
+ - file: method
154
+ key: HalfAcquisition
155
+
156
+ UseOrigin:
157
+ sources:
158
+ - file: method
159
+ key: UseOrigin
160
+
161
+ Reorder:
162
+ sources:
163
+ - file: method
164
+ key: Reorder
@@ -0,0 +1,167 @@
1
+ __meta__:
2
+ name: "sordino_metadata"
3
+ version: "0.1.0"
4
+ description: "Draft metadata mapping for ZTE-based fMRI (BEP proposal alignment)."
5
+ category: "metadata_spec"
6
+ transforms_source: "./utils.py"
7
+
8
+ RepetitionTime:
9
+ sources:
10
+ - file: method
11
+ key: PVM_RepetitionTime
12
+ - file: method
13
+ key: RepetitionTime
14
+ transform: ms_to_s
15
+
16
+ EchoTime:
17
+ sources:
18
+ - file: method
19
+ key: PVM_EchoTime
20
+ transform: ms_to_s
21
+
22
+ FlipAngle:
23
+ sources:
24
+ - file: acqp
25
+ key: ACQ_flip_angle
26
+ transform: first_float
27
+
28
+ MRAcquisitionType:
29
+ inputs:
30
+ value:
31
+ const: "3D"
32
+ transform: value_only
33
+
34
+ Manufacturer:
35
+ inputs:
36
+ value:
37
+ const: "Bruker"
38
+ transform: value_only
39
+
40
+ SequenceName:
41
+ sources:
42
+ - file: method
43
+ key: Method
44
+ transform: strip_bruker_string
45
+
46
+ ZTETechnique:
47
+ inputs:
48
+ method:
49
+ sources:
50
+ - file: method
51
+ key: Method
52
+ - file: method
53
+ key: PULPROG
54
+ transform: infer_zte_technique
55
+
56
+ ZTETrajectoryType:
57
+ sources:
58
+ - file: method
59
+ key: PVM_TrajType
60
+ - file: method
61
+ key: PVM_EncTraj
62
+ - file: method
63
+ key: TrajType
64
+ transform: normalize_trajectory
65
+
66
+ ZTEReadoutPoints:
67
+ sources:
68
+ - file: method
69
+ key: NPoints
70
+ transform: first_int
71
+
72
+ ZTEProjections:
73
+ sources:
74
+ - file: method
75
+ key: NPro
76
+ transform: first_int
77
+
78
+ ZTEOverSampling:
79
+ sources:
80
+ - file: method
81
+ key: OverSampling
82
+ transform: first_float
83
+
84
+ ZTEEffectiveBandwidth:
85
+ sources:
86
+ - file: method
87
+ key: PVM_EffSWh
88
+ transform: first_float
89
+
90
+ ZTEAcqDelayTotal:
91
+ sources:
92
+ - file: method
93
+ key: AcqDelayTotal
94
+ transform: first_float
95
+
96
+ ZTEUnderSampling:
97
+ sources:
98
+ - file: method
99
+ key: ProUnderSampling
100
+ transform: first_float
101
+
102
+ ZTEReceiverChannels:
103
+ sources:
104
+ - file: method
105
+ key: PVM_EncNReceivers
106
+ transform: first_int
107
+
108
+ ReconMatrix:
109
+ sources:
110
+ - file: method
111
+ key: PVM_Matrix
112
+ transform: to_int_list
113
+
114
+ FieldOfView:
115
+ sources:
116
+ - file: method
117
+ key: PVM_Fov
118
+ transform: to_float_list
119
+
120
+ SpatialResolution:
121
+ sources:
122
+ - file: method
123
+ key: PVM_SpatResol
124
+ transform: to_float_list
125
+
126
+ SliceOrientation:
127
+ sources:
128
+ - file: method
129
+ key: PVM_SPackArrSliceOrient
130
+ transform: convert_to_list
131
+
132
+ ReadoutOrientation:
133
+ sources:
134
+ - file: method
135
+ key: PVM_SPackArrReadOrient
136
+ transform: convert_to_list
137
+
138
+ ConversionSoftware:
139
+ inputs:
140
+ value:
141
+ const: "brkraw-sordino"
142
+ transform: value_only
143
+
144
+ ConversionSoftwareVersion:
145
+ inputs:
146
+ value:
147
+ const: "brkraw-sordino"
148
+ transform: plugin_version
149
+
150
+ ConversionMethod:
151
+ inputs:
152
+ package:
153
+ const: "brkraw-sordino"
154
+ name:
155
+ const: "brkraw-sordino"
156
+ transform: conversion_method
157
+
158
+ SourceDataset:
159
+ inputs:
160
+ value:
161
+ const: null
162
+ transform: source_dataset_env
163
+
164
+ ScanIdentifier:
165
+ inputs:
166
+ scan_id: "$scan_id"
167
+ transform: scan_id_to_string
@@ -0,0 +1,44 @@
1
+ __meta__:
2
+ name: "prune4recon"
3
+ version: "0.1.0"
4
+ description: >
5
+ De-identification pruner spec for Bruker ParaVision datasets that preserves the
6
+ FID file for reconstruction purposes. The spec drops the subject file and redacts
7
+ potential PII from JCAMP-DX parameters. Supports template variables:
8
+ $subject_id, $subject_name, $study_id.
9
+ category: "pruner_spec"
10
+
11
+ mode: "keep"
12
+
13
+ files:
14
+ - "method"
15
+ - "acqp"
16
+ - "reco"
17
+ - "rawdata.job0"
18
+ - "visu_pars"
19
+ - "2dseq"
20
+
21
+ update_params:
22
+ acqp:
23
+ ACQ_operator: ""
24
+ ACQ_institution: ""
25
+ ACQ_station: ""
26
+ ACQ_time: "<00:00:00 01 Jan 2000>"
27
+ ACQ_abs_time: "0"
28
+
29
+ visu_pars:
30
+ VisuInstitution: ""
31
+ VisuSubjectId: "$subject_id"
32
+ VisuSubjectName: "$subject_name"
33
+ VisuStudyId: "$study_id"
34
+ VisuStudyDate: "<00:00:00 01 Jan 2000>"
35
+ VisuStudyUid: "<1.2.3.4.5>"
36
+ VisuSeriesUid: "<1.2.3.4.5.1>"
37
+ VisuFrameUid: "<1.2.3.4.5.2>"
38
+ VisuSystemOrderNumber: "<>"
39
+ VisuInstitution: "<>"
40
+
41
+ reco:
42
+ RECO_base_image_uid: "<1.2.3.4.5.6>"
43
+
44
+ add_root: true
@@ -0,0 +1,103 @@
1
+ __meta__:
2
+ name: "sordino_recon"
3
+ version: "0.1.0"
4
+ description: "Parameter mapping for SORDINO reconstruction."
5
+ category: "recon_spec"
6
+ transforms_source: "./utils.py"
7
+
8
+ SliceOrientation:
9
+ sources:
10
+ - file: method
11
+ key: PVM_SPackArrSliceOrient
12
+ transform: first
13
+
14
+ ReadoutOrientation:
15
+ sources:
16
+ - file: method
17
+ key: PVM_SPackArrReadOrient
18
+ transform: first
19
+
20
+ GradientOrientation:
21
+ sources:
22
+ - file: method
23
+ key: PVM_SPackArrGradOrient
24
+ transform: squeeze_ndarray
25
+
26
+ EncNReceivers:
27
+ sources:
28
+ - file: method
29
+ key: PVM_EncNReceivers
30
+ transform: first_int
31
+
32
+ NPoints:
33
+ sources:
34
+ - file: method
35
+ key: NPoints
36
+ transform: first_int
37
+
38
+ NPro:
39
+ sources:
40
+ - file: method
41
+ key: NPro
42
+ transform: first_int
43
+
44
+ RepetitionTime_ms:
45
+ sources:
46
+ - file: method
47
+ key: RepetitionTime
48
+ - file: method
49
+ key: PVM_RepetitionTime
50
+ transform: first_float
51
+
52
+ EffBandwidth_Hz:
53
+ sources:
54
+ - file: method
55
+ key: PVM_EffSWh
56
+ transform: first_float
57
+
58
+ OverSampling:
59
+ sources:
60
+ - file: method
61
+ key: OverSampling
62
+ transform: first_float
63
+
64
+ AcqDelayTotal_us:
65
+ sources:
66
+ - file: method
67
+ key: AcqDelayTotal
68
+ transform: first_float
69
+
70
+ NRepetitions:
71
+ sources:
72
+ - file: method
73
+ key: PVM_NRepetitions
74
+ transform: first_int
75
+
76
+ Matrix:
77
+ sources:
78
+ - file: method
79
+ key: PVM_Matrix
80
+
81
+ UnderSampling:
82
+ sources:
83
+ - file: method
84
+ key: ProUnderSampling
85
+ transform: first_float
86
+
87
+ HalfAcquisition:
88
+ sources:
89
+ - file: method
90
+ key: HalfAcquisition
91
+ transform: to_bool
92
+
93
+ UseOrigin:
94
+ sources:
95
+ - file: method
96
+ key: UseOrigin
97
+ transform: to_bool
98
+
99
+ Reorder:
100
+ sources:
101
+ - file: method
102
+ key: Reorder
103
+ transform: to_bool
@@ -0,0 +1,212 @@
1
+ """Transform helpers for brkraw-sordino metadata and info mapping."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import re
7
+ import numpy as np
8
+ from typing import Any, Optional, cast
9
+ from importlib import metadata
10
+
11
+
12
+ def squeeze_ndarray(value: np.ndarray) -> np.ndarray:
13
+ return value.squeeze()
14
+
15
+
16
+ def strip_bruker_string(value: Any) -> Any:
17
+ if value is None:
18
+ return None
19
+ text = str(value).strip()
20
+ if text.startswith("<") and text.endswith(">"):
21
+ text = text[1:-1]
22
+ return text.strip()
23
+
24
+
25
+ def strip_jcamp_string(value: Optional[str]) -> str:
26
+ if value is None:
27
+ return "Unknown"
28
+ text = str(value).strip()
29
+ if text.startswith("<") and text.endswith(">"):
30
+ text = text[1:-1]
31
+ text = re.sub(r"\^+", " ", text)
32
+ return " ".join(text.split())
33
+
34
+
35
+ def ensure_list(value: Any) -> Optional[list]:
36
+ if value is None:
37
+ return None
38
+ if isinstance(value, (list, tuple)):
39
+ return list(value)
40
+ return [value]
41
+
42
+
43
+ def convert_to_list(value: Any):
44
+ if value is None:
45
+ return []
46
+ if hasattr(value, "tolist"):
47
+ return cast(Any, value).tolist()
48
+ if isinstance(value, (list, tuple)):
49
+ return list(value)
50
+ return [value]
51
+
52
+
53
+ def first(value: Any) -> Any:
54
+ if value is None:
55
+ return None
56
+ if isinstance(value, (list, tuple)) and value:
57
+ return value[0]
58
+ try:
59
+ import numpy as np
60
+ if isinstance(value, np.ndarray) and value.size:
61
+ return value.flat[0]
62
+ except Exception:
63
+ pass
64
+ return value
65
+
66
+
67
+ def first_float(value: Any) -> Optional[float]:
68
+ val = first(value)
69
+ if val is None:
70
+ return None
71
+ try:
72
+ return float(val)
73
+ except Exception:
74
+ return None
75
+
76
+
77
+ def first_int(value: Any) -> Optional[int]:
78
+ val = first(value)
79
+ if val is None:
80
+ return None
81
+ try:
82
+ return int(val)
83
+ except Exception:
84
+ return None
85
+
86
+
87
+ def to_float_list(value: Any) -> Optional[list]:
88
+ values = ensure_list(value)
89
+ if values is None:
90
+ return None
91
+ out = []
92
+ for item in values:
93
+ try:
94
+ out.append(float(item))
95
+ except Exception:
96
+ return None
97
+ return out
98
+
99
+
100
+ def to_int_list(value: Any) -> Optional[list]:
101
+ values = ensure_list(value)
102
+ if values is None:
103
+ return None
104
+ out = []
105
+ for item in values:
106
+ try:
107
+ out.append(int(item))
108
+ except Exception:
109
+ return None
110
+ return out
111
+
112
+
113
+ def to_bool(value: Any) -> bool:
114
+ if isinstance(value, str):
115
+ return value.strip().lower() in {"yes", "true", "1", "on"}
116
+ return bool(value)
117
+
118
+
119
+ def ms_to_s(value: Any) -> Optional[float]:
120
+ val = first_float(value)
121
+ if val is None:
122
+ return None
123
+ return val * 1e-3
124
+
125
+
126
+ def dwell_time_seconds(*, sw_hz: Any = None, dwell_us: Any = None) -> Optional[float]:
127
+ sw = first_float(sw_hz)
128
+ if sw:
129
+ return 1.0 / sw
130
+ dwell = first_float(dwell_us)
131
+ if dwell is None:
132
+ return None
133
+ return float(dwell) * 1e-6 * 2.0
134
+
135
+
136
+ def lower_string(value: Any) -> Optional[str]:
137
+ if value is None:
138
+ return None
139
+ return str(value).strip().lower()
140
+
141
+
142
+ def _normalize_text(value: Any) -> Optional[str]:
143
+ if value is None:
144
+ return None
145
+ text = str(value).strip()
146
+ return " ".join(text.split()) if text else None
147
+
148
+
149
+ def infer_zte_technique(*, method: Any = None, sequence: Any = None) -> Optional[str]:
150
+ text = _normalize_text(method) or _normalize_text(sequence)
151
+ if not text:
152
+ return None
153
+ lowered = text.lower()
154
+ if "sordino" in lowered:
155
+ return "SORDINO"
156
+ if "swift" in lowered:
157
+ return "MB-SWIFT"
158
+ if "zte" in lowered:
159
+ return "ZTE"
160
+ return None
161
+
162
+
163
+ def normalize_trajectory(value: Any) -> Optional[str]:
164
+ text = _normalize_text(value)
165
+ if not text:
166
+ return None
167
+ lowered = text.lower()
168
+ mapping = {
169
+ "radial": "radial",
170
+ "spiral": "spiral",
171
+ "cartesian": "cartesian",
172
+ "cart": "cartesian",
173
+ "cones": "cones",
174
+ "rosette": "rosette",
175
+ }
176
+ for key, target in mapping.items():
177
+ if key in lowered:
178
+ return target
179
+ return lowered
180
+
181
+
182
+ def value_only(*, value: Any) -> Any:
183
+ return value
184
+
185
+
186
+ def plugin_version(*, value: Any) -> str:
187
+ pkg = str(value or "brkraw-sordino")
188
+ try:
189
+ return metadata.version(pkg)
190
+ except Exception:
191
+ return "unknown"
192
+
193
+
194
+ def conversion_method(*, package: Any = None, name: Any = None) -> str:
195
+ pkg = str(package or name or "brkraw-sordino")
196
+ base = str(name or pkg)
197
+ try:
198
+ version = metadata.version(pkg)
199
+ except Exception:
200
+ version = None
201
+ return f"{base} v{version}" if version else base
202
+
203
+
204
+ def source_dataset_env(*, value: Any) -> Optional[str]:
205
+ _ = value
206
+ return os.environ.get("BRKRAW_SOURCE_DATASET")
207
+
208
+
209
+ def scan_id_to_string(*, scan_id: Any) -> Optional[str]:
210
+ if scan_id is None:
211
+ return None
212
+ return str(scan_id)