.fil Abaqus-Datei in Array

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Stoli
User
Beiträge: 17
Registriert: Donnerstag 24. Oktober 2013, 21:02

Hallo zusammen,
ich bin auf der Suche, nach einem "schönen" Weg eine .fil-Datei aus Abaqus mittels python in ein array-Format zu bekommen. Anschließend soll eine Auswertung dieser Daten über die Record Keys stattfinden.

Das Format ist sehr gewöhnungsbedürftig und ich konnte mit Hilfe eines replace-Befehls immerhin das Dokument zeilenweise soritieren.
Auf den Buchstaben I folgt ein INTEGER. Der Buchstabe A leitet einen STRING mit 8 Zeichen ein und auf ein D folgt ein FLOAT-Zahl in wissenschaftlicher Schreibweise, nur ist der Exponent durch ein "D" angegebenen, anstatt üblicherweise einem "E".

[codebox=python file=x]'I 19I 41921A6.10-1 A08-Nov-2A015 A09:54:03I 16I 13D 1.000000000000000D+00\nI 16I 41900I 11ADASHPOT2I 12I 11\nI 16I 41900I 12ASPRING2 I 12I 11\nI 12I 42001 \nI 223I 42000D 0.000000000000000D+00D 0.000000000000000D+00D 0.000000000000000D+00D 0.000000000000000D+00I 295I 11I 222I 11D 0.000000000000000D+00D 1.506949602122016D+00D 0.000000000000000D+00AFORCED OASCILLATIAON WITH AVISCOELAASTIC DAMAPING A A A A \nI 14I 41911I 11ANALL \nI 15I 3111I 11D 0.000000000000000D+00D 0.000000000000000D+00\nI 19I 3111I 12D 6.625918346244238D-02D 0.000000000000000D+00D 0.000000000000000D+00D-1.478679518984229D+01D 0.000000000000000D+00D 0.000000000000000D+00\nI 19I 3111I 13D 7.480262652497893D-02D 0.000000000000000D+00D 0.000000000000000D+00D-1.622259472865796D+01D 0.000000000000000D+00D 0.000000000000000D+00\nI 12I 42001 \n'[/code]
Zum Code, ich hoffe, dass er nicht durch das kopieren umformatiert wurde.

Ein .split() mit den oben verwendeten Buchstaben ist leider nicht ohne weiteres möglich, da in den STRINGS eben diese Buchstaben auch vorkommen, des weiteren erschwert die Exponential-Schreibweise mittels "D" das teilen der FLOATs.
Hat jemand eine Idee?

Grüße,
Stoli
BlackJack

@Stoli: Ich würde mir dafür einen Parser schreiben. Entweder mit regulären Ausdrücken und ein bisschen Code oder mit Hilfe des `pyparsing`-Moduls.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@Stoli: das läßt sich durch einen einfachen regulären Ausdruck lösen:

Code: Alles auswählen

import re
test = 'I 19I 41921A6.10-1  A08-Nov-2A015     A09:54:03I 16I 13D 1.000000000000000D+00\nI 16I 41900I 11ADASHPOT2I 12I 11\nI 16I 41900I 12ASPRING2 I 12I 11\nI 12I 42001                                                                                                                  \nI 223I 42000D 0.000000000000000D+00D 0.000000000000000D+00D 0.000000000000000D+00D 0.000000000000000D+00I 295I 11I 222I 11D 0.000000000000000D+00D 1.506949602122016D+00D 0.000000000000000D+00AFORCED OASCILLATIAON WITH AVISCOELAASTIC DAMAPING    A        A        A        A        \nI 14I 41911I 11ANALL    \nI 15I 3111I 11D 0.000000000000000D+00D 0.000000000000000D+00\nI 19I 3111I 12D 6.625918346244238D-02D 0.000000000000000D+00D 0.000000000000000D+00D-1.478679518984229D+01D 0.000000000000000D+00D 0.000000000000000D+00\nI 19I 3111I 13D 7.480262652497893D-02D 0.000000000000000D+00D 0.000000000000000D+00D-1.622259472865796D+01D 0.000000000000000D+00D 0.000000000000000D+00\nI 12I 42001                                      \n'
for i_val, a_val, d_val, unknown in re.findall('I(\s*[+-]?[0-9]+\s*)|A(.{8})|D(\s*[+-]?[0-9.]+(?:D[+-]*[0-9]+)?\s*)|(.)', test):
    if i_val: print "I", int(i_val)
    if a_val: print "A", a_val
    if d_val: print "D", float(d_val.replace('D','e'))
    if unkown: raise ValueError(unknown)
BlackJack

`re.Scanner` ist zwar nicht dokumentiert, existiert aber schon seit Ewigkeiten:

Code: Alles auswählen

import re
from pprint import pprint

DATA = (
    'I 19I 41921A6.10-1  A08-Nov-2A015     A09:54:03I 16I 13D 1.000000000000000D+00\n'
    'I 16I 41900I 11ADASHPOT2I 12I 11\n'
    'I 16I 41900I 12ASPRING2 I 12I 11\n'
    'I 12I 42001                                                                                                                  \n'
    'I 223I 42000D 0.000000000000000D+00D 0.000000000000000D+00D 0.000000000000000D+00D 0.000000000000000D+00I 295I 11I 222I 11D 0.000000000000000D+00D 1.506949602122016D+00D 0.000000000000000D+00AFORCED OASCILLATIAON WITH AVISCOELAASTIC DAMAPING    A        A        A        A        \n'
    'I 14I 41911I 11ANALL    \n'
    'I 15I 3111I 11D 0.000000000000000D+00D 0.000000000000000D+00\n'
    'I 19I 3111I 12D 6.625918346244238D-02D 0.000000000000000D+00D 0.000000000000000D+00D-1.478679518984229D+01D 0.000000000000000D+00D 0.000000000000000D+00\n'
    'I 19I 3111I 13D 7.480262652497893D-02D 0.000000000000000D+00D 0.000000000000000D+00D-1.622259472865796D+01D 0.000000000000000D+00D 0.000000000000000D+00\n'
    'I 12I 42001                                      \n'
)

SCANNER = re.Scanner(
    [
        (r'I[- ]\d+', lambda _, s: int(s[1:])),
        (r'A.{8}', lambda _, s: s[1:]),
        (
            r'D[- ]\d+\.\d+D[+-]\d{2}',
            lambda _, s: float(s[1:].replace('D', 'e'))
        ),
    ]
)


def scan(line):
    result, unparsed = SCANNER.scan(line)
    if unparsed.strip():
        raise ValueError('unexpeced trailing stuff: {0!r}'.format(unparsed))
    return result


def main():
    pprint(map(scan, DATA.splitlines()))


if __name__ == '__main__':
    main()
Stoli
User
Beiträge: 17
Registriert: Donnerstag 24. Oktober 2013, 21:02

Sirius3 hat geschrieben:@Stoli: das läßt sich durch einen einfachen regulären Ausdruck lösen:
Genau das habe ich gesucht - hervorragend, danke!
Habe noch ein bisschen was geändert, das "unknown" funktioniert hier auf meinem Rechner nicht, werd es auf einer aktuellen python-Version noch testen.

Das tmp.fil sieht folgendermaßen aus:
tmp.fil

Code: Alles auswählen

*I 19I 41921A6.10-1  A08-Nov-2A015     A09:54:03I 16I 13D 1.000000000000000D+00*
I 16I 41900I 11ADASHPOT2I 12I 11*I 16I 41900I 12ASPRING2 I 12I 11*I 15I 41900I 1
3AMASS    I 12*I 16I 41900I 211ADASHPOT2I 13I 12*I 16I 41900I 212ASPRING2 I 13I 
12*I 15I 41900I 213AMASS    I 13*I 16I 41901I 11D 1.000000000000000D+01D 0.00000
0000000000D+00D 0.000000000000000D+00*I 16I 41901I 12D 1.500000000000000D+01D 0.
000000000000000D+00D 0.000000000000000D+00*I 16I 41901I 13D 2.000000000000000D+0
1D 0.000000000000000D+00D 0.000000000000000D+00*I 15I 41933AD       I 11I 211*I 
15I 41933AM       I 13I 213*I 15I 41933AS       I 12I 212*I 16I 41931AFILE    I 
11I 12I 13*I 16I 41931ANALL    I 11I 12I 13*I 15I 41940I 11AANTIALIAASING    *I 
16I 41940I 12AWarnNodeABCInactiAveDof   *I 232I 41902I 11I 12I 13I 10I 10I 10I 1
0I 10I 10I 10I 10I 10I 10I 10I 10I 14I 15I 16I 10I 10I 10I 10I 10I 10I 10I 10I 1
0I 10I 10I 10*I 212I 41922ASTEADY SATATE VIBARATION OAF 2-DOF ASYSTEM (AVISCOELA
ASTIC DAMAPING)   A        A        *I 12I 42001  

Code: Alles auswählen

import re

with open('tmp.fil','r') as file_input_r:
    with open('output.txt','w') as file_output_w:
        contents = file_input_r.read()
        newcontents = contents.replace('\n','').replace('*I', '\nI')
        for i_val, a_val, d_val, unknown in re.findall('I(\s*[+-]?[0-9]+\s*)|A(.{8})|D(\s*[+-]?[0-9.]+(?:D[+-]*[0-9]+)?\s*)|(.)', newcontents):
            if i_val: file_output_w.write(i_val+'\t')
            if a_val: file_output_w.write(a_val.replace(' ', '')+'\t')
            if d_val: file_output_w.write(d_val.replace('D','e')+'\t')
Im nächsten Schritt werde ich das ganze in ein array überführen, um dann auf dieser Basis mir kleinere outputs spaltenweise zu generieren oder dementsprechend noch Werte zu berechnen.

Danke nochmal :)!
Antworten