2016-07-18 11 views
2

私はLTspiceとmatplotlibを使ってLTspiceからデータをプロットしたいのですが、PythonのLTspiceからエクスポートされたプロットデータをインポートするソリューションを探しています。PythonはLTspiceプロットをエクスポートします

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

(自身の方言で例えば)パンダでこれをインポートする可能性があるか、誰かのことを行います。データの形式は、次のようになりますので、

私は、パンダを使用してこれを行うには方法を見つけません簡単な回避策(ファイルを行単位で読み込み、値を抽出するなど)を知っていますか?

さらに悪いことに、複数のステップのプロットをエクスポートするとき、データはJavaで

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

のような行で区切られて、私はデータを読み取ることがスキャナオブジェクトを使用している場合があります。 Pythonにも同様の機能があるのですか?あるいは、プロットデータをPythonに取り込むための簡単な方法ですか?

答えて

1

私はLTspiceからエクスポートされたプロットデータに慣れていないので、あなたが指定したサンプル行の書式設定は常に有効です。

pandas-0.18ドキュメント(here)のIOツールのセクションを見ると、データフォーマット用のすぐに使えるパーサーユーティリティはありません。最初に気になることは、パンダのデータフレームに記入する前に、独自の解析と準備を行うことです。

私はあなたの問題の重要な部分がデータファイルを解析することを前提としています。私はpandasとmatplotlibで遊んでいたのでしばらく経っています。ここで

は、辞書のリストにあなたのデータを解析することでパンダのデータフレームを構築し、データフレームのplotメソッドを使用して、それをプロットするために迅速&汚いのpython3スクリプトです。私はコメントで手順を説明しようとした:

# 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') 

テキストエディタにこのコードをコピーしてltspice.pyとして保存し、あなたの端末からpython3 ltspice.py yourdata.datでそれを実行することができます。

実際には、parse_line関数は( 'key'、value)の形で2タプルのタプルを返します。ここで 'key'は列名を表します。この値を使用して、create_dataframe関数内の辞書のリストを構築します。

エクストラ

私は動作をテストするために別のスクリプトを書いた:LTSPy

# 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

このソリューションをありがとう、これは私のために働いた! 私は各行のチェックを 'strで追加しました。startswith( "ステップ情報") ' これにより、異なるステップをDataFramesのリストに分割しました。これは現在完全に動作します – RobertAlpha

+0

うれしいことです:)あなたは大歓迎です!残念ながら –

1

私はあなたがここで見つけることができますLTSpiceシミュレーション出力ファイルのためのPythonのリーダーを書かれています。また、ここでリーダーを使用する方法に関するいくつかの例のファイルがあります:exltspy.zip。それが使用の希望です。 (私はあまりにも酷いコーディングのために事前にお詫びします)。

+0

、@RobertAlphaはPython 3.xのバージョンをリクエストしました。 Pythonの新しいバージョンに移行しようとしていますか? – Paddy

関連する問題