2016-07-18 9 views
2

Ich möchte einige Daten von LTspice mit Python und Matplotlib plotten, und ich suche nach einer Lösung zum Importieren der exportierten Plot-Daten von LTspice in Python.Python lesen LTspice plot export

fand ich keine Möglichkeit, dies mit Pandas zu tun, da das Format der Daten wie folgt aussieht:

5.00000000000000e+006\t(2.84545891331278e+001dB,8.85405282381414e+001°) 

Gibt es eine Möglichkeit, dies mit Pandas zu importieren (zB mit einem eigenen Dialekt) oder tut jemand kennen Sie eine einfache Problemumgehung (z. B. Lesen der Datei Zeile für Zeile und Extrahieren der Werte)?

Um die Sache noch schlimmer zu machen, wenn die Handlung von mehreren Schritten zu exportieren, werden die Daten durch die Leitungen wie

Step Information: L=410n (Run: 2/4) 

In Java getrennt ich ein Objekt Scanner verwendet haben, können die Daten zu lesen. Gibt es eine ähnliche Funktion in Python oder sogar einen einfacheren Weg, um die Plotdaten in Python zu bekommen?

Antwort

1

Ich bin nicht vertraut mit exportierten Plot-Daten von LTspice, also gehe ich davon aus, dass die Formatierung der von Ihnen bereitgestellten Beispielzeilen für alle Zeiten gültig ist.

Mit Blick auf die IO-Tools Abschnitt der Pandas-0.18-Dokumentation (here), sehe ich keine gebrauchsfertige Parser-Dienstprogramm für Ihr Datenformat. Das erste, was einem in den Sinn kommt, ist das eigene Parsen und Vorbereiten, bevor man einen Pandas-Datenrahmen ausfüllt.

Ich gehe davon aus, dass der entscheidende Teil Ihres Problems ist, die Datendatei zu analysieren, es ist eine Weile her, seit ich mit Pandas und Matplotlib gespielt habe, also erwarten Sie Fehler in Bezug auf diese.

Beispiel

Hier ist eine schnelle & schmutzig python3 Skript Ihre Daten in eine Liste von Wörterbüchern zu analysieren, eine Pandas Datenrahmen mit ihm bauen und zeichnen sie die plot Methode der Datenrahmen verwenden. Ich habe versucht, die Schritte in den Kommentaren zu erklären:

# ltspice.py 
""" Use it as: 
    > python3 ltspice.py /path/to/datafile """ 

import pandas 
import sys 

data_header = "Time Gain Degree".split() 

# Valid line example: 
# 5.00000000000000e+006\t(2.84545891331278e+001dB,8.85405282381414e+001°) 

def parse_line(linestr): 
    # ValueError and IndexError exceptions are used to mark the failure of 
    # the parse. 
    try: 
     # First we split at the '\t' character. This will raise ValueError if 
     # there is no \t character or there is more than 1 \t 
     timestr, rest = linestr.split('\t') 

     # Then we find the indexes of the '(' and ')' in the rest string. 
     parenst, parenend = (rest.find('(')+1, rest.find(')')) 
     if (parenst == -1) or (parenend == -1): 
      # find() method returns -1 if nothing is found, I raise ValueError 
      # to mark it as a parsing failure 
      raise ValueError 

     # rest[parenst:parenend] returns the string inside parens. split method 
     # splits the string into words separated by the given character (i.e. 
     # ',') 
     powstr, degstr = rest[parenst:parenend].split(',') 

     # converting strings into floats. Replacing units as necessary. 
     time = float(timestr) 
     power = float(powstr.replace('dB', '')) 

     # this will fail with python 2.x 
     deg = float(degstr.replace('°', '')) 

     # You can use dict() instead of tuple() 
     return tuple(zip(data_header, (time, power, deg))) 

    except (ValueError,IndexError) as e: 
     return None 


def fileparser(fname): 
    """ A generator function to return a parsed line on each iteration """ 
    with open(fname, mode='r') as fin: 
     for line in fin: 
      res = parse_line(line) 
      if res is not None: 
       yield res 

def create_dataframe(fname): 
    p = fileparser(fname) 
    # rec is a tuple of 2-tuples that can be used to directly build a python 
    # dictionary 
    recs = [dict(rec) for rec in p] 
    return pandas.DataFrame.from_records(recs) 

if __name__ == '__main__': 
    data_fname = sys.argv[1] 
    df = create_dataframe(data_fname) 

    ax = df.plot(x='Time', y='Gain') 
    fig = ax.get_figure() 
    fig.savefig('df.png') 

Sie kopieren in einen Texteditor diesen Code und als ltspice.py und führen Sie es mit python3 ltspice.py yourdata.dat von Ihrem Terminal speichern.

Beachten Sie, dass die Funktion parse_line tatsächlich ein Tupel von 2-Tupeln in Form von ('Schlüssel', Wert) zurückgibt, wobei 'Schlüssel' den Spaltennamen darstellt. Dieser Wert wird dann verwendet, um die Liste der Wörterbücher in der create_dataframe-Funktion zu erstellen.

Extra-

Ich schrieb ein anderes Skript, das Verhalten zu testen:

# test.py 
import random 
from ltspice import fileparser 


def gen_data(): 
    time = random.randint(0,100)*1e6 
    db = random.lognormvariate(2,0.5) 
    degree = random.uniform(0,360) 
    # this is necessary for comparing parsed values with values generated 
    truncate = lambda x: float('{:.15e}'.format(x)) 
    return (truncate(time),truncate(db),truncate(degree)) 


def format_data_line(datatpl): 
    time, db, degree = datatpl[0], datatpl[1], datatpl[2] 
    formatted = "{0:.15e}\t({1:.15e}dB,{2:.15e}°)\n" 
    return formatted.format(time, db, degree) 


def gen_ignore_line(): 
    tmpl = "Step Information: L={}n (Run:{}/{})\n" 
    l = random.randint(100,1000) 
    r2 = random.randint(1,100) 
    r1 = random.randint(0,r2) 
    return tmpl.format(l,r1,r2) 


def create_test_file(fname, valid_count, invalid_count): 
    """ Creates a test file containing data lines mixed with lines to be 
    ignored. Returns the data created. 
    valid_count: number of the actual data lines 
    invalid_count: number of the to-be-ignored lines 
    """ 
    header = 'Time Gain Degree'.split() 
    data = [] 
    formatteddatalines = [] 
    for i in range(valid_count): 
     unfmtdata = gen_data() 
     data.append(tuple(zip(header, unfmtdata))) 
     formatteddatalines.append(format_data_line(unfmtdata)) 

    invalidlines = [] 
    for i in range(invalid_count): 
     invalidlines.append(gen_ignore_line()) 

    lines = formatteddatalines + invalidlines 
    random.shuffle(lines) 
    with open(fname, mode='w') as fout: 
     fout.writelines(lines) 

    return data 

if __name__ == '__main__': 
    fname = 'test.data' 
    validcnt = 10 
    invalidcnt = 2 

    validdata = create_test_file(fname, validcnt, invalidcnt) 
    parseddata = [data for data in fileparser(fname)] 

    # Note: this check ignores duplicates. 
    assert(set(validdata) == set(parseddata)) 
+0

Vielen Dank für diese Lösung, das hat für mich funktioniert! Ich fügte eine Überprüfung jeder Zeile mit 'str.startswith ("Step Information") ' und dadurch die verschiedenen Schritte in eine Liste von DataFrames getrennt, die nun einwandfrei funktioniert – RobertAlpha

+0

Froh, dass es geklappt hat :) Gern geschehen! –

1

ich ein Python-Reader für LTSpice Simulation Ausgabedateien geschrieben haben, die Sie hier finden können: LTSPy. Es gibt auch einige Beispieldateien zur Verwendung des Lesers hier: exltspy.zip. Hoffe das ist nützlich. (Ich entschuldige mich im Voraus für meine schlampigen Programmierpraktiken).

+0

unglücklicherweise, @RobertAlpha hat eine Version für Python 3.x angefordert. Planen Sie, auf die neue Version von Python zu wechseln? – Paddy