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
« 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.
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.
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.
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.
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"""
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
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.
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`
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.
46 Returns
47 -------
48 TimeHistoryArray
49 Time history array object.
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
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
79 def dec_to_strings(array):
80 """
81 Convert numpy array of decimal characters into a numpy array of strings.
83 Parameters
84 ----------
85 array : ndarray
86 Numpy array of decimal character codes
88 Returns
89 -------
90 array : ndarray
91 Numpy array of strings with one string for each row of the original numpy array
92 """
94 # Convert Decimal Codes into Strings
95 strings = np.array([''.join(map(chr, col)) for col in array.T])
96 return strings
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 }
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)
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
131 else:
132 raise ValueError('Invalid file type')