#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
1次元プロッタの CUI ファサードクラス
"""
from __future__ import print_function
import six
import os
import sys
from time import sleep
from uGao.QtCom import CommQt
from uGao.uGaoUtil import TempFile, TraceAtt, ConvertEC, STRING_TO_REPLACE_SPACE
if six.PY2:
    import thread as _thread
else:
    import _thread


#######################################
#  MPlot
#######################################
class MPlot(object):
    """
    プロッタのファサードクラス
    Python インタープリタ からプロッタを起動し
    制御するためのユーザインターフェイスを提供
    """
    # プロッタ通信クラスのインスタンスリスト
    plotList = []
    # plotList のロック用
    lck = _thread.allocate_lock()

    #########################################
    def __init__(self, data=None, closeFlag=True):
        """
        コンストラクタ
        @param  data  プロッタに表示するデータ、省略可
        　　　　　　　　エレメントアレイまたはエレメントアレイのリスト
        @closeFlag   親プロセス終了時に、プロッタをクローズするか
        　　　　　　 　　　　　　 否かのフラグ
        @retval 無し
        """
        self.plot = None
        # エレメントコンテナ変換クラスのインスタンス取得
        self.ce = ConvertEC()
        # テンポラリファイルクラスのインスタンス取得
        self.tp = TempFile()

        # プロッタの作成
        self.NewPlot(data, closeFlag)

    #########################################
    def NewPlot(self, data=None, closeFlag=True):
        """
        プロッタを追加し、カレントプロッタとする
        @param  data  プロッタに表示するデータ、省略可
                      エレメントアレイまたはエレメントアレイのリスト
        @param closeFlag  親プロセス終了時に、子プロセスを終了させるかどうかのフラグ
        @retval 無し
        """
        # 引数リストを作成
        pno = len(self.plotList) + 1
        strPno = "%d" % pno

        if closeFlag:
            cflag = "True"
        else:
            cflag = "False"

        arg = ["FastPlotQt.py", strPno, cflag]
        # プロセスID とプロッタ番号からポート番号を生成
        pxx = (os.getpid() % 500) * 20
        portno = 10000 + pxx + pno
        # GUI通信クラスのインスタンス取得
        # p = CommWx()
        p = CommQt()

        # プロセス生成と通信接続に成功したなら
        if p.NewComm(portno, arg):
            # 旧カレントプロッタのアイコン化要求
            self._IconizeCurrent()

            self.lck.acquire()
            # 追加したプロッタをリストへ追加
            self.plotList.append(p)
            # ロックの解放
            self.lck.release()

            # 追加したプロッタをカレントプロッタとする。
            self.plot = p

            # データが指定されていたら
            if data is not None:
                # データを追加
                self.AddData(data)
        else:
            print("\nError!!  Cannot create a new plotter!!.")

    #########################################
    def ChangePlot(self, num=None):
        """
        カレントプロッタを変更する
        @param  num  カレントにするプロッタ番号
        @retval 無し
        """
        if num is None:
            print("\nError!!  Input PlotNumber.")
        else:
            # 整数変換できるか
            try:
                pno = int(num)
            except:
                print('\nError!!  The argument must be integer.')
                return

            # プロッタ番号の範囲チェック
            if pno < 1 or num > len(self.plotList):
                # 引数エラー
                print("\nError!!  No such plotter.")
                return

            # 指定されたプロッタが閉じられていなければ
            if self.plotList[pno - 1].IsAliveComm():
                # 旧カレントプロッタのアイコン化要求
                self._IconizeCurrent()
                # カレントプロッタを変更
                self.plot = self.plotList[pno - 1]
                # 新カレントプロッタの復元要求
                self.plot.PutCommand("doiconize 0\n")
            # 既に閉じている場合は
            else:
                # エラーメッセージを表示
                print("\nThe plotter(%d) has been already closed." % num)

    #########################################
    def _IconizeCurrent(self):
        """
        カレントプロッタをアイコン化する
        @param  無し
        @retval 無し
        """
        # 先に(同一インスタンスの)カレントプロッタがあれば
        if self.plot is not None:
            # カレントプロッタが閉じられていなければ
            if self.plot.IsAliveComm():
                # 旧カレントプロッタのアイコン化要求
                self.plot.PutCommand("doiconize 1\n")

    # [inamura 171225]-->
    #########################################

    def SetAutoScaleY(self, flag=False):
        """
        Set AutoScaseY flag on adding data to plotter
        @param flag
        """
        if isinstance(flag, bool):
            strCmd = "autoscaley %s\n" % (flag)
            self.plot.PutCommand(strCmd)
    # <--[inamura 171225]
    #########################################

    def AddData(self, data=None, isAutoScale=False):
        """
        プロッタにデータを追加
        @param  data  プロッタに追加するデータ
                      エレメントコンテナまたはエレメントコンテナのリスト
                      (プロッタが読み込める形式のデータタプルも可)
        @retval 無し
        """
        if data is None:
            self._EmptyName('ElementContainer')
            return

        self.SetAutoScaleY(isAutoScale)  # [inamura 171225]

        lstDat = []
        # リストか
        if isinstance(data, list):
            # リスト中のエレメントコンテナ毎に変換
            for ec in data:
                ret = self.ce.ConvertEC(ec)
                if ret is None:
                    print("\nArgument is not acceptable.")
                    return
                # Manyo データからPython データタイプへ変換
                lstDat.append(ret)
        # 単一データ
        else:
            # Manyo データからPython データタイプへ変換
            ret = self.ce.ConvertEC(data)
            if ret is None:
                print("\nArgument is not acceptable.")
                return
            lstDat.append(ret)

        # テンポラリファイル名称を取得
        temppath = self.tp.GetTempName()

        if temppath is None:
            # 異常終了
            print("\nError!! Cannot make a temporary file.")
            return

        # オブジェクトをシリアライズしてテンポラリファイルへ書き込む
        ret = self.tp.MakeTempFile(lstDat, temppath)
        # 正常終了か
        if ret == 0:
            # コマンド作成(改行コード付)
            strCmd = "add %s\n" % temppath
            # コマンドの送信要求をカレントプロッタへ送る
            ret = self.plot.PutCommand(strCmd)
        else:
            # 異常終了
            print("\nError!! Cannot make a temporary file.")

    #########################################
    def Remove(self, dnum=0):
        """
        プロッタからデータを削除
        @param  dnum  データ番号、0の場合全部
        @retval 無し
        """
        # データ番号　入力していない場合
        if dnum is None:
            self._EmptyName('Data Number')
        else:
            # 整数変換できるか
            try:
                dno = int(dnum)
            except:
                print('\nError!!  Argument must be integer.')
                return

        # コマンド作成
            strCmd = "remove %d\n" % dno
        # コマンドの送信要求をカレントプロッタへ送る
            ret = self.plot.PutCommand(strCmd)
        # 否定応答を受信したなら
            if ret == "NACK":
                print("Error!!  Data number.")

    #########################################
    def SetLog(self, flag=None):
        """
        ログモード設定
        @param  flag  ログモード True or False
        @retval 無し
        """
        if isinstance(flag, bool):
            # コマンド作成
            # strCmd = "log %d\n" % flag
            if flag:
                strCmd = "log 1\n"
            else:
                strCmd = "log 0\n"
            # コマンドの送信要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)
        else:
            print("\nError!!  The argument must be True or False.")

    #########################################
    def SetLogX(self, flag=None):
        """
        ログモード設定
        @param  flag  ログモード True or False
        @retval 無し
        """
        if isinstance(flag, bool):
            # コマンド作成
            # strCmd = "logx %d\n" % flag
            if flag:
                strCmd = "logx 1\n"
            else:
                strCmd = "logx 0\n"
            # コマンドの送信要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)
        else:
            print("\nError!!  The argument must be True or False.")

    #########################################
    def SetLogY(self, flag=None):
        """
        ログモード設定
        @param  flag  ログモード True or False
        @retval 無し
        """
        if isinstance(flag, bool):
            # コマンド作成
            # strCmd = "log %d\n" % flag
            if flag:
                strCmd = "log 1\n"
            else:
                strCmd = "log 0\n"
            # コマンドの送信要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)
        else:
            print("\nError!!  The argument must be True or False.")

    #########################################
    def SetOverlay(self, flag=None):
        """
        オーバレイモード設定
        @param  flag  オーバレイモード True or False
        @retval 無し
        """
        if isinstance(flag, bool):
            # コマンド作成
            # strCmd = "overlay %d\n" % flag
            if flag:
                strCmd = "overlay 1\n"
            else:
                strCmd = "overlay 0\n"
            # コマンドの送信要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)
        else:
            print("\nError!!  The argument must be True or False.")

    #########################################
    def SetXScale(self, x0=None, x1=None):
        """
        自動スケールモード設定
        @param  x0 X軸始値
        @param  x1 X軸終値
        @retval 無し
        """
        self._makeScaleCommand("xscale", x0, x1)

    #########################################
    def SetYScale(self, y0=None, y1=None):
        """
        自動スケールモード設定
        @param  y0 Y軸始値
        @param  y1 Y軸終値
        @retval 無し
        """
        self._makeScaleCommand("yscale", y0, y1)

    #########################################
    def _makeScaleCommand(self, cmd, r0, r1):
        """
        自動スケールモード設定
        @param  cmd  送信コマンド
        @param  r0  引数1
        @param  r1  引数2
        @retval 無し
        """
        # 引数無しか
        if r0 is None and r1 is None:
            # 自動モード(引数無し)コマンドの送信要求をカレントプロッタへ送る
            self.plot.PutCommand(cmd + '\n')
        # マニュアル指定モード
        else:
            # 数値か
            try:
                rr0 = float(r0)
                rr1 = float(r1)
            except:
                print("\nError!!  The argument1 and 2 must be numeric.")
                return
            # 始値 < 終値か
            if rr0 < rr1:
                strCmd = "%s %.2f %.2f\n" % (cmd, rr0, rr1)

            else:
                print("\nError!!  The argument2 must be larger then the argument1.")
                return
            # コマンドの送信要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)

    #########################################
    def SetOffset(self, xoffset=None, yoffset=None):
        """
        オーバレイ時のオフセット指定
        @param  xoffset  X軸オフセット
        @param  yoffset  Y軸オフセット
        @retval 無し
        """
        # オフセットを入力していない場合
        if xoffset is None or yoffset is None:
            self._EmptyName('XOffset and YOffset')
        # 整数変換できるか
        else:
            try:
                xo = int(xoffset)
                yo = int(yoffset)
            except:
                print("\nError!!  Arguments must be integer.")

            # Xオフセット範囲チェック
            if xo < 0 or xo > 200:
                print("\nError!!  Offset must be between 0 to 200.")
                return
            # Yオフセット範囲チェック
            if yo < 0 or yo > 200:
                print("\nError!!  Arguments must be between 0 to 200.")
                return
            # コマンド作成
            strCmd = "offset %d %d\n" % (xoffset, yoffset)
            # コマンドの送信要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)

    #########################################
    def SetPlotParam(self, dnum=None, **kargs):
        """
        プロットパラメータ指定
        @param  dnum     データNo  または "all"
        @param  **kargs   キーワード引数
                ls        線種　['-', ':','--', '-.','']
                hs        ヒストグラムスタイル　True or False
                lw        線幅　1〜10
                lc        線色　['*', 'b', 'g', 'r', 'c', 'm', 'y', 'k']
                mk        マーカーの種類  ['', '.','o','s','v','d','+','x']
                ms        マーカーのサイズ　1〜10
                mc        マーカーの色　['*', 'b', 'g', 'r', 'c', 'm', 'y', 'k']
                eb        エラーバー指定    True or False
                es        エラーバーのキャップサイズ　1〜10
                sc        エラーバーの色　['*', 'b', 'g', 'r', 'c', 'm', 'y', 'k']
        @retval 無し
        """
        # データ番号を入力しなかった場合
        if dnum is None:
            self._EmptyName('Data Number')
        else:
            # 整数変換できるか
            try:
                dno = int(dnum)
            except:
                print('\nError data number!! The argument 1 must be integer.')
                return
            # キーワード引き数の数を確認
            if len(kargs) == 0:
                print("\nError!!  It needs at least one keyword.")
                print(
                    'Available keywords are "ls", hs", "lw", "lc", "mk", "ms", "mc", "eb", "es" and "ec".')
                return

            # コマンド作成
            strCmd = "plotparam %d" % dno

            # キーワードを取得
            for key in kargs:
                kcmd = ""

                # 線種の指定か
                if key == "ls":
                    kcmd = self._CheckValue(
                        TraceAtt.linestyle, key, kargs[key])
                # ヒストグラムスタイル指定か
                elif key == "hs":
                    if kargs[key] is True:
                        kcmd = " hs=%d" % 1
                    elif kargs[key] is False:
                        kcmd = " hs=%d" % 0
                    else:
                        print(
                            '\nError value!!  The value for "hs" must be True or False.')
                # 線幅の指定か
                elif key == "lw":
                    kcmd = self._CheckNum(key, kargs[key])
                # 線色の指定か
                elif key == "lc":
                    kcmd = self._CheckValue(TraceAtt.color, key, kargs[key])

                # マーカの指定か
                elif key == "mk":
                    kcmd = self._CheckValue(TraceAtt.marker, key, kargs[key])
                # マーカーサイズの指定か
                elif key == "ms":
                    kcmd = self._CheckNum(key, kargs[key])
                # マーカー色の指定か
                elif key == "mc":
                    kcmd = self._CheckValue(TraceAtt.color, key, kargs[key])

                # エラーバー指定か
                elif key == "eb":
                    if kargs[key] is True:
                        kcmd = " eb=%d" % 1
                    elif kargs[key] is False:
                        kcmd = " eb=%d" % 0
                    else:
                        print(
                            '\nError value!!  The value for "eb" must be True or False.')
                # キャップサイズの指定か
                elif key == "es":
                    kcmd = self._CheckNum(key, kargs[key])
                # エラーバー色の指定か
                elif key == "ec":
                    kcmd = self._CheckValue(TraceAtt.color, key, kargs[key])

                # キーワードエラー
                else:
                    print("\nError Keyword !!")
                    print(
                        'Available keywords are "ls", "lw", "lc", "mk", "ms", "mc", "eb", "es" and "ec".')
                    return

                # キーワード引数文字列が正常に作成できていたなかったなら
                if kcmd == "":
                    # 異常終了
                    return

                # コマンドにパラメータ文字列を連結
                strCmd = strCmd + kcmd

            # 改行コードを付加
            strCmd = strCmd + '\n'

            # コマンドの送信要求をカレントプロッタへ送る
            ret = self.plot.PutCommand(strCmd)
            # 否定応答を受信したなら
            if ret == "NACK":
                print("\nError!!  Data number.")

    #########################################
    def _CheckValue(self, lst, key, value):
        """
        指定されたキーの値をチェック
        @param  lst 　有効な値のリスト
        @param  key   キー文字列
        @param  value 値の文字列
        @retval キーワード引き数文字
        """
        # 指定された値はリスト中に存在するか
        if value in lst:
            # リスト中の値の順番を探す
            i = 0
            for item in lst:
                # リスト中にあるか
                if item == value:
                    # 文字列のキーワード引き数を作る
                    kcmd = " %s=%s" % (key, lst[i])
                    # 作成したキーワード引き数を返す
                    return kcmd
                i += 1

        # 不正な値だったなら
        else:
            # インストラクションメッセージを作成
            strMsg = "Avairable values for %s are " % key
            # 指定可能な値を列挙
            # 最後の2個の値を除き、カンマ付きで列挙
            for i in range(len(lst) - 2):
                item = '"%s", ' % lst[i]
                strMsg = strMsg + item
            # 最後の2個を連結
            i += 1
            j = i + 1
            item = '"%s" and "%s"' % (lst[i], lst[j])
            strMsg = strMsg + item

            # メッセージを表示
            print("\nValue Error!!")
            print(strMsg)
            # ヌル文字列を返す
            return ""

    #########################################
    def _CheckNum(self, key, value):
        """
        指定されたキーの値をチェック
        @param  key   キー文字列
        @param  value 値の文字列
        @retval 引き数文字
        """

        # 整数変換可か
        try:
            no = int(value)
        except:
            print('\nError!!  Value for "%s" must be integer.' % key)
            return ""
        if no < 1 or no > 10:
            print('\nError!! Value for "%s" must be between 1 to 10.' % key)
            return ""

        # 数値のキーワード引き数を作る
        kcmd = " %s=%.d" % (key, no)
        return kcmd

    #########################################
    def ChangeOrder(self, no1=None, no2=None):
        """
        指定されたキーの値をチェック
        @param  no1   変更前の順番
        @param  no2   変更後の順番
        @retval 無
        """
        # 引数を2つ入力していなかった場合
        if no1 is None or no2 is None:
            print("\nError!! Input OrderNumbers before change and after change.")
        # 整数変換可か
        else:
            try:
                n1 = int(no1)
                n2 = int(no2)
            except:
                print('\nError!! Arguments must be integer.')
                return ""
            if n1 < 1 or n2 < 1:
                print("\nError!!  Arguments must not be 0.")
            # コマンドを作成し送信
            strCmd = "shuffle %d %d\n" % (n1, n2)
            ret = self.plot.PutCommand(strCmd)
            # 否定応答を受信したなら
            if ret == "NACK":
                print("Data number error!!")

    #########################################
    def Close(self, plot=None):
        """
        カレントのプロッタ画面を閉じる
        @param  plot プロッタ番号
                    引数無しのときは、カレントプロッタ
                    "All" とすると、開いている全画面を閉じる
        @retval 無し
        """
        # カレントプロッタのクローズ要求か
        if plot is None:
            self.plot.PutCommand("close\n")

        # 全画面クローズ要求か
        elif plot == 0:
            # 全プロッタに対し
            for pl in self.plotList:
                # 生存していれば
                if pl.IsAliveComm():
                    # クローズ要求を送信
                    pl.PutCommand("close\n")

        # 指定プロッタのクローズか
        else:
            # 数値か
            try:
                pnum = int(plot)
            except:
                print('\nError plotter number.')
                return

            # プロッタ番号の範囲チェック
            if pnum > 0 and pnum <= len(self.plotList):
                # 指定プロッタのインスタンス取得
                pl = self.plotList[pnum - 1]
                # クローズ要求を送信
                pl.PutCommand("close\n")
            else:
                # 引数エラー
                print("\nError!!  There is no such plotter.")

    #########################################
    def ChangePage(self, pageNo=None):
        """
        ページを変更するする
        @param  pageNo  ページ番号
        @retval 無し
        """
        if pageNo is None:
            self._EmptyName('Page No')
        else:
            # 整数変換できるか
            try:
                pno = int(pageNo)
            except:
                print('\nError!!  Argument must be integer.')
                return
            if pno > 0:
                strCmd = "page %d\n" % pno
                # ページ変更要求をカレントプロッタへ送る
                self.plot.PutCommand(strCmd)
            else:
                print('\nError!!  Argument must not be zero.')

    #########################################
    def SetTraceNum(self, traceNo=None):
        """
        ページを変更する
        @param  pageNo  トレース番号
        @retval 無し
        """
        # トレース番号　入力していない場合
        if traceNo is None:
            self._EmptyName('TraceNumber')
        else:
            # 整数変換できるか
            try:
                tno = int(traceNo)
            except:
                print('\nError!!  Argument must be integer.')
                return
            if tno > 0 and tno < 51:
                strCmd = "tracenum %d\n" % tno
            # ページ変更要求をカレントプロッタへ送る
                ret = self.plot.PutCommand(strCmd)
            # 否定応答を受信したなら

                if ret == "NACK":
                    print(
                        '\nError!! The number of trace must be less than 4 in indivisual mode.')
            else:
                print('\nError!!  Argument must be between 1 to 50.')

    #########################################
    def SetXLabel(self, xlabel=None):
        """
        X軸のラベル設定
        @param  xlabel　横軸のラベル文字列
        @retval 無し
        """
        if xlabel is None or xlabel == "":
            self._EmptyName('xlabel')
        else:
            try:
                # 半角英数字を入力したか
                six.u(xlabel)
            except:
                self._AsciiName('xlabel')
            else:
                # コマンド作成
                strCmd = "xlabel %s\n" % xlabel
            # 座標ラベル変更要求をカレントプロッタへ送る
                self.plot.PutCommand(strCmd)

    #########################################

    def SetYLabel(self, ylabel=None):
        """
        X軸のラベル設定
        @param  ylabel  縦軸のラベル文字列
        @retval 無し
        """
        if ylabel is None or ylabel == "":
            self._EmptyName('ylabel')
        else:
            try:
                # 半角英数字を入力したか
                six.u(ylabel)
            except:
                self._AsciiName('ylabel')
            else:
                # コマンド作成
                strCmd = "ylabel %s\n" % ylabel
            # 座標ラベル変更要求をカレントプロッタへ送る
                self.plot.PutCommand(strCmd)

    #########################################
    def SetMainTitle(self, main=None):
        """
        メインタイトル設定
        @param  main　メインタイトル
        @retval 無し
        """
        if main is None or main == "":
            self._EmptyName('MainTitle')
        else:
            try:
                # 半角英数字を入力したか
                six.u(main)
            except:
                self._AsciiName('MainTitle')

            else:
                # コマンド作成
                main = main.replace(" ", STRING_TO_REPLACE_SPACE)
                strCmd = "maintitle %s\n" % main
                # タイトル変更要求をカレントプロッタへ送る
                self.plot.PutCommand(strCmd)

    #########################################

    def SetSubTitle(self, sub=None):
        """
        サブタイトル設定
        @param  sub　サブタイトル
        @retval 無し
        """
        if sub is None or sub == "":
            self._EmptyName('SubTitle')
        else:
            try:
                # 半角英数字を入力したか
                six.u(sub)
            except:
                self._AsciiName('SubTitle')
            else:
                # コマンド作成
                sub = sub.replace(" ", STRING_TO_REPLACE_SPACE)
                strCmd = "subtitle %s\n" % sub
        # タイトル変更要求をカレントプロッタへ送る
                self.plot.PutCommand(strCmd)

    #########################################
    def LoadFromText(self, filepath):
        """
        Load data from text file saved as MPlot
        @param filepath (str) path to file to load
        @retval None
        """
        if os.path.exists(filepath):
            strCmd = "loaddatafromtext {}\n".format(filepath)
            self.plot.PutCommand(strCmd)
        else:
            raise UserWarning(
                "MPlot::LoadFromText >>> Not found such file={}".format(filepath))

    #########################################
    def SaveAsText(self, filepath, isHist=False, useMask=False, maskVal=None):
        """
        Save data as text file
        @param filepath (str) path to file
        @param isHist (bool) save text as histogram
        @param useMask (bool) Use mask value user defines
        @param maskVal (float) mask value user defines
        @retval None
        """
        p_isHist = "FALSE"
        p_useMask = "FALSE"
        p_maskVal = "NONE"
        if useMask:
            p_useMask = "TRUE"
            if maskVal is not None:
                p_maskVal = "%g".format(float(maskVal))
        strCmd = "savedataastext {} {} {} {}\n".format(
            filepath, p_isHist, p_useMask, p_maskVal)
        self.plot.PutCommand(strCmd)

    #########################################
    def Print(self):
        """
        カレントプロッタを印刷する
        @param  無し
        @retval 無し
        """
        # 印刷要求をカレントプロッタへ送る
        answer = self.plot.PutCommand("print\n")
        # Windows の場合、タイムアウトによる NACK が返ってきたなら
        if answer == "NACK" and os.name == "nt":
            print("\nPlease answer to the print dialog.")

    #########################################
    def Save(self, fname=None):
        """
        画像ファイルの保存
        @param  ファイル名
        @retval 無し
        """
        # 引数無し時のプロテクト
        if fname is None:
            self._EmptyName('filename')
            return
        try:
            six.u(fname)
        except:
            # 全角文字が含まれている場合エラーとする
            self._AsciiName('Filename')
            return
        work = fname.split(os.sep)
        print(work)
        # ファイル名取り出し
        filename = os.path.basename(fname)
        path, ext = os.path.splitext(filename)
        # 拡張子を除くファイル名の長さは1以上か
        if len(path) > 1:
            # サポートしている拡張子か
            if ext == ".png" or ext == ".ps" or ext == ".eps":
                strCmd = "save" + ' ' + fname + '\n'
                # 画像保存要求をカレントプロッタへ送る
                self.plot.PutCommand(strCmd)
            else:
                print("\nError!!  Extention must be png, ps, or eps.")
        else:
            print("\nError!! Invalid file name.")

    #########################################
    def _AsciiName(self, name):
        """
        Ascii文字入力を促すメッセージ表示
        @param name 入力項目
        @retval 無し
        """
        print("\nCode error!! %s must be ASCII string." % name)

    #########################################
    def _EmptyName(self, name):
        """
        引数を入力しなかった場合入力を促すメッセージ表示
        @param name 入力項目
        @retval 無し
        """
        print("\nMissing argument error!! Input %s." % name)

    #########################################
    def GetAttr(self, attr):
        """
        属性の取得
        @param  attr 属性を示す文字列
        @retval 属性(文字列)
        """
        # 属性のデータ型を取得
        try:
            typeno = TraceAtt.attrType[attr]
        except:
            print("\nError!! Attribute key. See following.")
            strMsg = ""
            # キーの一覧を表示
            for att in TraceAtt.attrType:
                strTmp = '%s, ' % att
                strMsg = strMsg + strTmp
            print(strMsg)
        else:
            strComd = "getattr %s %d\n" % (attr, typeno)
            # 属性取得要求をカレントプロッタへ送る
            answer = self.plot.PutCommand(strComd)
            if answer == "NACK":
                return

            fr = file(answer, "rb")
            data = pickle.load(fr)
            # リストまたはディクショナリ
            if typeno == 4:
                try:
                    # テンポラリファイルを読み込む
                    fr = file(answer, "rb")
                    # データを復元(デシリアライズ)
                    data = pickle.load(fr)
                except:
                    print("\nError!! Can't read temp file.")
                else:
                    # テンポラリファイルをクローズ
                    fr.close()
                    # テンポラリファイルを削除
                    os.remove(answer)
                    # 復元したデータを表示
                    print("\n%s : " % attr)
                    print(data)
            # 数値等
            else:
                print("\n%s : %s" % (attr, answer))


#####################################################################
if __name__ == '__main__':
    """
    以下はテスト用のスクリプト

    """
    import platform
    if sys.platform == "win32":
        _PYTHONBIN = "python"
    elif platform.python_version_tuple()[0] == '2':
        _PYTHONBIN = "python2"
    else:
        _PYTHONBIN = "python3"
    epath = os.path.dirname(sys.argv[0])
    os.system("{} {}/FastPlotQt.py".format(_PYTHONBIN, epath))
