ChessAnalysisPipeline 0.0.11__py3-none-any.whl → 0.0.13__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.

Potentially problematic release.


This version of ChessAnalysisPipeline might be problematic. Click here for more details.

CHAP/common/reader.py CHANGED
@@ -6,7 +6,7 @@ Description: Module for Writers used in multiple experiment-specific
6
6
  workflows.
7
7
  """
8
8
 
9
- # system modules
9
+ # System modules
10
10
  from os.path import (
11
11
  isfile,
12
12
  splitext,
@@ -14,138 +14,86 @@ from os.path import (
14
14
  from sys import modules
15
15
  from time import time
16
16
 
17
- # local modules
17
+ # Third party modules
18
+ import numpy as np
19
+
20
+ # Local modules
18
21
  from CHAP import Reader
19
22
 
20
23
 
21
24
  class BinaryFileReader(Reader):
22
- """Reader for binary files"""
25
+ """Reader for binary files.
26
+ """
23
27
  def read(self, filename):
24
- """Return a content of a given file name
28
+ """Return a content of a given binary file.
25
29
 
26
- :param filename: name of the binart file to read from
27
- :return: the content of `filename`
30
+ :param filename: The name of the binary file to read from.
31
+ :type filename: str
32
+ :return: The file content.
28
33
  :rtype: binary
29
34
  """
30
-
31
35
  with open(filename, 'rb') as file:
32
36
  data = file.read()
33
37
  return data
34
38
 
35
39
 
36
- class SpecReader(Reader):
37
- """Reader for CHESS SPEC scans"""
38
- def read(self, filename=None, spec_config=None, detector_names=[]):
39
- """Take a SPEC configuration filename or dictionary and return
40
- the raw data as an NXentry.
40
+ class H5Reader(Reader):
41
+ """Reader for h5 files.
42
+ """
43
+ def read(self, filename, h5path='/'):
44
+ """Return the data object stored at `h5path` in an h5-file.
41
45
 
42
- :param filename: name of file with the SPEC configuration to
43
- read and pass onto the constructor of
44
- `CHAP.common.models.map.SpecConfig`
45
- :type filename: str, optional
46
- :param spec_config: SPEC configuration to be passed directly
47
- to the constructor of
48
- `CHAP.common.models.map.SpecConfig`
49
- :type spec_config: dict, optional
50
- :param detector_names: Detector prefixes to include raw data
51
- for in the returned NXentry
52
- :type detector_names: list[str]
53
- :return: Data from the SPEC configuration provided
54
- :rtype: nexusformat.nexus.NXentry
46
+ :param filename: The name of the h5-file to read from.
47
+ :type filename: str
48
+ :param h5path: The path to a specific location in the h5 file
49
+ to read data from, defaults to `'/'`
50
+ :type h5path: str, optional
51
+ :return: The object indicated by `filename` and `h5path`.
52
+ :rtype: object
55
53
  """
56
- from json import dumps
57
- from nexusformat.nexus import (NXcollection,
58
- NXdata,
59
- NXentry,
60
- NXfield)
61
- import numpy as np
62
- from CHAP.common.models.map import SpecConfig
63
-
64
- if filename is not None:
65
- if spec_config is not None:
66
- raise RuntimeError('Specify either filename or spec_config '
67
- 'in common.SpecReader, not both')
68
- # Read the map configuration from file
69
- if not isfile(filename):
70
- raise OSError(f'input file does not exist ({filename})')
71
- extension = splitext(filename)[1]
72
- if extension in ('.yml', '.yaml'):
73
- reader = YAMLReader()
74
- else:
75
- raise RuntimeError('input file has a non-implemented '
76
- f'extension ({filename})')
77
- spec_config = reader.read(filename)
78
- elif not isinstance(spec_config, dict):
79
- raise RuntimeError('Invalid parameter spec_config in '
80
- f'common.SpecReader ({spec_config})')
54
+ # Third party modules
55
+ from h5py import File
81
56
 
82
- # Validate the SPEC configuration provided by constructing a
83
- # SpecConfig
84
- spec_config = SpecConfig(**spec_config)
85
-
86
- # Set up NXentry and add misc. CHESS-specific metadata
87
- # as well as all spec_motors, scan_columns, and smb_pars
88
- nxentry = NXentry(name=spec_config.experiment_type)
89
- nxentry.spec_config = dumps(spec_config.dict())
90
- nxentry.attrs['station'] = spec_config.station
91
- nxentry.spec_scans = NXcollection()
92
- for scans in spec_config.spec_scans:
93
- nxscans = NXcollection()
94
- nxentry.spec_scans[f'{scans.scanparsers[0].scan_name}'] = nxscans
95
- nxscans.attrs['spec_file'] = str(scans.spec_file)
96
- nxscans.attrs['scan_numbers'] = scans.scan_numbers
97
- for scan_number in scans.scan_numbers:
98
- scanparser = scans.get_scanparser(scan_number)
99
- nxscans[scan_number] = NXcollection()
100
- if hasattr(scanparser, 'spec_positioner_values'):
101
- nxscans[scan_number].spec_motors = dumps(
102
- {k:float(v) for k,v
103
- in scanparser.spec_positioner_values.items()})
104
- if hasattr(scanparser, 'spec_scan_data'):
105
- nxscans[scan_number].scan_columns = dumps(
106
- {k:list(v) for k,v
107
- in scanparser.spec_scan_data.items() if len(v)})
108
- if hasattr(scanparser, 'pars'):
109
- nxscans[scan_number].smb_pars = dumps(
110
- {k:v for k,v in scanparser.pars.items()})
111
- if detector_names:
112
- nxdata = NXdata()
113
- nxscans[scan_number].data = nxdata
114
- for detector_name in detector_names:
115
- nxdata[detector_name] = NXfield(
116
- value=scanparser.get_detector_data(detector_name))
117
-
118
- return nxentry
57
+ data = File(filename, 'r')[h5path]
58
+ return data
119
59
 
120
60
 
121
61
  class MapReader(Reader):
122
- """Reader for CHESS sample maps"""
123
- def read(self, filename=None, map_config=None, detector_names=[]):
62
+ """Reader for CHESS sample maps.
63
+ """
64
+ def read(
65
+ self, filename=None, map_config=None, detector_names=[],
66
+ inputdir=None):
124
67
  """Take a map configuration dictionary and return a
125
- representation of the map as an NXentry. The NXentry's default
126
- data group will contain the raw data collected over the course
127
- of the map.
68
+ representation of the map as a NeXus NXentry object. The
69
+ NXentry's default data group will contain the raw data
70
+ collected over the course of the map.
128
71
 
129
- :param filename: name of file with the map configuration to
130
- read and pass onto the constructor of
131
- `CHAP.common.models.map.MapConfig`
72
+ :param filename: The name of a file with the map configuration
73
+ to read and pass onto the constructor of
74
+ `CHAP.common.models.map.MapConfig`, defaults to `None`.
132
75
  :type filename: str, optional
133
- :param map_config: map configuration to be passed directly to
134
- the constructor of `CHAP.common.models.map.MapConfig`
76
+ :param map_config: A map configuration to be passed directly to
77
+ the constructor of `CHAP.common.models.map.MapConfig`,
78
+ defaults to `None`.
135
79
  :type map_config: dict, optional
136
80
  :param detector_names: Detector prefixes to include raw data
137
- for in the returned NXentry
138
- :type detector_names: list[str]
139
- :return: Data from the map configuration provided
81
+ for in the returned NeXus NXentry object, defaults to `[]`.
82
+ :type detector_names: list[str], optional
83
+ :return: Data from the provided map configuration.
140
84
  :rtype: nexusformat.nexus.NXentry
141
85
  """
86
+ # Third party modules
142
87
  from json import dumps
143
- from nexusformat.nexus import (NXcollection,
144
- NXdata,
145
- NXentry,
146
- NXfield,
147
- NXsample)
148
- import numpy as np
88
+ from nexusformat.nexus import (
89
+ NXcollection,
90
+ NXdata,
91
+ NXentry,
92
+ NXfield,
93
+ NXsample,
94
+ )
95
+
96
+ # Local modules
149
97
  from CHAP.common.models.map import MapConfig
150
98
 
151
99
  if filename is not None:
@@ -168,7 +116,7 @@ class MapReader(Reader):
168
116
 
169
117
  # Validate the map configuration provided by constructing a
170
118
  # MapConfig
171
- map_config = MapConfig(**map_config)
119
+ map_config = MapConfig(**map_config, inputdir=inputdir)
172
120
 
173
121
  # Set up NXentry and add misc. CHESS-specific metadata
174
122
  nxentry = NXentry(name=map_config.title)
@@ -185,7 +133,8 @@ class MapReader(Reader):
185
133
 
186
134
  # Set up default data group
187
135
  nxentry.data = NXdata()
188
- nxentry.data.attrs['axes'] = map_config.dims
136
+ if map_config.map_type == 'structured':
137
+ nxentry.data.attrs['axes'] = map_config.dims
189
138
  for i, dim in enumerate(map_config.independent_dimensions[::-1]):
190
139
  nxentry.data[dim.label] = NXfield(
191
140
  value=map_config.coords[dim.label],
@@ -193,7 +142,8 @@ class MapReader(Reader):
193
142
  attrs={'long_name': f'{dim.label} ({dim.units})',
194
143
  'data_type': dim.data_type,
195
144
  'local_name': dim.name})
196
- nxentry.data.attrs[f'{dim.label}_indices'] = i
145
+ if map_config.map_type == 'structured':
146
+ nxentry.data.attrs[f'{dim.label}_indices'] = i
197
147
 
198
148
  # Create empty NXfields for all scalar data present in the
199
149
  # provided map configuration
@@ -241,43 +191,134 @@ class MapReader(Reader):
241
191
 
242
192
 
243
193
  class NexusReader(Reader):
244
- """Reader for NeXus files"""
194
+ """Reader for NeXus files.
195
+ """
245
196
  def read(self, filename, nxpath='/'):
246
- """Return the NeXus object stored at `nxpath` in the nexus
247
- file `filename`.
197
+ """Return the NeXus object stored at `nxpath` in a NeXus file.
248
198
 
249
- :param filename: name of the NeXus file to read from
199
+ :param filename: The name of the NeXus file to read from.
250
200
  :type filename: str
251
- :param nxpath: path to a specific loaction in the NeXus file
252
- to read from, defaults to `'/'`
201
+ :param nxpath: The path to a specific location in the NeXus
202
+ file tree to read from, defaults to `'/'`
253
203
  :type nxpath: str, optional
254
- :raises nexusformat.nexus.NeXusError: if `filename` is not a
255
- NeXus file or `nxpath` is not in `filename`.
256
- :return: the NeXus structure indicated by `filename` and `nxpath`.
204
+ :raises nexusformat.nexus.NeXusError: If `filename` is not a
205
+ NeXus file or `nxpath` is not in its tree.
206
+ :return: The NeXus object indicated by `filename` and `nxpath`.
257
207
  :rtype: nexusformat.nexus.NXobject
258
208
  """
259
-
209
+ # Third party modules
260
210
  from nexusformat.nexus import nxload
261
211
 
262
212
  nxobject = nxload(filename)[nxpath]
263
213
  return nxobject
264
214
 
265
215
 
216
+ class SpecReader(Reader):
217
+ """Reader for CHESS SPEC scans"""
218
+ def read(self, filename=None, spec_config=None, detector_names=[],
219
+ inputdir=None):
220
+ """Take a SPEC configuration filename or dictionary and return
221
+ the raw data as a Nexus NXentry object.
222
+
223
+ :param filename: The name of file with the SPEC configuration
224
+ to read from to pass onto the constructor of
225
+ `CHAP.common.models.map.SpecConfig`, defaults to `None`.
226
+ :type filename: str, optional
227
+ :param spec_config: A SPEC configuration to be passed directly
228
+ to the constructor of `CHAP.common.models.map.SpecConfig`,
229
+ defaults to `None`.
230
+ :type spec_config: dict, optional
231
+ :param detector_names: Detector prefixes to include raw data
232
+ for in the returned NeXus NXentry object, defaults to `[]`.
233
+ :type detector_names: list[str], optional
234
+ :return: The data from the provided SPEC configuration.
235
+ :rtype: nexusformat.nexus.NXentry
236
+ """
237
+ # Third party modules
238
+ from json import dumps
239
+ from nexusformat.nexus import (
240
+ NXcollection,
241
+ NXdata,
242
+ NXentry,
243
+ NXfield,
244
+ )
245
+
246
+ # Local modules
247
+ from CHAP.common.models.map import SpecConfig
248
+
249
+ if filename is not None:
250
+ if spec_config is not None:
251
+ raise RuntimeError('Specify either filename or spec_config '
252
+ 'in common.SpecReader, not both')
253
+ # Read the map configuration from file
254
+ if not isfile(filename):
255
+ raise OSError(f'input file does not exist ({filename})')
256
+ extension = splitext(filename)[1]
257
+ if extension in ('.yml', '.yaml'):
258
+ reader = YAMLReader()
259
+ else:
260
+ raise RuntimeError('input file has a non-implemented '
261
+ f'extension ({filename})')
262
+ spec_config = reader.read(filename)
263
+ elif not isinstance(spec_config, dict):
264
+ raise RuntimeError('Invalid parameter spec_config in '
265
+ f'common.SpecReader ({spec_config})')
266
+
267
+ # Validate the SPEC configuration provided by constructing a
268
+ # SpecConfig
269
+ spec_config = SpecConfig(**spec_config, inputdir=inputdir)
270
+
271
+ # Set up NXentry and add misc. CHESS-specific metadata
272
+ # as well as all spec_motors, scan_columns, and smb_pars
273
+ nxentry = NXentry(name=spec_config.experiment_type)
274
+ nxentry.spec_config = dumps(spec_config.dict())
275
+ nxentry.attrs['station'] = spec_config.station
276
+ nxentry.spec_scans = NXcollection()
277
+ for scans in spec_config.spec_scans:
278
+ nxscans = NXcollection()
279
+ nxentry.spec_scans[f'{scans.scanparsers[0].scan_name}'] = nxscans
280
+ nxscans.attrs['spec_file'] = str(scans.spec_file)
281
+ nxscans.attrs['scan_numbers'] = scans.scan_numbers
282
+ for scan_number in scans.scan_numbers:
283
+ scanparser = scans.get_scanparser(scan_number)
284
+ nxscans[scan_number] = NXcollection()
285
+ if hasattr(scanparser, 'spec_positioner_values'):
286
+ nxscans[scan_number].spec_motors = dumps(
287
+ {k:float(v) for k,v
288
+ in scanparser.spec_positioner_values.items()})
289
+ if hasattr(scanparser, 'spec_scan_data'):
290
+ nxscans[scan_number].scan_columns = dumps(
291
+ {k:list(v) for k,v
292
+ in scanparser.spec_scan_data.items() if len(v)})
293
+ if hasattr(scanparser, 'pars'):
294
+ nxscans[scan_number].smb_pars = dumps(
295
+ {k:v for k,v in scanparser.pars.items()})
296
+ if detector_names:
297
+ nxdata = NXdata()
298
+ nxscans[scan_number].data = nxdata
299
+ for detector_name in detector_names:
300
+ nxdata[detector_name] = NXfield(
301
+ value=scanparser.get_detector_data(detector_name))
302
+
303
+ return nxentry
304
+
305
+
266
306
  class URLReader(Reader):
267
- """Reader for data available over HTTPS"""
307
+ """Reader for data available over HTTPS.
308
+ """
268
309
  def read(self, url, headers={}, timeout=10):
269
310
  """Make an HTTPS request to the provided URL and return the
270
- results. Headers for the request are optional.
311
+ results. Headers for the request are optional.
271
312
 
272
- :param url: the URL to read
313
+ :param url: The URL to read.
273
314
  :type url: str
274
- :param headers: headers to attach to the request, defaults to
275
- `{}`
315
+ :param headers: Headers to attach to the request,
316
+ defaults to `{}`
276
317
  :type headers: dict, optional
277
- :return: the content of the response
318
+ :return: The content of the response.
278
319
  :rtype: object
279
320
  """
280
-
321
+ # System modules
281
322
  import requests
282
323
 
283
324
  resp = requests.get(url, headers=headers, timeout=timeout)
@@ -289,15 +330,17 @@ class URLReader(Reader):
289
330
 
290
331
 
291
332
  class YAMLReader(Reader):
292
- """Reader for YAML files"""
333
+ """Reader for YAML files.
334
+ """
293
335
  def read(self, filename):
294
336
  """Return a dictionary from the contents of a yaml file.
295
337
 
296
- :param filename: name of the YAML file to read from
297
- :return: the contents of `filename`
338
+ :param filename: The name of the YAML file to read from.
339
+ :type filename: str
340
+ :return: The contents of the file.
298
341
  :rtype: dict
299
342
  """
300
-
343
+ # Third party modules
301
344
  import yaml
302
345
 
303
346
  with open(filename) as file:
@@ -306,5 +349,7 @@ class YAMLReader(Reader):
306
349
 
307
350
 
308
351
  if __name__ == '__main__':
352
+ # Local modules
309
353
  from CHAP.reader import main
354
+
310
355
  main()