#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
U2IF.py
uGao 汎用2次元プロッタ I/F
"""
from __future__ import print_function
import time
import os
import logging
import Manyo
from uGao.uGaoUtil import IFEvtProp, PlotException, MASKVALUE
from uGao.u2dplot import D2Frame, PYSIDEVER
from uGao.u2dplotBase import DataConverter
import math
import Manyo.MLF as mm


import numpy as np

#######################################
#  定数定義
#######################################
MOUSE_UP = 1
REGION_CHANGE = 2
PLOTTER_CLOSED = 3

REGION_RECTANGLE = 0
REGION_LINE = 1
REGION_POINT = 2
REGION_CIRCLE = 3
REGION_RING = 4
REGION_SECTOR = 5
REGION_RING_SECTOR = 6

#######################################
def format_int_range(range0, range1):
    """強度積算範囲設定処理

    引数のどちらかがNoneの時は全範囲になるようにNoneにする。

    Parameters:
        range0 (float or None): 積算範囲始値
        range1 (float or None): 積算範囲終値
    """
    if (range0 is None) or (range1 is None):
        return None
    # 浮動小数点に変換
    try:
        rg0 = float(range0)
        rg1 = float(range1)
    except:
        raise PlotException('Common', 'C027', ('range',))

    if rg1 >= rg0:
        return [rg0, rg1]
    else:
        return [rg1, rg0]

#######################################
#  MousePrms
#######################################


class MousePrms(object):
    """
     マウスパラメータクラス
    """
    #########################################

    def __init__(self, x0, y0, x1=None, y1=None):
        """
        コンストラクタ
        @param  無し
        @retval 無し
        """
        self.X0 = x0
        self.Y0 = y0
        self.X1 = x1
        self.Y1 = y1

#######################################
#  U2IF
#######################################


class U2IF(object):
    """
    uGao 汎用2次元プロッタ I/F クラス
    """

    #########################################
    def __init__(self, parent=None, data=None, order=1, title=None):
        """コンストラクタ

        Parameters:
            parent (QWidget or None):親ウィンドウ。トップレベルウィンドウの場合はNone。
            data (ECM, ECA,or list(np.array, np.array,np.array) ): 表示対象のデータ
            order (int): プロッタ番号(タイトルバーに順番を表示)
            fTitle(str): フレームタイトル
        """
        self.order = order
        # プロパティ管理クラスのインスタンスを取得
        self.ifi = IFEvtProp(order)
        self.inhibit = False
        self.regionEnable = True

        # 初期化
        self.keys = (None, None, None)
        self.intRange = None
        self.parent = parent
        self.order = order
        self.title = title
        self.indices_sort = None
        self.dc = None  # DataConverterインスタンス

        # イベントハンドラ関数
        self.MouseMove = None
        self.ChangeRegionFunc = None
        self.PlotClose = None

        # イベントのリスナ登録
        self.ifi.AddListner(
            'mouse_up', self._OnNotifyMouse)              # マウス情報
        self.ifi.AddListner(
            'u2dclosed', self._OnNotifyPlotClose)         # プロッタクローズ
        self.ifi.AddListner(
            'add_region', self._OnNotifyChangeRegion)     # 領域追加
        self.ifi.AddListner(
            'change_region', self._OnNotifyChangeRegion)  # 領域変更
        self.ifi.AddListner(
            'del_region', self._OnNotifyChangeRegion)     # 領域削除
        self.ifi.AddListner('close_u2dplot', self._OnNotifyClose2dplot)

        self.plot = None

        if data is not None:
            # デフォルト条件でデータを表示
            self.SetData(data)

    #########################################
    def ShowPlot(self, data):
        """プロッタ表示(CUI 専用)

        Parameters:
            data (ECM, ECA,or list(np.array, np.array,np.array) ): 表示対象のデータ
        """
        ndata = DataConverter().ConvertData(data, self.keys, self.intRange)

        if PYSIDEVER == 2:
            # Hi-resolution Display for windows
            if hasattr(QtCore.Qt, 'AA_EnableHighDpiScaling'):
                QtWidgets.QApplication.setAttribute(
                    QtCore.Qt.AA_EnableHighDpiScaling, True)
        app = QtWidgets.QApplication([])
        # Set Default Font Size to (default 14)
        deffont = app.font()
        if "UTSUSEMI_DEFAULT_FONTSIZE" in os.environ:
            deffontsize = int(os.environ["UTSUSEMI_DEFAULT_FONTSIZE"])
            deffont.setPointSize(deffontsize)
        else:
            deffont.setPointSize(10)
        app.setFont(deffont)
        main_window = D2Frame(None, ndata)
        main_window.setWindowTitle("Plot window")
        main_window.show()
        if PYSIDEVER == 6:
            app.exec()
        else:
            app.exec_()

    #########################################
    def Bind(self, btype, func):
        """
        イベントハンドラの設定
        @param  btype(int) イベントタイプ
        @param  func  イベント発生時に実行する関数
        @retval 無し
        """
        if btype == MOUSE_UP:
            self.MouseMove = func
        elif btype == REGION_CHANGE:
            self.ChangeRegionFunc = func
        elif btype == PLOTTER_CLOSED:
            self.PlotClose = func

    #########################################
    def SetKeys(self, xkey, ykey, intkey=None, rkey=None):
        """キー文字列設定処理

        Parameters:
            xkey (str or None): X Key
            ykey (str or None): Y Key
            intkey (str or None): Int Key
            rkey (str or None): Range Key
        """
        if xkey is not None and not isinstance(xkey, str):
            raise PlotException('Common', 'C025', ('xkey',))
        if ykey is not None and not isinstance(ykey, str):
            raise PlotException('Common', 'C025', ('ykey',))
        if intkey is not None and not isinstance(intkey, str):
            raise PlotException('Common', 'C025', ('intkey',))
        if rkey is not None and not isinstance(rkey, str):
            raise PlotException('Common', 'C025', ('rkey',))

        self.keys = (xkey, ykey, intkey, rkey)

    #########################################
    def SetIntRange(self, range0, range1):
        """強度積算範囲設定処理

        self.intRangeに積算範囲を設定する。
        引数のどちらかがNoneの時は全範囲になるようにself.intRangeをNoneにする。

        Parameters:
            range0 (float or None): 積算範囲始値
            range1 (float or None): 積算範囲終値
        """
        self.intRange = format_int_range(range0, range1)

    #########################################
    def SetData(self, data):
        """
        データ設定処理
        @param  data (ECM, ECA,or list(np.array, np.array,np.array) ) 表示対象のデータ
        @retval 無し
        """
        if isinstance(data, Manyo.ElementContainerMatrix) or isinstance(data, Manyo.ElementContainerArray):
            self.dc = DataConverter()
            ndata = self.dc.ConvertData(data, self.keys, self.intRange)
            self.indices_sort = self.dc.PutLastSortIndices()
            # del dc [20170424, TI] TODO: 問題なければ削除
        else:
            ndata = data

        if self.plot is not None:
            # データ変更メッセージ送信
            self.ifi.NotifyEvent(self, 'change_data', ndata)
        else:
            # プロッタクローズメッセージのリスナー登録
            self.ifi.AddListner('close_plot', self._OnNotifyPlotClose)
            # データを表示
            self.plot = D2Frame(self.parent, ndata, self.order, self.title)
            self.plot.setWindowTitle("Plot window")
            self.plot.ifi.DelListner(self.plot.listner_index_slice)
            self.plot.ifi.AddListner(
                'left_mouse_click_cb', self.left_mouse_click_cb)
            self.plot.SetInhibitClose(self.inhibit)
            self.plot.RegionEnable(self.regionEnable)
            self.plot.show()

    #########################################
    def InhibitPlotClose(self, flag):
        """
        プロッタクローズ禁止の設定
        @param  flag (bool) True:禁止 or False: 解除
        @retval 無し
        """
        if self.plot is not None:
            self.plot.SetInhibitClose(flag)
        else:
            self.inhibit = flag

    #########################################
    def InhibitRegion(self, flag):
        """
        領域ダイアログ禁止の設定
        @param  flag (bool) True:禁止 or False: 解除
        @retval 無し
        """
        if self.plot is not None:
            if flag:
                self.plot.RegionEnable(False)
            else:
                self.plot.RegionEnable(True)
        else:
            self.regionEnable = not flag

    #########################################
    def ReadData(self, filename):
        """
        データをファイルより読み込む
        @param  filename (string) ファイルのパス
        @retval True or False
        """
        if self.plot is None:
            return False
        try:
            dat = self.plot.ReadDatFile(filename)
        except:
            return False
        # データ変更メッセージ送信
        self.ifi.NotifyEvent(self, 'change_data', dat)
        return True

    #########################################
    def SetGroups(self, groups, colors):
        """
        グループとカラーを設定
        @param  groups (string list) グループ名
        @param  colors (string list) グループカラー
        @retval 無し
        """
        if self.plot is None:
            return
        cNames = ["White", "Yellow", "Black",
                  "Blue", "Green", "Red", "Cyan", "Purple"]

        crnames = []
        for i in range(len(groups)):
            # グループ数よりすくなければ
            if i >= len(colors):
                crnames.append("White")
            else:
                # 大文字に変換
                crnames.append(colors[i])

        codes = []
        for color in crnames:
            if color in cNames:
                cindex = cNames.index(color)
            else:
                cindex = 0
            codes.append(cindex)

        self.plot.SetGroupColors(groups, crnames, codes)

    #########################################
    def AddRegion(self, regName, values, groupIndex=0):
        """
        領域追加
        @param  regName (string) 領域名
        @param  values (string list) 領域の値
        @param  groupIndex (int) グループ指定
        @retval 無し
        """
        # 領域追加メッセージ送信
        self.ifi.NotifyEvent(self, 'add_region_from_other',
                             (regName, values, groupIndex))

    #########################################
    def GetRegion(self, index=None):
        """
        領域取得
        @param  index (int) 行インデックス、None のとき全データ
        @retval (regName, values, groupIndex)
        """
        # 領域データ取得
        regionData = self.ifi.GetProperty('region_data')
        # インデックスの指定が無いときは、全データ
        if index is None:
            return regionData

        # 指定されたインデックスが領域数を越えていれば
        if index >= len(regionData):
            return None
        return regionData[index]

    #########################################
    def ChangeRegion(self, index, regName, values, groupIndex=0):
        """
        領域のパラメータ変更
        @param  index (int) 行インデックス
        @param  regName (string) 領域名
        @param  values (string list) 領域の値
        @param  groupIndex (int) グループ指定
        @retval 無し
        """
        # 領域変更メッセージ送信
        self.ifi.NotifyEvent(self, 'change_region_prms',
                             (index, regName, values, groupIndex))

    #########################################
    def DeleteRegion(self, index):
        """
        領域削除
        @param  index (int) 行インデックス
        @retval 無し
        """
        # 領域削除メッセージ送信
        self.ifi.NotifyEvent(self, 'del_region_from_other', index)

    #########################################
    def SelectRegion(self, index):
        """
        領域選択
        @param  index (int) 行インデックス
        @retval 無し
        """
        # 領域選択メッセージ送信
        self.ifi.NotifyEvent(self, 'change_selected_row', index)

    #########################################
    def SetRegionType(self, regName):
        """
        領域タイプを設定
        @param  regName (string) 領域名
        @retval 無し
        """
        # 領域タイプ変更メッセージ送信
        self.ifi.NotifyEvent(self, 'select_region', regName)

    #########################################
    def SaveAsBin(self, filename):
        """
        データをバイナリファイルに書き込む
        @param  filename (string) ファイルのパス
        @retval True or False
        """
        if self.plot is None:
            return False
        try:
            self.plot.SaveAsBin(filename)
        except:
            return False
        return True

    #########################################
    def SaveAsTxt(self, filename):
        """
        データをテキストファイルに書き込む
        @param  filename (string) ファイルのパス
        @retval True or False
        """
        if self.plot is None:
            return False
        try:
            self.plot.SaveAsTxt(filename)
        except:
            return False
        return True

    #########################################
    def SetTitles(self, title, comment=None):
        """
        タイトルとコメントの設定
        @param  title (string) グラフのタイトル
        @param  comment (string) コメント
        @retval 無し
        """
        if self.plot is None:
            return
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        # 書き換え
        params.title = title
        if comment is not None:
            params.comment = comment
        # パラメータ変更通知
        self.ifi.NotifyEvent(self, 'change_params')

    #########################################
    def GetTitles(self):
        """
        タイトルとコメントの取得
        @param  無し
        @retval タイトルとコメント
        """
        if self.plot is None:
            return ("", "")
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        return (params.title, params.comment)

    #########################################
    def SetTransPosition(self, trans):
        """
        軸の転置指定
        @param  title (string) グラフのタイトル
        @param  comment (string) コメント
        @retval 無し
        """
        if self.plot is None:
            return
        # 引数の型チェック
        if isinstance(trans, bool):
            # パラメータをプロッタ画面より取得
            params = self.ifi.GetProperty('params')
            # 現在の値と異なっていたなら
            if params.transPosition != trans:
                params.transPosition = trans
                # パラメータ変更通知
                self.ifi.NotifyEvent(self, 'change_params')
        else:
            raise PlotException('Common', 'C028', ('Argument',))

    #########################################
    def GetTransPosition(self):
        """
        軸の転置取得
        @param  無し
        @retval タイトルとコメント
        """
        if self.plot is None:
            return False
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        return params.transPosition

    #########################################
    def SetXScale(self, auto, range0, range1):
        """
        Xスケールパラメータ設定
        @param  auto (bool) 範囲自動か
        @param  range0 (float) 範囲の始値
        @param  range1 (float) 範囲の終値
        @retval 無し
        """
        self._SetScale(True, auto, range0, range1)

    #########################################
    def SetYScale(self, auto, range0, range1):
        """
        Yスケールパラメータ設定
        @param  auto (bool) 範囲自動か
        @param  range0 (float) 範囲の始値
        @param  range1 (float) 範囲の終値
        @retval 無し
        """
        self._SetScale(False, auto, range0, range1)

    #########################################
    def _SetScale(self, xx, auto, range0, range1):
        """
        スケールパラメータ設定
        @param  xx (bool) X軸か
        @param  auto (bool) 範囲自動か
        @param  range0 (float) 範囲の始値
        @param  range1 (float) 範囲の終値
        @retval 無し
        """
        if self.plot is None:
            return
        # 引数の型チェック
        if not isinstance(auto, bool):
            raise PlotException('Common', 'C028', ('auto',))
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        # X軸か
        if xx:
            scale = params.xscale
        else:
            scale = params.yscale
        # 自動か
        if auto:
            if scale.autoRange:
                return
            scale.autoRange = True
        else:
            # 数値か
            try:
                rg0 = float(range0)
                rg1 = float(range1)
            except:
                raise PlotException('Common', 'C027', ('Range',))
            if rg0 >= rg1:
                raise PlotException('Common', 'C009', ('range1', 'range0'))
            scale.range = [rg0, rg1]
        # パラメータ変更通知
        self.ifi.NotifyEvent(self, 'change_params')

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

    def GetXScale(self):
        """
        X軸範囲取得
        @param  無し
        @retval (auto, range0, range1)
        """
        if self.plot is None:
            return
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        scale = params.xscale
        if scale.range is None:
            return (scale.autoRange, 0.0, 1.0)
        return (scale.autoRange, scale.range[0], scale.range[1])

    #########################################
    def GetYScale(self):
        """
        Y軸範囲取得
        @param  無し
        @retval (auto, range0, range1)
        """
        if self.plot is None:
            return
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        scale = params.yscale
        if scale.range is None:
            return (scale.autoRange, 0.0, 1.0)
        return (scale.autoRange, scale.range[0], scale.range[1])

    #########################################
    def SetXTicksFormat(self, auto, ftype=None, precision=None, fontsize=None):
        """
        X軸のチックラベル設定
        @param  auto (bool) 自動か
        @param  ftype (int) 形式 0: Floating Point, 1: Exponential
        @param  precision (int) 精度
        @param  fontsize(int) フォントサイズ
        @retval 無し
        """
        self._SetTicksFormat(True, auto, ftype, precision, fontsize)

    #########################################
    def SetYTicksFormat(self, auto, ftype=None, precision=None, fontsize=None):
        """
        Y軸のチックラベル設定
        @param  auto (bool) 自動か
        @param  ftype (int) 形式 0: Floating Point, 1: Exponential
        @param  precision (int) 精度
        @param  fontsize(int) フォントサイズ
        @retval 無し
        """
        self._SetTicksFormat(False, auto, ftype, precision, fontsize)

    #########################################
    def _SetTicksFormat(self, xx, auto, ftype=None, precision=None, fontsize=None):
        """
        チックラベル設定
        @param  xx (bool) X軸か
        @param  auto (bool) 自動か
        @param  ftype (int) 形式 0: Floating Point, 1: Exponential
        @param  precision (int) 精度
        @param  fontsize(int) フォントサイズ
        @retval 無し
        """
        if self.plot is None:
            return
        # 引数の型チェック
        if not isinstance(auto, bool):
            raise PlotException('Common', 'C028', ('Auto',))
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        # X軸か
        if xx:
            scale = params.xscale
        else:
            scale = params.yscale
        # 自動か
        if auto:
            if scale.autoTick:
                return
            scale.autoTick = True
        else:
            # 表示形式が指定されているか
            if ftype is not None:
                if not isinstance(ftype, int):
                    raise PlotException('Common', 'C026', ('ftype',))
                if ftype < 0 or ftype > 1:
                    raise PlotException('Common', 'C008', ('ftype', '0', '1'))
                scale.format = ftype
            # 精度が指定されているか
            if precision is not None:
                if not isinstance(precision, int):
                    raise PlotException('Common', 'C026', ('precision',))
                if precision < 0 or precision > 5:
                    raise PlotException(
                        'Common', 'C008', ('precision', '0', '5'))
                scale.precision = precision
            # フォントサイズが指定されているか
            if fontsize is not None:
                if not isinstance(fontsize, int):
                    raise PlotException('Common', 'C026', ('fontsize',))
                if fontsize < 6 or fontsize > 12:
                    raise PlotException(
                        'Common', 'C008', ('fontsize', '6', '12'))
                scale.fontSize = fontsize
        # パラメータ変更通知
        self.ifi.NotifyEvent(self, 'change_params')

    #########################################
    def GetXTicksFormat(self):
        """
        X軸のチックラベル取得
        @param  無し
        @retval 無し
        """
        if self.plot is None:
            return
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        scale = params.xscale
        return (scale.autoTick, scale.format, scale.precision, scale.fontSize)

    #########################################
    def GetYTicksFormat(self):
        """
        Y軸のチックラベル取得
        @param  無し
        @retval 無し
        """
        if self.plot is None:
            return
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        scale = params.yscale
        return (scale.autoTick, scale.format, scale.precision, scale.fontSize)

    #########################################
    def SetLabels(self, xlabel, ylabel):
        """
        軸のラベルを指定
        @param  xlabel (string or None) X軸のラベル
        @param  ylabel (string or None) Y軸のラベル
        @retval 無し
        """
        if self.plot is None:
            return
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        if xlabel is not None:
            params.xscale.label = xlabel
        if ylabel is not None:
            params.yscale.label = ylabel
        # パラメータ変更通知
        self.ifi.NotifyEvent(self, 'change_params')

    #########################################
    def GetLabels(self, ):
        """
        軸のラベルを取得
        @param  無し
        @retval (xlabel, ylabel)
        """
        if self.plot is None:
            return ("", "")
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        return (params.xscale.label, params.yscale.label)

    #########################################
    def SetUnits(self, xunit, yunit):
        """
        軸のUnitを指定
        @param  xunit (string or None) X軸のunit
        @param  yunit (string or None) Y軸のunit
        @retval 無し
        """
        if self.plot is None:
            return
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        if params.xscale.label is not None:
            params.xscale.unit = xunit
        if params.yscale.label is not None:
            params.yscale.unit = yunit
        # パラメータ変更通知
        self.ifi.NotifyEvent(self, 'change_params')

    #########################################
    def GetUnits(self, ):
        """
        軸のUnitを取得
        @param  無し
        @retval (xunit, yunit)
        """
        if self.plot is None:
            return ("", "")
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        return (params.xscale.unit, params.yscale.unit)

    #########################################
    def SetHGrid(self, grid, color=None, interval=None):
        """
        水平グリッドの指定
        @param  grid (string) グラフのタイトル
        @param  color (int) 0:White, 1:Yellow 2:Red, 3:Black, 4:Blue, 5:Green, 6:Cyan, 7:Purple
        @param  interval (float) 間隔
        @retval 無し
        """
        if self.plot is None:
            return
        # 引数の型チェック
        if isinstance(grid, bool):
            # パラメータをプロッタ画面より取得
            params = self.ifi.GetProperty('params')
            params.hgrid = grid
            # カラーが指定されていれば
            if color is not None:
                params.gridColor = color
            # 間隔が指定されていれば
            if color is not None:
                params.hgridInterval = interval
            # パラメータ変更通知
            self.ifi.NotifyEvent(self, 'change_params')
        else:
            raise PlotException('Common', 'C028', ('Argument',))

    #########################################
    def GetHGrid(self):
        """
        水平グリッドの取得
        @param  grid (string) グラフのタイトル
        @param  color (int) 0:White, 1:Yellow 2:Red, 3:Black, 4:Blue, 5:Green, 6:Cyan, 7:Purple
        @param  interval (float) 間隔
        @retval 無し
        """
        if self.plot is None:
            return None
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        return (params.hgrid, params.gridColor, params.hgridInterval)

    #########################################
    def SetVGrid(self, grid, color=None, interval=None):
        """
        垂直グリッドの指定
        @param  grid (string) グラフのタイトル
        @param  color (int) 0:White, 1:Yellow 2:Red, 3:Black, 4:Blue, 5:Green, 6:Cyan, 7:Purple
        @param  interval (float) 間隔
        @retval 無し
        """
        if self.plot is None:
            return
        # 引数の型チェック
        if isinstance(grid, bool):
            # パラメータをプロッタ画面より取得
            params = self.ifi.GetProperty('params')
            params.vgrid = grid
            # カラーが指定されていれば
            if color is not None:
                params.gridColor = color
            # 間隔が指定されていれば
            if color is not None:
                params.vgridInterval = interval
            # パラメータ変更通知
            self.ifi.NotifyEvent(self, 'change_params')
        else:
            raise PlotException('Common', 'C028', ('Argument',))

    #########################################
    def GetVGrid(self):
        """
        垂直グリッドの取得
        @param  grid (string) グラフのタイトル
        @param  color (int) 0:White, 1:Yellow 2:Red, 3:Black, 4:Blue, 5:Green, 6:Cyan, 7:Purple
        @param  interval (float) 間隔
        @retval 無し
        """
        if self.plot is None:
            return None
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        return (params.vgrid, params.gridColor, params.vgridInterval)

    #########################################
    def SetColorMap(self, mapNo, auto, log=False, range0=None, range1=None):
        """
        カラーマップの指定
        @param  mapNo (int) カラーマップ指定　0: Default,  1: Red Scale,  2: Blue Scale,  3: Gray Scale
        @param  auto (bool) 自動範囲指定
        @param  log  (bool) ログスケール指定
        @param  range0 (float) 範囲の始値
        @param  range1 (float) 範囲の終値
        @retval 無し
        """
        if self.plot is None:
            return
        # 引数の型チェック
        if not isinstance(mapNo, int):
            raise PlotException('Common', 'C026', ('mapNo',))
        if not isinstance(auto, bool):
            raise PlotException('Common', 'C028', ('auto',))
        if not isinstance(log, bool):
            raise PlotException('Common', 'C028', ('log',))

        # マップの番号範囲
        if mapNo < 0 or mapNo > (len(COLOR_MAPS) - 1):
            raise PlotException('Common', 'C008', ('mapNo', '0', '3'))
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        params.colorMap = mapNo
        params.logScale = log
        # 自動か
        if auto:
            params.autoRange = auto
        else:
            # 数値か
            try:
                rg0 = float(range0)
                rg1 = float(range1)
            except:
                raise PlotException('Common', 'C027', ('Range',))
            if rg0 >= rg1:
                raise PlotException('Common', 'C009', ('range1', 'range0'))
            params.range = [rg0, rg1]
        # パラメータ変更通知
        self.ifi.NotifyEvent(self, 'change_params')

    #########################################
    def GetColorMap(self):
        """
        カラーマップの取得
        @param  無し
        @retval  (mapNo, auto, log, range0, range1)
        """
        if self.plot is None:
            return None
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        return (params.colorMap, params.autoRange, params.logScale, params.range[0], params.range[1])

    #########################################
    def SetSmooth(self, isSmooth=False, windowVal=1, timesVal=1):
        """
        スムージングの指定
        @param isSmooth   スムージングを行うかどうか
        @param windowVal  スムージングのウィンドウ値
        @param timesVal   the number of times
        @retval None
        """
        if self.plot is None:
            return
        # 引数の型チェック
        if not isinstance(isSmooth, bool):
            raise PlotException('Common', 'C028', ('isSmooth',))
        if not isinstance(windowVal, int):
            raise PlotException('Common', 'C027', ('windowVal',))
        if not isinstance(timesVal, int):
            raise PlotException('Common', 'C027', ('timesVal',))
        if windowVal <= 0.0:
            raise PlotException('Common', 'C010', ('windowVal', '1'))
        if timesVal <= 0.0:
            raise PlotException('Common', 'C010', ('timesVal', '1'))
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        params.smoothing = [isSmooth, windowVal, times]
        # パラメータ変更通知
        self.ifi.NotifyEvent(self, 'change_params')

    #########################################
    def GetSmooth(self):
        """
        スムージング設定の取得
        @param None
        @retval (isSmooth,windowVal) : SetSmoothの引数と同じ
        """
        if self.plot is None:
            return None
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        return (params.smoothing[0], params.smoothing[1], params.smoothing[2])

    #########################################
    def SetBankSeparator(self, flag=False):
        """
        Bank Separatorの指定
        @param flag   Showing bank separators or not
        @retval None
        """
        if self.plot is None:
            return
        # 引数の型チェック
        if not isinstance(flag, bool):
            raise PlotException('Common', 'C028', ('isSmooth',))
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        params.bankseparator = flag
        # パラメータ変更通知
        self.ifi.NotifyEvent(self, 'change_params')

    #########################################
    def SetWindowSize(self, width, height):
        """
        #[inamura 181113]
        """
        if self.plot is None:
            return
        # 引数のチェック
        if isinstance(width, int) or isinstance(width, float):
            pass
        else:
            return
        if isinstance(height, int) or isinstance(height, float):
            pass
        else:
            return
        if width <= 0 or height <= 0:
            return
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        params.window_size[0] = int(width)
        params.window_size[1] = int(height)
        # パラメータ変更通知
        self.ifi.NotifyEvent(self, 'change_params')

    #########################################
    def SetSliceMethod(self, isAve=True):
        """
        #[inamura 190226]
        """
        if self.plot is None:
            return
        # 引数のチェック
        if isinstance(isAve, bool):
            pass
        else:
            return
        # パラメータをプロッタ画面より取得
        params = self.ifi.GetProperty('params')
        params.slice_ave_mode = isAve
        # パラメータ変更通知
        self.ifi.NotifyEvent(self, 'change_params')

    #########################################
    def SetDetectMapMode(self, isDetMapMode=True):
        """
        """
        if self.plot is None:
            return
        # 引数のチェック
        if isinstance(isDetMapMode, bool):
            pass
        else:
            return
        params = self.ifi.GetProperty('params')
        params.detectmapmode = isDetMapMode
        # 再描画通知
        self.ifi.NotifyEvent(self, 'change_params')

    #########################################
    def _OnNotifyClose2dplot(self, eventSrc, evtType, dat=None):
        """
        Close u2dplot::D2Frame #[inamura 181001]
        @param eventSrc   イベント発生元インスタンス
        @param  evtType (str) 発生したイベントのタイプ
        @retval 無し
        """
        try:
            self.plot.Close()
        except:
            raise UserWarning("Failed u2dplot::D2Frame::Close")

    #########################################
    def _OnNotifyPlotClose(self, eventSrc, evtType, dat=None):
        """
        プロッタクローズメッセージ受信
        @param eventSrc   イベント発生元インスタンス
        @param  evtType (str) 発生したイベントのタイプ
        @retval 無し
        """
        self.plot = None
        # イベントハンドラが設定されているか
        if self.PlotClose is not None:
            # apply(self.PlotClose, (self.order,))
            self.PlotClose(self.order)

    #########################################
    def _OnNotifyMouse(self, wid, evt, dat):
        """
        マウスアップイベント受信
        @param  wid イベント発生元
        @param  evt イベントデータ
        @param  dat (transPosition, x0,y0,x1,y1)
        @retval 無し
        """
        # イベントハンドラが設定されているか
        if self.MouseMove is None:
            return
        transPosition, x0, y0, x1, y1 = dat
        # 軸の転置が指定されていれば
        if transPosition:
            # データを入れ替え
            tmp = x0
            x0 = y0
            y0 = tmp
            tmp = x1
            x1 = y1
            y1 = tmp

        self.MouseMove(*(MousePrms(x0, y0, x1, y1),))

    #########################################
    def _OnNotifyChangeRegion(self, wid, evt, dat):
        """
        領域追加・変更イベント受信
        @param  wid イベント発生元
        @param  evt イベントデータ
        @param  dat (transPosition, x0,y0,x1,y1)
        @retval 無し
        """
        # イベントハンドラが設定されているか
        if self.ChangeRegionFunc is not None:
            apply(self.ChangeRegionFunc)

    #########################################
    def IsTransposed(self):
        """
        転置であるかを返す

        Returns:
            bool
        """
        params = self.ifi.GetProperty('params')
        return params.transPosition

    #########################################
    def GetBins(self):
        """
        表示中のデータのbinを返す

        Returns:
            Tuple(ndarray, ndarray) xbin, ybin
        """
        return self.plot.data[1][0], self.plot.data[2].T[0]

    #########################################
    def GetQuadMesh(self):
        """
        描画された2次元プロット情報を返す

        Returns:
            matplotlib.collections.QuadMesh
        """
        return self.plot.d2.GetQuadMesh()

    #########################################
    def GetSelectedRegPath(self):
        """
        選択されている領域のpathを返す

        Returns:
            matplotlib.path.Path 選択されている領域のpath
        """
        for diagram in self.plot.d2.regAxes.get_children():
            if diagram.get_gid() == "selected":
                return diagram.get_patch_transform().transform_path(diagram.get_path())
        return None

    #########################################
    def GetSelectedRegInfo(self):
        """
        選択されている領域情報を返す

        Retunrs:
            list 領域情報のリスト　[領域名、カラー、値のリスト、選択否選択のbool]
        """
        for region in self.plot.d2.regInfos:
            if region[3]:
                return region
        return region


#########################################
if __name__ == '__main__':

    '''
    import ana.Reduction.BaseCommands as bc

    eca = bc.LoadDataFromDump( "./files/", "eca.dmp" )
    bc.SaveDataToDump( mat(10), "./", "eca.dmp" )
    app = wx.PySimpleApp()
    u2 = U2IF(None, None)
    u2.SetKeys(u'DETID',None, u'Qx')
     u2.SetIntRange(-0.2,0.0)
    mat = bc.LoadDataFromDump( "./files/", "SAS104212_SM_lam_20140209.dmp" )
    hh = mat(237).PutHeaderPointer()
    hh.OverWrite("MASKED", 1)
    # u2.SetData(mat)
    # app.MainLoop()
    '''

    TestU2IF()
