brukerapi 0.4.1__tar.gz → 0.4.2__tar.gz

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 (54) hide show
  1. {brukerapi-0.4.1/brukerapi.egg-info → brukerapi-0.4.2}/PKG-INFO +4 -4
  2. brukerapi-0.4.2/brukerapi/__init__.py +1 -0
  3. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/cli.py +13 -13
  4. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/config/properties_2dseq_core.json +24 -17
  5. brukerapi-0.4.2/brukerapi/config/properties_2dseq_custom.json +184 -0
  6. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/config/properties_fid_core.json +111 -59
  7. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/config/properties_rawdata_core.json +40 -21
  8. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/config/properties_traj_core.json +4 -4
  9. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/dataset.py +340 -40
  10. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/folders.py +62 -24
  11. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/jcampdx.py +129 -92
  12. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/mergers.py +2 -2
  13. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/schemas.py +120 -8
  14. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/splitters.py +66 -42
  15. brukerapi-0.4.2/brukerapi/utils.py +97 -0
  16. {brukerapi-0.4.1 → brukerapi-0.4.2/brukerapi.egg-info}/PKG-INFO +4 -4
  17. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi.egg-info/SOURCES.txt +5 -0
  18. brukerapi-0.4.2/brukerapi.egg-info/requires.txt +11 -0
  19. {brukerapi-0.4.1 → brukerapi-0.4.2}/pyproject.toml +9 -5
  20. brukerapi-0.4.2/test/test_api.py +194 -0
  21. {brukerapi-0.4.1 → brukerapi-0.4.2}/test/test_dataset.py +77 -11
  22. {brukerapi-0.4.1 → brukerapi-0.4.2}/test/test_folders.py +39 -0
  23. brukerapi-0.4.2/test/test_frames.py +96 -0
  24. brukerapi-0.4.2/test/test_geometry.py +283 -0
  25. {brukerapi-0.4.1 → brukerapi-0.4.2}/test/test_jcampdx.py +286 -16
  26. brukerapi-0.4.2/test/test_latent_conformance.py +246 -0
  27. {brukerapi-0.4.1 → brukerapi-0.4.2}/test/test_paths.py +46 -0
  28. {brukerapi-0.4.1 → brukerapi-0.4.2}/test/test_property_configs.py +29 -19
  29. brukerapi-0.4.2/test/test_raw_layouts.py +293 -0
  30. brukerapi-0.4.2/test/test_split.py +149 -0
  31. brukerapi-0.4.1/brukerapi/__init__.py +0 -1
  32. brukerapi-0.4.1/brukerapi/config/properties_2dseq_custom.json +0 -289
  33. brukerapi-0.4.1/brukerapi/utils.py +0 -57
  34. brukerapi-0.4.1/brukerapi.egg-info/requires.txt +0 -13
  35. brukerapi-0.4.1/test/test_split.py +0 -50
  36. {brukerapi-0.4.1 → brukerapi-0.4.2}/LICENSE +0 -0
  37. {brukerapi-0.4.1 → brukerapi-0.4.2}/MANIFEST.in +0 -0
  38. {brukerapi-0.4.1 → brukerapi-0.4.2}/README.rst +0 -0
  39. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/config/properties_fid_custom.json +0 -0
  40. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/config/properties_rawdata_custom.json +0 -0
  41. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/config/properties_traj_custom.json +0 -0
  42. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/data.py +0 -0
  43. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/exceptions.py +0 -0
  44. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi/paths.py +0 -0
  45. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi.egg-info/dependency_links.txt +0 -0
  46. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi.egg-info/entry_points.txt +0 -0
  47. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi.egg-info/not-zip-safe +0 -0
  48. {brukerapi-0.4.1 → brukerapi-0.4.2}/brukerapi.egg-info/top_level.txt +0 -0
  49. {brukerapi-0.4.1 → brukerapi-0.4.2}/setup.cfg +0 -0
  50. {brukerapi-0.4.1 → brukerapi-0.4.2}/test/test_exceptions.py +0 -0
  51. {brukerapi-0.4.1 → brukerapi-0.4.2}/test/test_random_access.py +0 -0
  52. {brukerapi-0.4.1 → brukerapi-0.4.2}/test/test_rawdata.py +0 -0
  53. {brukerapi-0.4.1 → brukerapi-0.4.2}/test/test_trajectory.py +0 -0
  54. {brukerapi-0.4.1 → brukerapi-0.4.2}/test/test_utils.py +0 -0
@@ -1,23 +1,23 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brukerapi
3
- Version: 0.4.1
3
+ Version: 0.4.2
4
4
  Summary: Bruker API
5
5
  Author-email: Tomas Psorn <tomaspsorn@isibrno.cz>, Jiri Vitous <vitous@isibrno.cz>
6
6
  Maintainer-email: Jiri Vitous <vitous@isibrno.cz>
7
7
  License: MIT
8
8
  Project-URL: Homepage, https://github.com/isi-nmr/brukerapi-python
9
9
  Project-URL: Download, https://github.com/isi-nmr/brukerapi-python/releases/latest
10
- Requires-Python: >=3.8
10
+ Requires-Python: >=3.10
11
11
  Description-Content-Type: text/x-rst
12
12
  License-File: LICENSE
13
- Requires-Dist: numpy<2; python_version < "3.9"
14
- Requires-Dist: numpy>=1.26.0; python_version >= "3.9"
13
+ Requires-Dist: numpy>=2.1; python_version >= "3.10"
15
14
  Requires-Dist: pyyaml
16
15
  Provides-Extra: dev
17
16
  Requires-Dist: pytest; extra == "dev"
18
17
  Requires-Dist: zenodo_get; extra == "dev"
19
18
  Requires-Dist: ruff==0.16.0; extra == "dev"
20
19
  Requires-Dist: pytest-cov; extra == "dev"
20
+ Requires-Dist: pyrefly; extra == "dev"
21
21
  Dynamic: license-file
22
22
 
23
23
  brukerapi-python
@@ -0,0 +1 @@
1
+ __all__ = ["dataset", "exceptions", "folders", "jcampdx", "utils"]
@@ -112,9 +112,9 @@ def split(args):
112
112
  dataset = Dataset(args.path_in)
113
113
 
114
114
  if args.slice_package:
115
- SlicePackageSplitter().split(dataset, write=True)
115
+ SlicePackageSplitter().split(dataset, write=True, path_out=args.path_out)
116
116
  elif args.frame_group:
117
- FrameGroupSplitter(args.frame_group).split(dataset, write=True)
117
+ FrameGroupSplitter(args.frame_group).split(dataset, write=True, path_out=args.path_out)
118
118
 
119
119
 
120
120
  def report(args):
@@ -124,25 +124,25 @@ def report(args):
124
124
  :return:
125
125
  """
126
126
  input = Path(args.input)
127
-
128
- if args.output is None:
129
- output = None
130
- else:
131
- output = Path(args.output)
127
+ output = None if args.output is None else Path(args.output)
132
128
 
133
129
  if input.is_dir():
134
130
  # folder in-place
135
131
  if output is None:
136
- Folder(input).report(format_=args.format, props=args.props, verbose=args.verbose)
137
- elif output.is_dir():
138
- # folder to folder
139
- Folder(input).report(path_out=output, format_=args.format, props=args.props, verbose=args.verbose)
132
+ Folder(str(input)).report(format_=args.format, props=args.props, verbose=args.verbose)
133
+ else:
134
+ # folder to folder -- an output folder that does not exist yet is
135
+ # created rather than silently matching no branch and exiting 0
136
+ output.mkdir(parents=True, exist_ok=True)
137
+ Folder(str(input)).report(path_out=output, format_=args.format, props=args.props, verbose=args.verbose)
140
138
  # dataset in-place
141
139
  elif output is None:
142
- Dataset(input, add_parameters=["subject"]).report(props=args.props, verbose=args.verbose)
140
+ Dataset(input, add_parameters=["subject"]).report(props=args.props, verbose=args.verbose, format_=args.format)
143
141
  # dataset to folder, or dataset to file
144
142
  else:
145
- Dataset(input, add_parameters=["subject"]).report(path=output, props=args.props, verbose=args.verbose)
143
+ if not output.suffix:
144
+ output.mkdir(parents=True, exist_ok=True)
145
+ Dataset(input, add_parameters=["subject"]).report(path=output, props=args.props, verbose=args.verbose, format_=args.format)
146
146
 
147
147
 
148
148
  def filter(args):
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "pv_version": [
3
3
  {
4
- "cmd": "#VisuCreatorVersion[1:-1]",
5
- "conditions": []
4
+ "cmd": "#VisuCreatorVersion[1:-1].split(';')[0]",
5
+ "conditions": [],
6
+ "comment": "spec 7.1: VisuCreator/VisuCreatorVersion are semicolon-separated lists; the first creator is the one that wrote the dataset"
6
7
  }
7
8
  ],
8
9
  "numpy_dtype": [
@@ -67,8 +68,12 @@
67
68
  "conditions": ["#RECO_wordtype in ['_32BIT_SGN_INT','_16BIT_SGN_INT','_32BIT_FLOAT','_8BIT_UNSGN_INT']", "#RECO_byte_order in ['littleEndian','bigEndian']"]
68
69
  },
69
70
  {
70
- "cmd": "np.dtype({'ip_int':'int32','ip_short':'int16','ip_float':'float32'}[#DATTYPE]).newbyteorder('<')",
71
- "conditions": ["#DATTYPE in ['ip_int','ip_short','ip_float']"]
71
+ "cmd": "np.dtype(DATTYPE_WORD_TYPES[str(#DATTYPE)]).newbyteorder('>' if int(np.atleast_1d(#PR_STA)[15]) else '<')",
72
+ "conditions": ["str(#DATTYPE) in DATTYPE_WORD_TYPES", "len(np.atleast_1d(#PR_STA))>15"]
73
+ },
74
+ {
75
+ "cmd": "np.dtype(DATTYPE_WORD_TYPES[str(#DATTYPE)]).newbyteorder('<')",
76
+ "conditions": ["str(#DATTYPE) in DATTYPE_WORD_TYPES"]
72
77
  }
73
78
  ],
74
79
  "shape_frames": [
@@ -118,11 +123,17 @@
118
123
  "conditions": []
119
124
  },
120
125
  {
121
- "cmd": "#RECO_size.tuple",
122
- "conditions": []
126
+ "cmd": "(int(#IM_SIX), int(#IM_SIY))",
127
+ "conditions": [],
128
+ "comment": "spec 8: IM_SIX/IM_SIY are the in-plane matrix written after transposition; IM_SIZ is the number of frames, which shape_frames already counts"
129
+ },
130
+ {
131
+ "cmd": "transposed_size(#RECO_size.tuple, #RECO_transposition)",
132
+ "conditions": [],
133
+ "comment": "spec 6.9: RECO_size still refers to the non-transposed ordering, so the stored frame shape is RECO_size with the recorded exchange applied"
123
134
  },
124
135
  {
125
- "cmd": "tuple(size for size in (int(#IM_SIX), int(#IM_SIY), int(#IM_SIZ)) if size > 1)",
136
+ "cmd": "#RECO_size.tuple",
126
137
  "conditions": []
127
138
  }
128
139
  ],
@@ -150,14 +161,9 @@
150
161
  ],
151
162
  "num_slice_packages": [
152
163
  {
153
- "cmd": "len(#VisuCoreSlicePacksSlices.nested)",
154
- "conditions": []
155
- },
156
- {
157
- "cmd": "1",
164
+ "cmd": "len(@slice_packages_index())",
158
165
  "conditions": []
159
166
  }
160
-
161
167
  ],
162
168
  "slope": [
163
169
  {
@@ -165,8 +171,9 @@
165
171
  "conditions": []
166
172
  },
167
173
  {
168
- "cmd": "#RECO_map_slope.array",
169
- "conditions": []
174
+ "cmd": "1.0 / #RECO_map_slope.array",
175
+ "conditions": [],
176
+ "comment": "spec 3.4: real = pixel / RECO_map_slope + RECO_map_offset, so VisuCoreDataSlope = 1 / RECO_map_slope. Multiplying instead of dividing makes values slope^2 too small"
170
177
  }
171
178
  ],
172
179
  "offset": [
@@ -181,11 +188,11 @@
181
188
  ],
182
189
  "dim_type": [
183
190
  {
184
- "cmd": "#VisuCoreDimDesc.list + ['spatial',] + #VisuFGOrderDesc.sub_list(1)",
191
+ "cmd": "#VisuCoreDimDesc.list + ['frame',] + #VisuFGOrderDesc.sub_list(1)",
185
192
  "conditions": ["@is_single_slice==True"]
186
193
  },
187
194
  {
188
- "cmd": "#VisuCoreDimDesc.list + ['spatial',]",
195
+ "cmd": "#VisuCoreDimDesc.list + ['frame',]",
189
196
  "conditions": ["@is_single_slice==True"]
190
197
  },
191
198
  {
@@ -0,0 +1,184 @@
1
+ {
2
+ "subj_id": [
3
+ {
4
+ "cmd": "#VisuSubjectName[1:-1]",
5
+ "conditions": [
6
+ ]
7
+ },
8
+ {
9
+ "cmd": "''",
10
+ "conditions": [
11
+ ]
12
+ }
13
+ ],
14
+ "study_id": [
15
+ {
16
+ "cmd": "str(#VisuStudyNumber)",
17
+ "conditions": [
18
+ ]
19
+ },
20
+ {
21
+ "cmd": "''",
22
+ "conditions": [
23
+ ]
24
+ }
25
+ ],
26
+ "exp_id": [
27
+ {
28
+ "cmd": "@path.parents[2].name",
29
+ "conditions": [
30
+ ]
31
+ },
32
+ {
33
+ "cmd": "''",
34
+ "conditions": [
35
+ ]
36
+ }
37
+ ],
38
+ "proc_id": [
39
+ {
40
+ "cmd": "@path.parents[0].name",
41
+ "conditions": [
42
+ ]
43
+ },
44
+ {
45
+ "cmd": "''",
46
+ "conditions": [
47
+ ]
48
+ }
49
+ ],
50
+ "id": [
51
+ {
52
+ "cmd": "'2DSEQ_{}_{}_{}_{}'.format(@exp_id, @proc_id, @subj_id, @study_id)",
53
+ "conditions": [
54
+ ]
55
+ }
56
+ ],
57
+ "extent": [
58
+ {
59
+ "cmd": "np.array([#PVM_VoxArrSize[0,0] * #VisuAcqSize[1], #PVM_VoxArrSize[0,1] * #VisuAcqSize[2], #VisuCoreFrameThickness])",
60
+ "conditions": [
61
+ "@pv_version.split('.')[0]=='5'",
62
+ "#VisuCoreDimDesc.list[0]=='spectroscopic'",
63
+ "#VisuCoreDimDesc.list[1]=='spatial'",
64
+ "#VisuCoreDimDesc.list[2]=='spatial'"]
65
+ },
66
+ {
67
+ "cmd": "np.array([#PVM_VoxArrSize[0,0], #PVM_VoxArrSize[0,1], #PVM_VoxArrSize[0,2]])",
68
+ "conditions": [
69
+ "@pv_version.split('.')[0]!='5'",
70
+ "#VisuCoreDimDesc.list[0]=='spectroscopic'",
71
+ "#VisuCoreDimDesc.list[1]=='spatial'",
72
+ "#VisuCoreDimDesc.list[2]=='spatial'"]
73
+ },
74
+ {
75
+ "cmd": "np.array([#VisuCoreExtent[0], #VisuCoreExtent[1], (np.shape(#VisuCorePosition)[0] + 1 ) * abs(#VisuCorePosition[1,2] - #VisuCorePosition[0,2])])",
76
+ "conditions": [
77
+ "#VisuCorePosition.size[0]>1",
78
+ "#VisuCoreDim==2"
79
+ ]
80
+ },
81
+ {
82
+ "cmd": "np.array([#VisuCoreExtent[0], #VisuCoreExtent[1], #VisuCoreFrameThickness])",
83
+ "conditions": [
84
+ "#VisuCorePosition.size[0]==1",
85
+ "#VisuCoreDim==2"
86
+ ]
87
+ },
88
+ {
89
+ "cmd": "np.array([#VisuCoreExtent[0], #VisuCoreExtent[1], #VisuCoreExtent[2]])",
90
+ "conditions": [
91
+ "#VisuCoreDimDesc.list[0]=='spatial'",
92
+ "#VisuCoreDimDesc.list[1]=='spatial'",
93
+ "#VisuCoreDimDesc.list[2]=='spatial'"]
94
+ }
95
+ ],
96
+ "resolution": [
97
+ {
98
+ "cmd": "np.array([#PVM_VoxArrSize[0,0], #PVM_VoxArrSize[0,1], #VisuCoreFrameThickness])",
99
+ "conditions": [
100
+ "@pv_version.split('.')[0]=='5'",
101
+ "#VisuCoreDimDesc.list[0]=='spectroscopic'",
102
+ "#VisuCoreDimDesc.list[1]=='spatial'",
103
+ "#VisuCoreDimDesc.list[2]=='spatial'"]
104
+ },
105
+ {
106
+ "cmd": "np.array([#PVM_VoxArrSize[0,0] / #VisuCoreSize[1], #PVM_VoxArrSize[0,1] / #VisuCoreSize[2], #PVM_VoxArrSize[0,2]])",
107
+ "conditions": [
108
+ "@pv_version.split('.')[0]!='5'",
109
+ "#VisuCoreDimDesc.list[0]=='spectroscopic'",
110
+ "#VisuCoreDimDesc.list[1]=='spatial'",
111
+ "#VisuCoreDimDesc.list[2]=='spatial'"]
112
+ },
113
+ {
114
+ "cmd": "np.array([#VisuCoreExtent[0] / #VisuCoreSize[0], #VisuCoreExtent[1] / #VisuCoreSize[1], np.linalg.norm(#VisuCorePosition[1,:] - #VisuCorePosition[0,:])])",
115
+ "conditions": [
116
+ "#VisuCorePosition.size[0]>1",
117
+ "#VisuCoreDim==2"],
118
+ "comment": "spec 7.10: the distance between two measured slice centres. VisuCoreSlicePacksSliceDist is already centre-to-centre, so it must not be added to VisuCoreFrameThickness"
119
+ },
120
+ {
121
+ "cmd": "np.array([#VisuCoreExtent[0] / #VisuCoreSize[0], #VisuCoreExtent[1] / #VisuCoreSize[1], #VisuCoreSlicePacksSliceDist.list[0]])",
122
+ "conditions": [
123
+ "#VisuCoreDim==2"]
124
+ },
125
+ {
126
+ "cmd": "np.array([#VisuCoreExtent[0] / #VisuCoreSize[0], #VisuCoreExtent[1] / #VisuCoreSize[1], #VisuCoreFrameThickness])",
127
+ "conditions": [
128
+ "#VisuCoreDim==2"]
129
+ },
130
+ {
131
+ "cmd": "np.array([#VisuCoreExtent[0] / #VisuCoreSize[0], #VisuCoreExtent[1] / #VisuCoreSize[1], #VisuCoreExtent[2] / #VisuCoreSize[2]])",
132
+ "conditions": [
133
+ "#VisuCoreDimDesc.list[0]=='spatial'",
134
+ "#VisuCoreDimDesc.list[1]=='spatial'",
135
+ "#VisuCoreDimDesc.list[2]=='spatial'"]
136
+ }
137
+ ],
138
+ "TE": [
139
+ {
140
+ "cmd": "#VisuAcqEchoTime",
141
+ "conditions": [
142
+ ]
143
+ }
144
+ ],
145
+ "TR": [
146
+ {
147
+ "cmd": "#VisuAcqRepetitionTime",
148
+ "conditions": [
149
+ ]
150
+ }
151
+ ],
152
+ "imaging_frequency": [
153
+ {
154
+ "cmd": "#VisuAcqImagingFrequency",
155
+ "conditions": [
156
+ ]
157
+ }
158
+ ],
159
+ "date": [
160
+ {
161
+ "cmd": "datetime.datetime.strptime(#VisuStudyDate[1:-1], '%X %d %b %Y')",
162
+ "conditions": [
163
+ "'T' not in #VisuStudyDate"
164
+ ]
165
+ },
166
+ {
167
+ "cmd": "datetime.datetime.strptime(#VisuStudyDate[1:-1], '%Y-%m-%dT%X,%f%z')",
168
+ "conditions": [
169
+ "'T' in #VisuStudyDate"
170
+ ]
171
+ }
172
+ ],
173
+ "dwell_s": [
174
+ {
175
+ "cmd": "1./ (#VisuAcqPixelBandwidth * #VisuCoreSize.list[0]) / 2.",
176
+ "conditions": []
177
+ },
178
+ {
179
+ "cmd": "None",
180
+ "conditions": [],
181
+ "comment": "default value"
182
+ }
183
+ ]
184
+ }