Coverage for src / sdynpy / fileio / sdynpy_dataphysics.py: 13%

54 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-11 16:22 +0000

1# -*- coding: utf-8 -*- 

2""" 

3Load in time data from dataphysics runs. 

4 

5Using the functions in this module, one can read mat v7.3 files written from DataPhysics. 

6""" 

7""" 

8Copyright 2022 National Technology & Engineering Solutions of Sandia, 

9LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. 

10Government retains certain rights in this software. 

11 

12This program is free software: you can redistribute it and/or modify 

13it under the terms of the GNU General Public License as published by 

14the Free Software Foundation, either version 3 of the License, or 

15(at your option) any later version. 

16 

17This program is distributed in the hope that it will be useful, 

18but WITHOUT ANY WARRANTY; without even the implied warranty of 

19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

20GNU General Public License for more details. 

21 

22You should have received a copy of the GNU General Public License 

23along with this program. If not, see <https://www.gnu.org/licenses/>. 

24""" 

25 

26import h5py 

27import numpy as np 

28import os 

29from ..core.sdynpy_data import coordinate_array, TimeHistoryArray, CoordinateArray, FunctionTypes, data_array 

30from scipy.io import loadmat 

31 

32def read_dataphysics_output(file: os.PathLike | h5py.File | dict, coordinate: CoordinateArray | None = None): 

33 """ 

34 Reads a Data Physics .mat or .uff file and converts it into a SDYNPY timehistory array object. 

35 

36 Parameters 

37 ---------- 

38 file : os.PathLike | h5py.File | dict 

39 Path to a .mat file (can be legacy .mat or v7.3) or a .uff file 

40 Alternatively, can be an `h5py.File` object or a `dict` created using `scipy.io.loadmat` 

41 

42 coordinate : CoordinateArray, optional 

43 sdynpy coordinate array. If not provided, will attempt to determine coordinate  

44 nodes/directions using `ChanName` from the .mat file or `comment4` from the .uff/.unv file. 

45 

46 Returns 

47 ------- 

48 TimeHistoryArray 

49 Time history array object. 

50 

51 """ 

52 UFF = False 

53 MAT = False 

54 MAT73 = False 

55 ext = None 

56 if isinstance(file, str): 

57 # Get File Extension 

58 _, ext = os.path.splitext(file) 

59 ext = ext.lower() 

60 elif isinstance(file, dict): 

61 data = file 

62 MAT = True 

63 elif isinstance(file, h5py.File): 

64 MAT = True 

65 MAT73 = True 

66 

67 if ext == '.mat': 

68 try: 

69 data = loadmat(file) 

70 MAT = True 

71 except NotImplementedError: 

72 file = h5py.File(file,'r') 

73 MAT = True 

74 MAT73 = True 

75 elif ext == '.uff': 

76 UFF = True 

77 

78 

79 def dec_to_strings(array): 

80 """ 

81 Convert numpy array of decimal characters into a numpy array of strings. 

82 

83 Parameters 

84 ---------- 

85 array : ndarray 

86 Numpy array of decimal character codes 

87 

88 Returns 

89 ------- 

90 array : ndarray 

91 Numpy array of strings with one string for each row of the original numpy array 

92 """ 

93 

94 # Convert Decimal Codes into Strings 

95 strings = np.array([''.join(map(chr, col)) for col in array.T]) 

96 return strings 

97 

98 

99 if MAT: 

100 if MAT73: 

101 # Create Dictionary Structure 

102 data = { 

103 'ChanName':dec_to_strings(np.array(file['ChanName'])), # Numpy Array (# Channels) 

104 'EUType':np.array(file['EUType']).T, # Numpy Array (# Channels x 1) 

105 'InputChanNums':np.array(file['InputChanNums']).T, # Numpy Array (# Channels x 1) 

106 'Sensitivity':np.array(file['Sensitivity']).T, # Numpy Array (# Channels x 1) 

107 'Unit':dec_to_strings(np.array(file['Unit'])), # Numpy Array (# Channels) 

108 'hDelta':np.array(file['hDelta']), # Numpy Array (1 x 1) 

109 'TimeData':np.array(file['TimeData']).T, # Numpy Array (# Abscissa x # Channels) 

110 } 

111 

112 if coordinate is None: 

113 coordinate = coordinate_array(string_array=data['ChanName']) 

114 ordinate = np.array(data['TimeData']).swapaxes(0,1) 

115 abscissa_spacing = data['hDelta'][0,0] 

116 abscissa = np.linspace(0, ordinate.shape[-1]*abscissa_spacing, num=ordinate.shape[-1]) 

117 comment1 = 'Data Physics Corporation' 

118 comment2 = '' 

119 comment3 = '' 

120 comment4 = data['ChanName'] 

121 comment5 = data['Sensitivity'][:,0] 

122 return data_array(FunctionTypes.TIME_RESPONSE, abscissa, ordinate, coordinate[:,np.newaxis],comment1=comment1, comment2=comment2, comment3=comment3, comment4=comment4, comment5=comment5) 

123 

124 elif UFF: 

125 data = TimeHistoryArray.load(file) 

126 if coordinate is None: 

127 coordinate = coordinate_array(string_array=data.comment4) 

128 data.coordinate[:, 0] = coordinate 

129 return data 

130 

131 else: 

132 raise ValueError('Invalid file type')