Skip to content
This repository was archived by the owner on Nov 27, 2023. It is now read-only.

Commit abcf1b0

Browse files
committed
IO:FastLin: slightly more robust read and standalone file
1 parent 6e215bd commit abcf1b0

File tree

1 file changed

+74
-37
lines changed

1 file changed

+74
-37
lines changed

pyFAST/input_output/fast_linearization_file.py

Lines changed: 74 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1+
import os
12
import numpy as np
2-
import pandas as pd
33
import re
44
try:
55
from .file import File, WrongFormatError, BrokenFormatError
66
except:
77
File = dict
8-
class WrongFormatError(Exception): pass
98
class BrokenFormatError(Exception): pass
109

1110
class FASTLinearizationFile(File):
@@ -42,6 +41,27 @@ def defaultExtensions():
4241
def formatName():
4342
return 'FAST linearization output'
4443

44+
def __init__(self, filename=None, **kwargs):
45+
""" Class constructor. If a `filename` is given, the file is read. """
46+
self.filename = filename
47+
if filename:
48+
self.read(**kwargs)
49+
50+
def read(self, filename=None, **kwargs):
51+
""" Reads the file self.filename, or `filename` if provided """
52+
53+
# --- Standard tests and exceptions (generic code)
54+
if filename:
55+
self.filename = filename
56+
if not self.filename:
57+
raise Exception('No filename provided')
58+
if not os.path.isfile(self.filename):
59+
raise OSError(2,'File not found:',self.filename)
60+
if os.stat(self.filename).st_size == 0:
61+
raise EmptyFileError('File is empty:',self.filename)
62+
# --- Calling (children) function to read
63+
self._read(**kwargs)
64+
4565
def _read(self, *args, **kwargs):
4666
self['header']=[]
4767

@@ -61,7 +81,7 @@ def readToMarker(fid, marker, nMax):
6181
lines.append(line.strip())
6282
return lines, line
6383

64-
def readOP(fid, n):
84+
def readOP(fid, n, name=''):
6585
OP=[]
6686
Var = {'RotatingFrame': [], 'DerivativeOrder': [], 'Description': []}
6787
colNames=fid.readline().strip()
@@ -86,14 +106,30 @@ def readOP(fid, n):
86106
Var['Description'].append(' '.join(sp[iRot+1:]).strip())
87107
if i>=n-1:
88108
break
109+
OP=np.asarray(OP)
89110
return OP, Var
90111

91-
def readMat(fid, n, m):
92-
vals=[f.readline().strip().split() for i in np.arange(n)]
93-
# try:
94-
return np.array(vals).astype(float)
95-
# except ValueError:
96-
# import pdb; pdb.set_trace()
112+
def readMat(fid, n, m, name=''):
113+
pattern = re.compile(r"[\*]+")
114+
vals=[pattern.sub(' inf ', fid.readline().strip() ).split() for i in np.arange(n)]
115+
vals = np.array(vals)
116+
try:
117+
vals = np.array(vals).astype(float) # This could potentially fail
118+
except:
119+
raise Exception('Failed to convert into an array of float the matrix `{}`\n\tin linfile: {}'.format(name, self.filename))
120+
if vals.shape[0]!=n or vals.shape[1]!=m:
121+
shape1 = vals.shape
122+
shape2 = (n,m)
123+
raise Exception('Shape of matrix `{}` has wrong dimension ({} instead of {})\n\tin linfile: {}'.format(name, shape1, shape2, name, self.filename))
124+
125+
nNaN = sum(np.isnan(vals.ravel()))
126+
nInf = sum(np.isinf(vals.ravel()))
127+
if nInf>0:
128+
raise Exception('Some ill-formated/infinite values (e.g. `*******`) were found in the matrix `{}`\n\tin linflile: {}'.format(name, self.filename))
129+
if nNaN>0:
130+
raise Exception('Some NaN values were found in the matrix `{}`\n\tin linfile: `{}`.'.format(name, self.filename))
131+
return vals
132+
97133

98134
# Reading
99135
with open(self.filename, 'r', errors="surrogateescape") as f:
@@ -119,35 +155,35 @@ def readMat(fid, n, m):
119155
except:
120156
self['WindSpeed'] = None
121157

122-
KEYS=['Order of','A:','B:','C:','D:','ED M:', 'dUdu','dUdy']
123-
124158
for i, line in enumerate(f):
125159
line = line.strip()
126-
KeyFound=any([line.find(k)>=0 for k in KEYS])
127-
if KeyFound:
128-
if line.find('Order of continuous states:')>=0:
129-
self['x'], self['x_info'] = readOP(f, nx)
130-
elif line.find('Order of continuous state derivatives:')>=0:
131-
self['xdot'], self['xdot_info'] = readOP(f, nx)
132-
elif line.find('Order of inputs')>=0:
133-
self['u'], self['u_info'] = readOP(f, nu)
134-
elif line.find('Order of outputs')>=0:
135-
self['y'], self['y_info'] = readOP(f, ny)
136-
elif line.find('A:')>=0:
137-
self['A'] = readMat(f, nx, nx)
138-
elif line.find('B:')>=0:
139-
self['B'] = readMat(f, nx, nu)
140-
elif line.find('C:')>=0:
141-
self['C'] = readMat(f, ny, nx)
142-
elif line.find('D:')>=0:
143-
self['D'] = readMat(f, ny, nu)
144-
elif line.find('dUdu:')>=0:
145-
self['dUdu'] = readMat(f, nu, nu)
146-
elif line.find('dUdy:')>=0:
147-
self['dUdy'] = readMat(f, nu, ny)
148-
elif line.find('ED M:')>=0:
149-
self['EDDOF'] = line[5:].split()
150-
self['M'] = readMat(f, 24, 24)
160+
if line.find('Order of continuous states:')>=0:
161+
self['x'], self['x_info'] = readOP(f, nx, 'x')
162+
elif line.find('Order of continuous state derivatives:')>=0:
163+
self['xdot'], self['xdot_info'] = readOP(f, nx, 'xdot')
164+
elif line.find('Order of inputs')>=0:
165+
self['u'], self['u_info'] = readOP(f, nu, 'u')
166+
elif line.find('Order of outputs')>=0:
167+
self['y'], self['y_info'] = readOP(f, ny, 'y')
168+
elif line.find('A:')>=0:
169+
self['A'] = readMat(f, nx, nx, 'A')
170+
elif line.find('B:')>=0:
171+
self['B'] = readMat(f, nx, nu, 'B')
172+
elif line.find('C:')>=0:
173+
self['C'] = readMat(f, ny, nx, 'C')
174+
elif line.find('D:')>=0:
175+
self['D'] = readMat(f, ny, nu, 'D')
176+
elif line.find('dUdu:')>=0:
177+
self['dUdu'] = readMat(f, nu, nu,'dUdu')
178+
elif line.find('dUdy:')>=0:
179+
self['dUdy'] = readMat(f, nu, ny,'dUdy')
180+
elif line.find('StateRotation:')>=0:
181+
pass
182+
# TODO
183+
#StateRotation:
184+
elif line.find('ED M:')>=0:
185+
self['EDDOF'] = line[5:].split()
186+
self['M'] = readMat(f, 24, 24,'M')
151187

152188
def toString(self):
153189
s=''
@@ -319,7 +355,8 @@ def udescr(self):
319355
else:
320356
return []
321357

322-
def _toDataFrame(self):
358+
def toDataFrame(self):
359+
import pandas as pd
323360
dfs={}
324361

325362
xdescr_short = self.xdescr()

0 commit comments

Comments
 (0)