|
7 | 7 | File = dict
|
8 | 8 | class BrokenFormatError(Exception): pass
|
9 | 9 |
|
| 10 | +class SlowReaderNeededError(Exception): |
| 11 | + pass |
10 | 12 |
|
11 | 13 |
|
12 | 14 | _lin_vec = ['x','xd','xdot','u','y','z','header']
|
@@ -80,144 +82,61 @@ def read(self, filename=None, starSub=None, removeStatesPattern=None):
|
80 | 82 | # --- StarValues replacement `*****` -> inf
|
81 | 83 | starPattern = re.compile(r"[\*]+")
|
82 | 84 | 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) |
221 | 140 |
|
222 | 141 | if removeStatesPattern is not None:
|
223 | 142 | self.removeStates(pattern=removeStatesPattern)
|
@@ -442,9 +361,6 @@ def eva(self, normQ=None, sort=True, discardIm=True):
|
442 | 361 | return freq_d, zeta, Q, freq_0
|
443 | 362 |
|
444 | 363 |
|
445 |
| - |
446 |
| - |
447 |
| - |
448 | 364 | def short_descr(slist):
|
449 | 365 | """ Shorten and "unify" the description from lin file """
|
450 | 366 | def shortname(s):
|
@@ -587,6 +503,103 @@ def shortname(s):
|
587 | 503 |
|
588 | 504 |
|
589 | 505 |
|
| 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 | + |
590 | 603 | if __name__ == '__main__':
|
591 | 604 | f = FASTLinearizationFile('../../data/example_files/StandstillSemi_ForID_EDHD.1.lin')
|
592 | 605 | print(f)
|
|
0 commit comments