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