fmatTranspose のソースコード

#!
# coding: utf-8
# Copyright (C) 2016 TOPS SYSTEMS
### @file fmatTranspose.py
### @brief transpose Data dumper FLT matrix.
###
### DataDumperによりダンプされた配列を整形する
### (1) 転置
### (2) レジスタ長にあわせたゼロフィル
### 
### Contact: izumida@topscom.co.jp
###
### @author: M.Izumida
### @date: December 2, 2016
###
# v01r01 newly created
# v01r02 2016/12/14 (2)の機能を追加
# 
# Written for Python 2.7 (NOT FOR 3.x)
#=======================================================================
# インポート宣言
import sys
import re
import argparse
import os
import struct
from datetime import datetime
#=======================================================================
# バージョン文字列
versionSTR = "fmatTranspose.py v01r02b Tops Systems (pgm by mpi)"
#=======================================================================
# 共通サブルーチン
#-------------------------------------------------------------------
def errPrint(mes, opt=True):
    """errPrint.

    エラー出力へのメッセージ表示
    optがTrueであれば改行も行う
    後の始末はその後で別に書くこと
    """
    sys.stderr.write(mes)
    if opt:
        sys.stderr.write('\n')

#-------------------------------------------------------------------
def stdExceptionHandler(mes):
    """standard Exception Handler.

    エラーメッセージを送出し、デバッグのための情報を出力する
    """
    errPrint("Exception Captured: " + str(mes))
    errPrint("0:" + str(sys.exc_info()[0]))
    errPrint("1:" + str(sys.exc_info()[1]))
    errPrint("2:" + str(sys.exc_info()[2]))

#-------------------------------------------------------------------
def tryIntParse(st, dval, radix=10):
    """try Parse string to Integer

    文字列stをパースして整数化できれば値を返す、できなければデフォルト値dvalを返す
    """
    try:
        work = int(st, radix)
    except:
        return dval
    return work

#=======================================================================
# 解析オプション クラス
class Options:
    """Options Class.

    グローバルオプションを保持するクラス
    """
    pass

#=======================================================================
# FLTファイルリーダライタ クラス
[ドキュメント]class FltFileReaderWriter: """FltFile ReaderWriter Class. FLTファイルを読みとり、ターゲットの配列であれば いったん配列として内部に保持し、 転置してから出力する。 そうでない行についてはそのままスルーで出力する。 """ #-------------------------------------------------------------------- def __init__(self, inputFnam, outputFnam, targetArrayName, mode=0): """FLT File Reader Constructor コンストラクタ 入力ファイル名 inputFnam 処理対象配列名 targetArrayName """ self.iFname = inputFnam self.oFname = outputFnam self.tName = targetArrayName self.aNameT = "" self.md = mode self.ZERO = 0 # レコードヘッダ、トレイラの検索表現 self.headerRE = re.compile("^\@([a-zA-Z_][a-zA-Z0-9_]*)\<FLOAT\>\[([0-9]+)\,\s*([0-9]+)\]\s*\{") self.trailerRE = re.compile("^}\s*nREC\=([0-9]+)\,\s*CONV_ERR_CODE\=([0-9]+)\,\s*CONV_ERR_COUNT\=([0-9]+)"); # 配列データ保持構造 self.clearArray() self.inData = False # ファイルデータ保持構造 self.Buffer = [] self.nLine = 0 # 反転モード self.REV = False # debug self.debug = False self.verbose = False #--------------------------------------------------------------------
[ドキュメント] def clearArray(self): """Clear Array method 配列の一時記憶構造を初期化する """ self.Array = [] self.iX = 0 self.iY = 0 self.nData = 0 self.xCnt = 0 self.yCnt = 0 self.tempLine = []
#--------------------------------------------------------------------
[ドキュメント] def read(self): """Read method FLTファイルを読み込むメソッド """ try: with open(self.iFname, 'r') as f: for line in f: if self.rLine(line): return False except: stdExceptionHandler("Error: in file reading = " + self.iFname) return False return True
#--------------------------------------------------------------------
[ドキュメント] def rLine(self, lin): """Read Line method 読み取った1行を処理するメソッド inData フラグが立っていれば、 .. ①レコード末尾行であればパラメータを読み取ってチェックする .. チェック結果で問題あればエラー終了 .. 問題なければ貯めてある配列をmodeに応じて整形したバッファに出力する .. inDataフラグを下す .. ②レコード末尾行でなければデータ行として、配列にため込む inData フラグが立っていなければ .. ①配列ヘッダ行であればパラメータを読み取って該当か否か判断する。 .. 該当データであれば inData フラグを立て、配列を初期化して処理に進む。 .. ②それ以外であればそのままバッファに転送する 問題発生するとエラーメッセージをstderrに書いた後、Trueを返す """ if self.inData: trailer = self.trailerRE.match(lin) if trailer: if self.xCnt != 0: print "WARNING: X=", self.xCnt, " Y=", self.yCnt nREC = tryIntParse(trailer.group(1), 0) if self.nData != nREC: errPrint("ERROR: " + lin ) errPrint("ERROR: Trailer size mismatch. Actual=" + str(self.nData) + " nREC=" + str(nREC)) return True if self.md == 1: self.zerofill() else: self.transpose() self.inData = False else: dlis = lin.split(",") for item in dlis: fdata = item.strip() if '.' not in fdata: continue self.tempLine.append(fdata) self.nData += 1 self.xCnt +=1 if self.xCnt >= self.iX: if self.debug: print "Y:" + str(self.yCnt) + " X:" + str(self.xCnt) + ":" + str(self.iX) + ":#=" + str(self.nData) self.Array.append(self.tempLine) self.yCnt += 1 if self.yCnt > self.iY: errPrint("ERROR: Too much data Y=" + str(self.yCnt) + ":" + str(self.iY)) return True self.xCnt = 0 self.tempLine = [] else: header = self.headerRE.match(lin) if header: aname = header.group(1) if self.verbose: print "Find header:" + aname if aname.startswith(self.tName): self.clearArray() if self.md == 1: self.aNameT = aname + "Z" else: self.aNameT = aname + "T" self.iX = tryIntParse(header.group(2), 0) self.iY = tryIntParse(header.group(3), 0) if (self.iX * self.iY) < 1: errPrint("ERROR: Unexpected Array size ?=" + lin) return True self.inData = True if self.verbose: print "-->" + self.aNameT else: self.Buffer.append(lin) self.nLine += 1 else: self.Buffer.append(lin) self.nLine += 1 return False
#--------------------------------------------------------------------
[ドキュメント] def transpose(self): """Transpose method 配列を転置してバッファに送るメソッド """ lineBuffer = "@" + self.aNameT + "<FLOAT>[" + str(self.iY) + ", " + str(self.iX) + "] {\n" self.Buffer.append(lineBuffer) idx = 0 lineBuffer = "" for v in range(0, self.iX): for u in range(0, self.iY): BLK = self.Array[u] ELEM = BLK[v] lineBuffer += ELEM + ", " idx += 1 if (idx % 16) == 0: lineBuffer += "\n" self.Buffer.append(lineBuffer) lineBuffer = "" if (idx % 16) != 0: self.Buffer.append(lineBuffer + "\n") lineBuffer = "} nREC=" + str(self.nData) + ", CONV_ERR_CODE=0, CONV_ERR_COUNT=0\n" self.Buffer.append(lineBuffer)
#--------------------------------------------------------------------
[ドキュメント] def zerofill(self): """Zero Fill method データ要素+ZEROフィル指定個数分の0で16要素となるようにしてバッファに送るメソッド 横方向iX個毎にこの操作を行う。iXに余りがでる場合も残りはゼロフィル """ dNum = 16 - self.ZERO #1行に入れるデータ要素の個数 if (self.iX % dNum) == 0: nLine = self.iX / dNum #ゼロフィルによって作るべき行数 else: nLine = (self.iX / dNum) + 1 #ゼロフィルによって作るべき行数 lineBuffer = "@" + self.aNameT + "<FLOAT>[" + str(nLine*16) + ", " + str(self.iY) + "] {\n" self.Buffer.append(lineBuffer) idx = 0 lineBuffer = "" for u in range(0, self.iY): for v in range(0, self.iX): BLK = self.Array[u] ELEM = BLK[v] lineBuffer += ELEM + ", " idx += 1 if (v % dNum) == (dNum - 1): for i in range(0, self.ZERO): lineBuffer += "0, " idx += 1 if (idx % 16) == 0: lineBuffer += "\n" self.Buffer.append(lineBuffer) lineBuffer = "" if (idx % 16) != 0: for i in range(0, 16 - (idx % 16)): lineBuffer += "0, " self.Buffer.append(lineBuffer + "\n") lineBuffer = "} nREC=" + str(nLine * 16 * self.iY) + ", CONV_ERR_CODE=0, CONV_ERR_COUNT=0\n" self.Buffer.append(lineBuffer)
#--------------------------------------------------------------------
[ドキュメント] def write(self): """Write method. バッファをファイルを出力する """ try: with open(self.oFname, 'w') as f: for lin in self.Buffer: f.write(lin) except: stdExceptionHandler("ERROR: in file writing = " + self.oFname) return False return True
#======================================================================= # メインプログラム def main(): """main. メインプログラム """ #----------------------------------------------------------------------- # コマンドラインオプション処理 # parser = argparse.ArgumentParser(description='fmatTranspose.') parser.add_argument('--IN', nargs=1, help='Specify FLT input file name.') parser.add_argument('--OUT', nargs=1, help='Specify FLT output file name.') parser.add_argument('--TA', nargs=1, help='Specify Target array name.') parser.add_argument('--ZERO', nargs=1, help='Specify number of zerofill(1-15).') parser.add_argument('-r', dest='rev', help='Reverse mode(NOT SUPPORTED YET).', action='store_true', default=False) parser.add_argument('-d', dest='debug', help='Debug mode, print debug information.', action='store_true', default=False) parser.add_argument('-v', dest='verbose', help='Verbose mode.', action='store_true', default=False) parser.add_argument('-V', dest='VERSION', help='Show Version, then exit', action='store_true', default=False) args = parser.parse_args() #----------------------------------------------------------------------- # Version 表示 # print versionSTR if args.VERSION: sys.exit(0) #----------------------------------------------------------------------- # ファイル名処理 # if args.IN is None: errPrint('ERROR: NO input file!!!') sys.exit(1) else: inFname = args.IN[0] if not os.path.isfile(inFname): errPrint('ERROR: INPUT file, NOT EXIST.') sys.exit(1) #----------------------------------------------------------------------- # パラメータ処理 # mode = 0 ... transpose, 1...zero fill, 2...Separate Channel if args.TA is None: errPrint('ERROR: NO target array name!!!') sys.exit(1) else: ta = args.TA[0] mode = 0 # Default transpose dfext = "_transpose.flt" if args.ZERO is not None: mode = 1 zero = tryIntParse(args.ZERO[0], 0) if (zero < 1) or (zero > 15): errPrint('ERROR: number of Zero fill. ?=' + args.ZERO[0]) sys.exit(1) dfext = "_zero.flt" else: zero = 0 if args.OUT is None: outFname = ta + dfext else: outFname = args.OUT[0] #----------------------------------------------------------------------- # 実処理 # flt = FltFileReaderWriter(inFname, outFname, ta, mode) flt.verbose = args.verbose flt.debug = args.debug flt.ZERO = zero flt.REV = args.rev if flt.read(): if not flt.write(): sys.exit(1) else: sys.exit(1) #終了メッセージ today = datetime.today() print "-" * 50 print today.strftime("FINISH: %Y/%m/%d %H:%M:%S") #----------------------------------------------------------------------- # 正常終了 # sys.exit(0) #======================================================================= # メインプログラムの起動 if __name__ == "__main__": main()