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

Commit 3f4fce7

Browse files
committed
IO: Lin: speed up of reader for baseline case with floats
1 parent 63cc257 commit 3f4fce7

File tree

1 file changed

+154
-141
lines changed

1 file changed

+154
-141
lines changed

pyFAST/input_output/fast_linearization_file.py

+154-141
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
File = dict
88
class BrokenFormatError(Exception): pass
99

10+
class SlowReaderNeededError(Exception):
11+
pass
1012

1113

1214
_lin_vec = ['x','xd','xdot','u','y','z','header']
@@ -80,144 +82,61 @@ def read(self, filename=None, starSub=None, removeStatesPattern=None):
8082
# --- StarValues replacement `*****` -> inf
8183
starPattern = re.compile(r"[\*]+")
8284
starSubStr = ' inf '
83-
84-
def extractVal(lines, key, NA=None, missing=None, dtype=float):
85-
for l in lines:
86-
if l.find(key)>=0:
87-
#l = starPattern.sub(starSubStr, l)
88-
try:
89-
return dtype(l.split(key)[1].split()[0])
90-
except:
91-
return NA
92-
return missing
93-
94-
def readToMarker(fid, marker, nMax):
95-
lines=[]
96-
for i, line in enumerate(fid):
97-
if i>nMax:
98-
raise BrokenFormatError('`{}` not found in file'.format(marker))
99-
if line.find(marker)>=0:
100-
break
101-
lines.append(line.strip())
102-
return lines, line
103-
104-
def readOP(fid, n, name='', defaultDerivOrder=1):
105-
OP=[]
106-
Var = {'RotatingFrame': [], 'DerivativeOrder': [], 'Description': []}
107-
colNames=fid.readline().strip()
108-
dummy= fid.readline().strip()
109-
bHasDeriv= colNames.find('Derivative Order')>=0
110-
for i, line in enumerate(fid):
111-
line = line.strip()
112-
line = starPattern.sub(starSubStr, line)
113-
sp = line.split()
114-
if sp[1].find(',')>=0:
115-
# Most likely this OP has three values (e.g. orientation angles)
116-
# For now we discard the two other values
117-
OP.append(float(sp[1][:-1]))
118-
iRot=4
119-
else:
120-
OP.append(float(sp[1]))
121-
iRot=2
122-
Var['RotatingFrame'].append(sp[iRot])
123-
if bHasDeriv:
124-
Var['DerivativeOrder'].append(int(sp[iRot+1]))
125-
Var['Description'].append(' '.join(sp[iRot+2:]).strip())
126-
else:
127-
Var['DerivativeOrder'].append(defaultDerivOrder)
128-
Var['Description'].append(' '.join(sp[iRot+1:]).strip())
129-
if i>=n-1:
130-
break
131-
OP = np.asarray(OP)
132-
nInf = sum(np.isinf(OP))
133-
if nInf>0:
134-
sErr = 'Some ill-formated/infinite values (e.g. `*******`) were found in the vector `{}`\n\tin linflile: {}'.format(name, self.filename)
135-
if starSub is None:
136-
raise Exception(sErr)
137-
else:
138-
print('[WARN] '+sErr)
139-
OP[np.isinf(OP)] = starSub
140-
141-
Var['RotatingFrame'] = np.asarray(Var['RotatingFrame'])
142-
Var['DerivativeOrder'] = np.asarray(Var['DerivativeOrder'])
143-
Var['Description'] = np.asarray(Var['Description'])
144-
return OP, Var
145-
146-
def readMat(fid, n, m, name=''):
147-
vals=[starPattern.sub(starSubStr, fid.readline().strip() ).split() for i in np.arange(n)]
148-
vals = np.array(vals)
149-
try:
150-
vals = np.array(vals).astype(float) # This could potentially fail
151-
except:
152-
raise Exception('Failed to convert into an array of float the matrix `{}`\n\tin linfile: {}'.format(name, self.filename))
153-
if vals.shape[0]!=n or vals.shape[1]!=m:
154-
shape1 = vals.shape
155-
shape2 = (n,m)
156-
raise Exception('Shape of matrix `{}` has wrong dimension ({} instead of {})\n\tin linfile: {}'.format(name, shape1, shape2, name, self.filename))
157-
158-
nNaN = sum(np.isnan(vals.ravel()))
159-
nInf = sum(np.isinf(vals.ravel()))
160-
if nInf>0:
161-
sErr = 'Some ill-formated/infinite values (e.g. `*******`) were found in the matrix `{}`\n\tin linflile: {}'.format(name, self.filename)
162-
if starSub is None:
163-
raise Exception(sErr)
164-
else:
165-
print('[WARN] '+sErr)
166-
vals[np.isinf(vals)] = starSub
167-
if nNaN>0:
168-
raise Exception('Some NaN values were found in the matrix `{}`\n\tin linfile: `{}`.'.format(name, self.filename))
169-
return vals
170-
171-
172-
# Reading
173-
with open(self.filename, 'r', errors="surrogateescape") as f:
174-
# --- Reader header
175-
self['header'], lastLine=readToMarker(f, 'Jacobians included', 30)
176-
self['header'].append(lastLine)
177-
nx = extractVal(self['header'],'Number of continuous states:' , dtype=int, NA=np.nan, missing=None)
178-
nxd = extractVal(self['header'],'Number of discrete states:' , dtype=int, NA=np.nan, missing=None)
179-
nz = extractVal(self['header'],'Number of constraint states:' , dtype=int, NA=np.nan, missing=None)
180-
nu = extractVal(self['header'],'Number of inputs:' , dtype=int, NA=np.nan, missing=None)
181-
ny = extractVal(self['header'],'Number of outputs:' , dtype=int, NA=np.nan, missing=None)
182-
bJac = extractVal(self['header'],'Jacobians included in this file?', dtype=bool, NA=False, missing=None)
183-
self['Azimuth'] = extractVal(self['header'], 'Azimuth:' , dtype=float, NA=np.nan, missing=None)
184-
self['RotSpeed'] = extractVal(self['header'], 'Rotor Speed:', dtype=float, NA=np.nan, missing=None) # rad/s
185-
self['WindSpeed'] = extractVal(self['header'], 'Wind Speed:' , dtype=float, NA=np.nan, missing=None)
186-
self['t'] = extractVal(self['header'],'Simulation time:' , dtype=float, NA=np.nan, missing=None)
187-
188-
for i, line in enumerate(f):
189-
line = line.strip()
190-
if line.find('Order of continuous states:')>=0:
191-
self['x'], self['x_info'] = readOP(f, nx, 'x', defaultDerivOrder=1)
192-
elif line.find('Order of continuous state derivatives:')>=0:
193-
self['xdot'], self['xdot_info'] = readOP(f, nx, 'xdot', defaultDerivOrder=2)
194-
elif line.find('Order of discrete states:')>=0:
195-
self['xd'], self['xd_info'] = readOP(f, nxd, 'xd', defaultDerivOrder=2)
196-
elif line.find('Order of inputs')>=0:
197-
self['u'], self['u_info'] = readOP(f, nu, 'u', defaultDerivOrder=0)
198-
elif line.find('Order of outputs')>=0:
199-
self['y'], self['y_info'] = readOP(f, ny, 'y', defaultDerivOrder=0)
200-
elif line.find('Order of constraint states:')>=0:
201-
self['z'], self['z_info'] = readOP(f, nz, 'z', defaultDerivOrder=0)
202-
elif line.find('A:')>=0:
203-
self['A'] = readMat(f, nx, nx, 'A')
204-
elif line.find('B:')>=0:
205-
self['B'] = readMat(f, nx, nu, 'B')
206-
elif line.find('C:')>=0:
207-
self['C'] = readMat(f, ny, nx, 'C')
208-
elif line.find('D:')>=0:
209-
self['D'] = readMat(f, ny, nu, 'D')
210-
elif line.find('dUdu:')>=0:
211-
self['dUdu'] = readMat(f, nu, nu,'dUdu')
212-
elif line.find('dUdy:')>=0:
213-
self['dUdy'] = readMat(f, nu, ny,'dUdy')
214-
elif line.find('StateRotation:')>=0:
215-
pass
216-
# TODO
217-
#StateRotation:
218-
elif line.find('ED M:')>=0:
219-
self['EDDOF'] = line[5:].split()
220-
self['M'] = readMat(f, 24, 24,'M')
85+
starSubFn = lambda si: starPattern.sub(starSubStr, si)
86+
87+
# Reading function, with slow or fast reader. See sub functions at end of this file
88+
def doRead(slowReader=False):
89+
with open(self.filename, 'r', errors="surrogateescape") as f:
90+
# --- Reader header
91+
self['header'], lastLine=readToMarker(f, 'Jacobians included', 30)
92+
self['header'].append(lastLine)
93+
nx = extractVal(self['header'],'Number of continuous states:' , dtype=int, NA=np.nan, missing=None)
94+
nxd = extractVal(self['header'],'Number of discrete states:' , dtype=int, NA=np.nan, missing=None)
95+
nz = extractVal(self['header'],'Number of constraint states:' , dtype=int, NA=np.nan, missing=None)
96+
nu = extractVal(self['header'],'Number of inputs:' , dtype=int, NA=np.nan, missing=None)
97+
ny = extractVal(self['header'],'Number of outputs:' , dtype=int, NA=np.nan, missing=None)
98+
bJac = extractVal(self['header'],'Jacobians included in this file?', dtype=bool, NA=False, missing=None)
99+
self['Azimuth'] = extractVal(self['header'], 'Azimuth:' , dtype=float, NA=np.nan, missing=None)
100+
self['RotSpeed'] = extractVal(self['header'], 'Rotor Speed:', dtype=float, NA=np.nan, missing=None) # rad/s
101+
self['WindSpeed'] = extractVal(self['header'], 'Wind Speed:' , dtype=float, NA=np.nan, missing=None)
102+
self['t'] = extractVal(self['header'],'Simulation time:' , dtype=float, NA=np.nan, missing=None)
103+
for i, line in enumerate(f):
104+
line = line.strip()
105+
if line.find('Order of continuous states:')>=0:
106+
self['x'], self['x_info'] = readOP(f, nx, 'x', defaultDerivOrder=1, starSubFn=starSubFn, starSub=starSub)
107+
elif line.find('Order of continuous state derivatives:')>=0:
108+
self['xdot'], self['xdot_info'] = readOP(f, nx, 'xdot', defaultDerivOrder=2, starSubFn=starSubFn, starSub=starSub)
109+
elif line.find('Order of discrete states:')>=0:
110+
self['xd'], self['xd_info'] = readOP(f, nxd, 'xd', defaultDerivOrder=2, starSubFn=starSubFn, starSub=starSub)
111+
elif line.find('Order of inputs')>=0:
112+
self['u'], self['u_info'] = readOP(f, nu, 'u', defaultDerivOrder=0, starSubFn=starSubFn, starSub=starSub)
113+
elif line.find('Order of outputs')>=0:
114+
self['y'], self['y_info'] = readOP(f, ny, 'y', defaultDerivOrder=0, starSubFn=starSubFn, starSub=starSub)
115+
elif line.find('Order of constraint states:')>=0:
116+
self['z'], self['z_info'] = readOP(f, nz, 'z', defaultDerivOrder=0, starSubFn=starSubFn, starSub=starSub)
117+
elif line.find('A:')>=0:
118+
self['A'] = readMat(f, nx, nx, 'A', slowReader=slowReader, filename=self.filename, starSubFn=starSubFn, starSub=starSub)
119+
elif line.find('B:')>=0:
120+
self['B'] = readMat(f, nx, nu, 'B', slowReader=slowReader, filename=self.filename, starSubFn=starSubFn, starSub=starSub)
121+
elif line.find('C:')>=0:
122+
self['C'] = readMat(f, ny, nx, 'C', slowReader=slowReader, filename=self.filename, starSubFn=starSubFn, starSub=starSub)
123+
elif line.find('D:')>=0:
124+
self['D'] = readMat(f, ny, nu, 'D', slowReader=slowReader, filename=self.filename, starSubFn=starSubFn, starSub=starSub)
125+
elif line.find('dUdu:')>=0:
126+
self['dUdu'] = readMat(f, nu, nu,'dUdu', slowReader=slowReader, filename=self.filename, starSubFn=starSubFn, starSub=starSub)
127+
elif line.find('dUdy:')>=0:
128+
self['dUdy'] = readMat(f, nu, ny,'dUdy', slowReader=slowReader, filename=self.filename, starSubFn=starSubFn, starSub=starSub)
129+
elif line.find('StateRotation:')>=0:
130+
pass
131+
# TODO
132+
#StateRotation:
133+
elif line.find('ED M:')>=0:
134+
self['EDDOF'] = line[5:].split()
135+
self['M'] = readMat(f, 24, 24,'M', slowReader=slowReader, filename=self.filename, starSubFn=starSubFn, starSub=starSub)
136+
try:
137+
doRead(slowReader=False)
138+
except SlowReaderNeededError:
139+
doRead(slowReader=True)
221140

222141
if removeStatesPattern is not None:
223142
self.removeStates(pattern=removeStatesPattern)
@@ -442,9 +361,6 @@ def eva(self, normQ=None, sort=True, discardIm=True):
442361
return freq_d, zeta, Q, freq_0
443362

444363

445-
446-
447-
448364
def short_descr(slist):
449365
""" Shorten and "unify" the description from lin file """
450366
def shortname(s):
@@ -587,6 +503,103 @@ def shortname(s):
587503

588504

589505

506+
def extractVal(lines, key, NA=None, missing=None, dtype=float):
507+
for l in lines:
508+
if l.find(key)>=0:
509+
#l = starPattern.sub(starSubStr, l)
510+
try:
511+
return dtype(l.split(key)[1].split()[0])
512+
except:
513+
return NA
514+
return missing
515+
516+
def readToMarker(fid, marker, nMax):
517+
lines=[]
518+
for i, line in enumerate(fid):
519+
if i>nMax:
520+
raise BrokenFormatError('`{}` not found in file'.format(marker))
521+
if line.find(marker)>=0:
522+
break
523+
lines.append(line.strip())
524+
return lines, line
525+
526+
def readOP(fid, n, name='', defaultDerivOrder=1, filename='', starSubFn=None, starSub=None):
527+
OP=[]
528+
Var = {'RotatingFrame': [], 'DerivativeOrder': [], 'Description': []}
529+
colNames=fid.readline().strip()
530+
dummy= fid.readline().strip()
531+
bHasDeriv= colNames.find('Derivative Order')>=0
532+
for i, line in enumerate(fid):
533+
line = line.strip()
534+
line = starSubFn(line)
535+
sp = line.split()
536+
if sp[1].find(',')>=0:
537+
# Most likely this OP has three values (e.g. orientation angles)
538+
# For now we discard the two other values
539+
OP.append(float(sp[1][:-1]))
540+
iRot=4
541+
else:
542+
OP.append(float(sp[1]))
543+
iRot=2
544+
Var['RotatingFrame'].append(sp[iRot])
545+
if bHasDeriv:
546+
Var['DerivativeOrder'].append(int(sp[iRot+1]))
547+
Var['Description'].append(' '.join(sp[iRot+2:]).strip())
548+
else:
549+
Var['DerivativeOrder'].append(defaultDerivOrder)
550+
Var['Description'].append(' '.join(sp[iRot+1:]).strip())
551+
if i>=n-1:
552+
break
553+
OP = np.asarray(OP)
554+
nInf = np.sum(np.isinf(OP))
555+
if nInf>0:
556+
sErr = 'Some ill-formated/infinite values (e.g. `*******`) were found in the vector `{}`\n\tin linflile: {}'.format(name, filename)
557+
if starSub is None:
558+
raise Exception(sErr)
559+
else:
560+
print('[WARN] '+sErr)
561+
OP[np.isinf(OP)] = starSub
562+
563+
Var['RotatingFrame'] = np.asarray(Var['RotatingFrame'])
564+
Var['DerivativeOrder'] = np.asarray(Var['DerivativeOrder'])
565+
Var['Description'] = np.asarray(Var['Description'])
566+
return OP, Var
567+
568+
569+
570+
def readMat(fid, n, m, name='', slowReader=False, filename='', starSubFn=None, starSub=None):
571+
if not slowReader:
572+
try:
573+
return np.array([fid.readline().strip().split() for i in np.arange(n)],dtype=float)
574+
except:
575+
print('[INFO] Failed to read some value in matrix {}, trying slower reader'.format(name))
576+
raise SlowReaderNeededError()
577+
else:
578+
#vals = vals.ravel()
579+
#vals = np.array(list(map(starSubFn, vals))).reshape(n,m)
580+
vals=np.array([starSubFn( fid.readline().strip() ).split() for i in np.arange(n)], dtype=str)
581+
try:
582+
vals = vals.astype(float) # This could potentially fail
583+
except:
584+
raise Exception('Failed to convert into an array of float the matrix `{}`\n\tin linfile: {}'.format(name, filename))
585+
if vals.shape[0]!=n or vals.shape[1]!=m:
586+
shape1 = vals.shape
587+
shape2 = (n,m)
588+
raise Exception('Shape of matrix `{}` has wrong dimension ({} instead of {})\n\tin linfile: {}'.format(name, shape1, shape2, name, filename))
589+
590+
nNaN = np.sum(np.isnan(vals.ravel()))
591+
nInf = np.sum(np.isinf(vals.ravel()))
592+
if nInf>0:
593+
sErr = 'Some ill-formated/infinite values (e.g. `*******`) were found in the matrix `{}`\n\tin linflile: {}'.format(name, filename)
594+
if starSub is None:
595+
raise Exception(sErr)
596+
else:
597+
print('[WARN] '+sErr)
598+
vals[np.isinf(vals)] = starSub
599+
if nNaN>0:
600+
raise Exception('Some NaN values were found in the matrix `{}`\n\tin linfile: `{}`.'.format(name, filename))
601+
return vals
602+
590603
if __name__ == '__main__':
591604
f = FASTLinearizationFile('../../data/example_files/StandstillSemi_ForID_EDHD.1.lin')
592605
print(f)

0 commit comments

Comments
 (0)