DefDAP 1.2.2__tar.gz → 1.3.0__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 (37) hide show
  1. {defdap-1.2.2 → defdap-1.3.0}/DefDAP.egg-info/PKG-INFO +2 -1
  2. {defdap-1.2.2 → defdap-1.3.0}/DefDAP.egg-info/requires.txt +1 -0
  3. {defdap-1.2.2 → defdap-1.3.0}/PKG-INFO +2 -1
  4. defdap-1.3.0/defdap/_version.py +1 -0
  5. {defdap-1.2.2 → defdap-1.3.0}/defdap/file_readers.py +156 -12
  6. {defdap-1.2.2 → defdap-1.3.0}/pyproject.toml +3 -2
  7. defdap-1.2.2/defdap/_version.py +0 -1
  8. {defdap-1.2.2 → defdap-1.3.0}/DefDAP.egg-info/SOURCES.txt +0 -0
  9. {defdap-1.2.2 → defdap-1.3.0}/DefDAP.egg-info/dependency_links.txt +0 -0
  10. {defdap-1.2.2 → defdap-1.3.0}/DefDAP.egg-info/top_level.txt +0 -0
  11. {defdap-1.2.2 → defdap-1.3.0}/LICENSE +0 -0
  12. {defdap-1.2.2 → defdap-1.3.0}/README.md +0 -0
  13. {defdap-1.2.2 → defdap-1.3.0}/defdap/__init__.py +0 -0
  14. {defdap-1.2.2 → defdap-1.3.0}/defdap/_accelerated.py +0 -0
  15. {defdap-1.2.2 → defdap-1.3.0}/defdap/base.py +0 -0
  16. {defdap-1.2.2 → defdap-1.3.0}/defdap/crystal.py +0 -0
  17. {defdap-1.2.2 → defdap-1.3.0}/defdap/crystal_utils.py +0 -0
  18. {defdap-1.2.2 → defdap-1.3.0}/defdap/ebsd.py +0 -0
  19. {defdap-1.2.2 → defdap-1.3.0}/defdap/experiment.py +0 -0
  20. {defdap-1.2.2 → defdap-1.3.0}/defdap/file_writers.py +0 -0
  21. {defdap-1.2.2 → defdap-1.3.0}/defdap/hrdic.py +0 -0
  22. {defdap-1.2.2 → defdap-1.3.0}/defdap/inspector.py +0 -0
  23. {defdap-1.2.2 → defdap-1.3.0}/defdap/plotting.py +0 -0
  24. {defdap-1.2.2 → defdap-1.3.0}/defdap/quat.py +0 -0
  25. {defdap-1.2.2 → defdap-1.3.0}/defdap/slip_systems/cubic_bcc.txt +0 -0
  26. {defdap-1.2.2 → defdap-1.3.0}/defdap/slip_systems/cubic_bcc_110only.txt +0 -0
  27. {defdap-1.2.2 → defdap-1.3.0}/defdap/slip_systems/cubic_fcc.txt +0 -0
  28. {defdap-1.2.2 → defdap-1.3.0}/defdap/slip_systems/cubic_fcc_damask.txt +0 -0
  29. {defdap-1.2.2 → defdap-1.3.0}/defdap/slip_systems/hexagonal_noca.txt +0 -0
  30. {defdap-1.2.2 → defdap-1.3.0}/defdap/slip_systems/hexagonal_withca.txt +0 -0
  31. {defdap-1.2.2 → defdap-1.3.0}/defdap/utils.py +0 -0
  32. {defdap-1.2.2 → defdap-1.3.0}/docs/source/conf.py +0 -0
  33. {defdap-1.2.2 → defdap-1.3.0}/setup.cfg +0 -0
  34. {defdap-1.2.2 → defdap-1.3.0}/tests/test_ebsd.py +0 -0
  35. {defdap-1.2.2 → defdap-1.3.0}/tests/test_hrdic.py +0 -0
  36. {defdap-1.2.2 → defdap-1.3.0}/tests/test_io.py +0 -0
  37. {defdap-1.2.2 → defdap-1.3.0}/tests/test_quat.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DefDAP
3
- Version: 1.2.2
3
+ Version: 1.3.0
4
4
  Summary: A python library for correlating EBSD and HRDIC data.
5
5
  Author: Rhys Thomas, João Quinta da Fonseca
6
6
  Author-email: "Michael D. Atkinson" <michael.atkinson@ukaea.uk>
@@ -34,6 +34,7 @@ Requires-Dist: peakutils
34
34
  Requires-Dist: matplotlib_scalebar
35
35
  Requires-Dist: networkx
36
36
  Requires-Dist: numba
37
+ Requires-Dist: h5py
37
38
  Provides-Extra: testing
38
39
  Requires-Dist: pytest<8; extra == "testing"
39
40
  Requires-Dist: coverage; extra == "testing"
@@ -7,6 +7,7 @@ peakutils
7
7
  matplotlib_scalebar
8
8
  networkx
9
9
  numba
10
+ h5py
10
11
 
11
12
  [docs]
12
13
  sphinx==5.0.2
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: DefDAP
3
- Version: 1.2.2
3
+ Version: 1.3.0
4
4
  Summary: A python library for correlating EBSD and HRDIC data.
5
5
  Author: Rhys Thomas, João Quinta da Fonseca
6
6
  Author-email: "Michael D. Atkinson" <michael.atkinson@ukaea.uk>
@@ -34,6 +34,7 @@ Requires-Dist: peakutils
34
34
  Requires-Dist: matplotlib_scalebar
35
35
  Requires-Dist: networkx
36
36
  Requires-Dist: numba
37
+ Requires-Dist: h5py
37
38
  Provides-Extra: testing
38
39
  Requires-Dist: pytest<8; extra == "testing"
39
40
  Requires-Dist: coverage; extra == "testing"
@@ -0,0 +1 @@
1
+ __version__ = '1.3.0'
@@ -13,15 +13,16 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- import numpy as np
17
- from numpy.lib.recfunctions import structured_to_unstructured
18
- import pandas as pd
19
16
  from abc import ABC, abstractmethod
20
17
  import pathlib
21
18
  import re
22
-
23
19
  from typing import TextIO, Dict, List, Callable, Any, Type, Optional
24
20
 
21
+ import h5py
22
+ import numpy as np
23
+ from numpy.lib.recfunctions import structured_to_unstructured
24
+ import pandas as pd
25
+
25
26
  from defdap.crystal import Phase
26
27
  from defdap.quat import Quat
27
28
  from defdap.utils import Datastore
@@ -56,11 +57,14 @@ class EBSDDataLoader(ABC):
56
57
  self.data_format = None
57
58
 
58
59
  @staticmethod
59
- def get_loader(data_type: str, file_name: pathlib.Path) -> 'Type[EBSDDataLoader]':
60
+ def get_loader(
61
+ data_type: str, file_name: pathlib.Path
62
+ ) -> 'Type[EBSDDataLoader]':
60
63
  if data_type is None:
61
64
  data_type = {
62
65
  '.crc': 'oxfordbinary',
63
66
  '.cpr': 'oxfordbinary',
67
+ '.h5oina': 'oxfordh5',
64
68
  '.ctf': 'oxfordtext',
65
69
  '.ang': 'edaxang',
66
70
  }.get(file_name.suffix, 'oxfordbinary')
@@ -70,6 +74,7 @@ class EBSDDataLoader(ABC):
70
74
  loader = {
71
75
  'oxfordbinary': OxfordBinaryLoader,
72
76
  'oxfordtext': OxfordTextLoader,
77
+ 'oxfordh5': Oxfordh5Loader,
73
78
  'edaxang': EdaxAngLoader,
74
79
  'pythondict': PythonDictLoader,
75
80
  }[data_type]
@@ -234,6 +239,134 @@ class OxfordTextLoader(EBSDDataLoader):
234
239
  self.check_data()
235
240
 
236
241
 
242
+ class Oxfordh5Loader(EBSDDataLoader):
243
+ def load(self, file_name: pathlib.Path, dataset = None) -> None:
244
+ """Read an Oxford Instruments ``.h5oina`` orientation file.
245
+
246
+ Parameters
247
+ ----------
248
+ file_name : pathlib.Path
249
+ Path to file.
250
+ dataset : str (raw or processed), optional
251
+ Dataset to load. If None, defaults to raw data.
252
+
253
+ """
254
+ # Open data file and read in metadata
255
+ if not file_name.is_file():
256
+ raise FileNotFoundError(f"Cannot open file {file_name}")
257
+
258
+ file = h5py.File(file_name)
259
+
260
+ # This header contains all the information in the map that does not
261
+ # change with processing
262
+ raw_header = file['1']['EBSD']['Header']
263
+ shape = (int(raw_header['Y Cells'][0]), int(raw_header['X Cells'][0]))
264
+ self.loaded_metadata['shape'] = shape
265
+ self.loaded_metadata['step_size'] = float(raw_header['X Step'][0])
266
+ self.loaded_metadata['acquisition_rotation'] = Quat.from_euler_angles(
267
+ *raw_header['Specimen Orientation Euler'][0]
268
+ )
269
+
270
+ # Check if `Data Processing` dataset exists in the h5
271
+ if 'Data' in file['1']['Data Processing'] and dataset is None:
272
+ print('\n\tMultiple datasets in h5 file, defaulting to raw data.')
273
+ print(
274
+ '\tProcessed data can be accessed by passing `processed` to '
275
+ 'the `dataset` argument.'
276
+ )
277
+
278
+ # Handle `raw` or `processed` selection
279
+ if dataset is None or dataset == 'raw':
280
+ root = file['1']['EBSD']
281
+ if dataset == 'processed':
282
+ if 'Data Processing' not in file['1']:
283
+ raise ValueError('No processed data in h5 file.')
284
+ if 'Data' not in file['1']['Data Processing']:
285
+ raise ValueError('No processed data in h5 file.')
286
+ root = file['1']['Data Processing']
287
+
288
+ # Phase data from relevant dataset
289
+ for phase_data in root['Header']['Phases'].values():
290
+ phase = Phase(
291
+ phase_data['Phase Name'][0].decode(),
292
+ phase_data['Laue Group'][0],
293
+ phase_data['Space Group'][0],
294
+ np.concatenate([
295
+ phase_data['Lattice Dimensions'][0],
296
+ phase_data['Lattice Angles'][0]
297
+ ]))
298
+ self.loaded_metadata['phases'].append(phase)
299
+
300
+ self.check_metadata()
301
+
302
+ # Some data is only available and relevant for the raw data, for
303
+ # example band contrast
304
+ if dataset == 'raw':
305
+ raw_data = root['Data']
306
+ self.loaded_data.add(
307
+ 'band_contrast',
308
+ np.array(raw_data['Band Contrast']).reshape(shape),
309
+ unit='', type='map', order=0,
310
+ plot_params={
311
+ 'plot_colour_bar': True,
312
+ 'cmap': 'gray',
313
+ 'clabel': 'Band contrast',
314
+ }
315
+ )
316
+ self.loaded_data.add(
317
+ 'band_slope',
318
+ np.array(raw_data['Band Slope']).reshape(shape),
319
+ unit='', type='map', order=0,
320
+ plot_params={
321
+ 'plot_colour_bar': True,
322
+ 'cmap': 'gray',
323
+ 'clabel': 'Band slope',
324
+ }
325
+ )
326
+ self.loaded_data.add(
327
+ 'mean_angular_deviation',
328
+ np.array(raw_data['Mean Angular Deviation']).reshape(shape),
329
+ unit='', type='map', order=0,
330
+ plot_params={
331
+ 'plot_colour_bar': True,
332
+ 'clabel': 'Mean angular deviation',
333
+ }
334
+ )
335
+ self.loaded_data.add(
336
+ 'pattern_quality',
337
+ np.array(raw_data['Pattern Quality']).reshape(shape),
338
+ unit='', type='map', order=0,
339
+ plot_params={
340
+ 'plot_colour_bar': True,
341
+ 'clabel': 'Pattern quality',
342
+ }
343
+ )
344
+
345
+ # If pattern matching is performed, the cross correlation coefficient
346
+ # is useful
347
+ if dataset == 'processed' and 'Pattern Matching' in root:
348
+ pattern_data = root['Pattern Matching']['Data']
349
+ self.loaded_data.add(
350
+ 'pattern_quality',
351
+ np.array(
352
+ pattern_data['Cross Correlation Coefficient']
353
+ ).reshape(shape),
354
+ unit='', type='map', order=0,
355
+ plot_params={
356
+ 'plot_colour_bar': True,
357
+ 'clabel': 'Cross Correlation Coefficient',
358
+ }
359
+ )
360
+
361
+ # Get Euler angles from relevant dataset
362
+ self.loaded_data.phase = np.array(root['Data']['Phase']).reshape(shape)
363
+ self.loaded_data.euler_angle = (
364
+ root['Data']['Euler'][:].reshape(shape + (3,)).transpose((2, 0, 1))
365
+ )
366
+
367
+ self.check_data()
368
+
369
+
237
370
  class EdaxAngLoader(EBSDDataLoader):
238
371
  def load(self, file_name: pathlib.Path) -> None:
239
372
  """ Read an EDAX .ang file.
@@ -327,7 +460,9 @@ class EdaxAngLoader(EBSDDataLoader):
327
460
  )
328
461
  add_phase = 1 if data['phase'].min() == 0 else 0
329
462
  self.loaded_data.phase = data['phase'].reshape(shape) + add_phase
330
- self.loaded_data['phase', 'plot_params']['vmax'] = len(self.loaded_metadata['phases'])
463
+ self.loaded_data['phase', 'plot_params']['vmax'] = len(
464
+ self.loaded_metadata['phases']
465
+ )
331
466
 
332
467
  # flatten the structured dtype
333
468
  euler_angle = structured_to_unstructured(
@@ -424,8 +559,10 @@ class OxfordBinaryLoader(EBSDDataLoader):
424
559
 
425
560
  group_name = group_pat.match(line.strip()).group(1)
426
561
  group_dict = dict()
427
- read_until_string(cpr_file, '[', comment_char=comment_char,
428
- line_process=lambda l: parse_line(l, group_dict))
562
+ read_until_string(
563
+ cpr_file, '[', comment_char=comment_char,
564
+ line_process=lambda l: parse_line(l, group_dict)
565
+ )
429
566
  metadata[group_name] = group_dict
430
567
 
431
568
  # Create phase objects and move metadata to object metadata dict
@@ -549,7 +686,8 @@ class OxfordBinaryLoader(EBSDDataLoader):
549
686
  data[['ph1', 'phi', 'ph2']].reshape(shape)).transpose((2, 0, 1))
550
687
 
551
688
  if self.loaded_metadata['edx']['Count'] > 0:
552
- EDXFields = [key for key in data.dtype.fields.keys() if key.startswith('EDX')]
689
+ EDXFields = [key for key in data.dtype.fields.keys()
690
+ if key.startswith('EDX')]
553
691
  for field in EDXFields:
554
692
  self.loaded_data.add(
555
693
  field,
@@ -590,7 +728,9 @@ class PythonDictLoader(EBSDDataLoader):
590
728
  unit='', type='map', order=0
591
729
  )
592
730
  self.loaded_data.phase = data_dict['phase']
593
- self.loaded_data['phase', 'plot_params']['vmax'] = len(self.loaded_metadata['phases'])
731
+ self.loaded_data['phase', 'plot_params']['vmax'] = len(
732
+ self.loaded_metadata['phases']
733
+ )
594
734
  self.loaded_data.euler_angle = data_dict['euler_angle']
595
735
  self.check_data()
596
736
 
@@ -819,8 +959,12 @@ class OpenPivBinaryLoader(DICDataLoader):
819
959
 
820
960
  # if y descending, flip
821
961
  if np.all(np.diff(data['y'][:,0])) > 0:
822
- self.loaded_data.coordinate = np.array([data['x'][::-1], data['y'][::-1]])
823
- self.loaded_data.displacement = np.array([data['u'][::-1], data['v'][::-1]])
962
+ self.loaded_data.coordinate = np.array(
963
+ [data['x'][::-1], data['y'][::-1]]
964
+ )
965
+ self.loaded_data.displacement = np.array(
966
+ [data['u'][::-1], data['v'][::-1]]
967
+ )
824
968
  else:
825
969
  self.loaded_data.coordinate = np.array([data['x'], data['y']])
826
970
  self.loaded_data.displacement = np.array([data['u'], data['v']])
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "DefDAP"
7
- version = "1.2.2"
7
+ version = "1.3.0"
8
8
  authors = [
9
9
  {name = "Michael D. Atkinson", email = "michael.atkinson@ukaea.uk"},
10
10
  {name = "Rhys Thomas"},
@@ -41,6 +41,7 @@ dependencies = [
41
41
  "matplotlib_scalebar",
42
42
  "networkx",
43
43
  "numba",
44
+ "h5py"
44
45
  ]
45
46
 
46
47
  [project.urls]
@@ -75,7 +76,7 @@ defdap = ["slip_systems/*.txt"]
75
76
 
76
77
  [tool.commitizen]
77
78
  name = "cz_conventional_commits"
78
- version = "1.2.2"
79
+ version = "1.3.0"
79
80
  tag_format = "v$version"
80
81
  version_files = [
81
82
  "pyproject.toml:version",
@@ -1 +0,0 @@
1
- __version__ = '1.2.2'
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes