class Params:
    def __init__(self, lang):
        self.lang = lang
        self.task = None
        self.fpath = None
        """
        First 5 lines of original data
        """
        self.data5 = None
        self.columns = None
        self.col_types_def = None
        self.col_types = None
        self.objective = None
        self.col_types_changed = True
        """
        Note that X was transformed
        (i.e. some features may be transformed to dummy variables)
        while columns(_def) and col_types(_def) represent original ones.
        """
        self.X = None
        self.y = None
        self.algorithms = None
        self.mdl = None
        self.results = None
        self.error = None
        # Parameters for feature selection
        self.X_fs = None
        self.algorithms_fs = None
        self.mdl_fs = None
        self.results_fs = None
        self.not_deleted = False

        self.out_dir = None
        self.path_pred = None
    
    def initialize(self, is_task=True):
        if is_task:
            self.task = None

        self.fpath = None
        self.data5 = None
        self.columns = None
        self.col_types_def = None
        self.col_types = None
        self.objective = None
        self.col_types_changed = True
        self.X = None
        self.y = None
        self.algorithms = None
        self.mdl = None
        self.results = None
        self.error = None
        self.X_fs = None
        self.algorithms_fs = None
        self.mdl_fs = None
        self.results_fs = None
        self.not_deleted = False
        self.out_dir = None
        self.path_pred = None
 class Introduction(Content):

    def __init__(self, parent=None, button_func=None, params=None):
        super().__init__(parent, 'Introduction', params)

        self.button_func = button_func

        path = os.path.abspath(os.path.dirname(__file__)) + '/static/'
        path += 'introduction'

        text = self.get_text(path)

        self.set_paragraph('MALSS interactive', text=text)

        btn = QPushButton('Next', self.inner)
        btn.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        if self.params.lang == 'en':
            btn.clicked.connect(lambda: self.button_func('Task'))
        else:
            btn.clicked.connect(lambda: self.button_func('分析タスク'))

        self.vbox.addStretch(1)

        self.vbox.addWidget(btn) class TypeOfTask(Content):

    def __init__(self, parent=None, button_func=None, params=None):
        super().__init__(parent, 'Task', params)

        self.button_func = button_func

        path = os.path.abspath(os.path.dirname(__file__)) + '/static/'

        # Text for machine learning tasks
        path1 = path + 'task'
        text = self.get_text(path1)
        if self.params.lang == 'en':
            self.set_paragraph('Type of task', text=text, img=path1)
        else:
            self.set_paragraph('分析タスク', text=text, img=path1)

        # Text for supervised learning
        path2 = path + 'supervised_learning'
        text = self.get_text(path2)
        if self.params.lang == 'en':
            self.set_paragraph('Supervised learning', text=text, img=path2)
        else:
            self.set_paragraph('教師あり学習', text=text, img=path2)

        if params.lang == 'jp':
            self.set_paragraph(
                'タスクの選択',
                text='あなたの機械学習のタスクを選択してください。')
        else:
            self.set_paragraph(
                'Task selection',
                text='Choose your machine learning task.')

        vbox1 = QVBoxLayout()
        vbox1.setContentsMargins(10, 10, 10, 10)
        vbox1.setSpacing(10)

        rbtn_cls = QRadioButton('Classification', self.inner)
        rbtn_cls.setStyleSheet('QRadioButton{font: 15pt;};')
        rbtn_cls.clicked.connect(self.rbtn_clicked)
        rbtn_reg = QRadioButton('Regression', self.inner)
        rbtn_reg.setStyleSheet('QRadioButton{font: 15pt;};')
        rbtn_reg.clicked.connect(self.rbtn_clicked)
        if params.task == 'Classification':
            rbtn_cls.setChecked(True)
        elif params.task == 'Regression':
            rbtn_reg.setChecked(True)

        self.btn_group = QButtonGroup()
        self.btn_group.addButton(rbtn_cls, 1)
        self.btn_group.addButton(rbtn_reg, 1)

        vbox1.addWidget(rbtn_cls)
        vbox1.addWidget(rbtn_reg)
        vbox1.addStretch(1)

        self.vbox.addLayout(vbox1)

        self.vbox.addStretch(1)

        self.btn = QPushButton('Next', self.inner)
        self.btn.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        if self.params.lang == 'en':
            self.btn.clicked.connect(lambda: self.button_func('Input data'))
        else:
            self.btn.clicked.connect(lambda: self.button_func('入力データ'))
        if params.task is None:
            self.btn.setEnabled(False)

        self.vbox.addWidget(self.btn)

    def rbtn_clicked(self):
        self.params.task = self.btn_group.checkedButton().text()
        self.btn.setEnabled(True)
 class SetFile(Content):

    def __init__(self, parent=None, button_func=None, params=None):
        super().__init__(parent, 'Input data', params)

        self.fpath = None

        self.button_func = button_func

        path = os.path.abspath(os.path.dirname(__file__)) + '/static/'

        # Text for data format
        path1 = path + 'format'
        text = self.get_text(path1)
        if self.params.lang == 'en':
            self.set_paragraph('Data format', text=text, img=path1)
        else:
            self.set_paragraph('入力データフォーマット', text=text, img=path1)

        # Text for data format
        path2 = path + 'dummy'
        text = self.get_text(path2)
        if self.params.lang == 'en':
            self.set_paragraph('Dummy variables', text=text, img=path2)
        else:
            self.set_paragraph('ダミー変数', text=text, img=path2)

        if params.lang == 'jp':
            self.set_paragraph(
                'ファイル選択',
                text='データ分析を行うファイルを選択してください。')
        else:
            self.set_paragraph(
                'File selection',
                text='Choose your input file.')

        hbox1 = QHBoxLayout()
        hbox1.setContentsMargins(10, 10, 10, 10)

        lbl = QLabel('Location:', self.inner)
        self.le = QLineEdit(self.inner)
        fo_btn = QPushButton('Browse...', self.inner)
        fo_btn.clicked.connect(self.show_dialog)

        hbox1.addWidget(lbl)
        hbox1.addWidget(self.le)
        hbox1.addWidget(fo_btn)

        self.vbox.addLayout(hbox1)

        self.vbox.addStretch(1)

        self.btn = QPushButton('Next', self.inner)
        self.btn.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        self.btn.clicked.connect(self.button_clicked)

        if self.params.fpath is not None:
            self.le.setText(self.params.fpath)
            self.fpath = self.params.fpath
        else:
            self.btn.setEnabled(False)

        self.vbox.addWidget(self.btn)

    def show_dialog(self):
        fname = QFileDialog.getOpenFileName(self, 'Open', '')
        self.le.setText(fname[0])
        self.btn.setEnabled(True)
        self.fpath = fname[0]

    def button_clicked(self):
        if self.params.fpath != self.fpath:
            self.params.initialize(is_task=False)
            self.button_func(self.title, delete_after=True)
            self.params.fpath = self.fpath

            try:
                # engine='python' is to avoid pandas's bug.
                data = pd.read_csv(
                    self.params.fpath, header=0, engine='python',
                    dtype=self.make_dtype(self.params.columns,
                                        self.params.col_types))
            except Exception:
                import traceback
                self.params.error = traceback.format_exc()
                self.button_func('Error')
                return
            self.params.data5 = data.head(min(5, data.shape[0]))

            self.params.columns = data.columns
            self.params.col_types_def =\
                list(map(str, data.dtypes.get_values()))
            self.params.col_types =\
                list(map(str, data.dtypes.get_values()))

        if self.params.lang == 'jp':
            self.button_func('データの確認')
        else:
            self.button_func('Data check')
 class DataCheck(Content):

    def __init__(self, parent=None, button_func=None, params=None):
        super().__init__(parent, 'Data check', params)

        self.button_func = button_func

        path = os.path.abspath(os.path.dirname(__file__)) + '/static/'

        # nr = min(5, data.shape[0])
        nr = len(self.params.data5)

        if params.lang == 'jp':
            text = ('データの読み込み結果（先頭{n}行）を以下に示します．\n'
                    'データを正しく読み込めていることを確認してください．'.format(n=nr))
            self.set_paragraph(
                'データ読み込み結果の確認', text=text)
        else:
            text = ('First {n} rows of your data are shown below.\n'
                    'Confirm that the data was read correctly.'.format(n=nr))
            self.set_paragraph(
                'Check data', text=text)

        table = NonScrollTable(self.inner)

        table.setRowCount(nr)
        table.setColumnCount(len(self.params.columns))
        table.setHorizontalHeaderLabels(self.params.columns)

        for r in range(nr):
            for c in range(len(self.params.columns)):
                item = QTableWidgetItem(str(self.params.data5.iat[r, c]))
                item.setFlags(Qt.ItemIsEnabled)
                table.setItem(r, c, item)

        table.setNonScroll()

        self.vbox.addWidget(table)

        # Text for type checking and objective variable setting
        path1 = path + 'categorical'
        text = self.get_text(path1)
        if self.params.lang == 'en':
            self.set_paragraph(
                'Check type of variables and set objective variable',
                text=text)
        else:
            self.set_paragraph('変数タイプの確認と目的変数の設定', text=text)

        # htable = QTableWidget(self.inner)
        htable = NonScrollTable(self.inner)

        htable.setRowCount(len(self.params.columns))
        htable.setColumnCount(4)
        htable.setHorizontalHeaderLabels(
            ['columns', 'categorical', 'numerical', 'target'])

        self.lst_cat = []
        self.lst_num = []
        self.lst_obj = []
        self.obj_group = QButtonGroup(self.inner)
        for c in range(len(self.params.columns)):
            # col 1
            item = QTableWidgetItem(self.params.columns[c])
            item.setFlags(Qt.ItemIsEnabled)
            htable.setItem(c, 0, item)

            group = QButtonGroup(self.inner)

            # col 2
            htable.setCellWidget(
                c, 1,
                self.__make_cell(c, 'cat', self.params.col_types[c],
                                 self.params.col_types_def[c]))
            group.addButton(self.lst_cat[-1])

            # col 3
            htable.setCellWidget(
                c, 2,
                self.__make_cell(c, 'num', self.params.col_types[c],
                                 self.params.col_types_def[c]))
            group.addButton(self.lst_num[-1])

            # col 4
            htable.setCellWidget(
                c, 3,
                self.__make_cell(c, 'obj', self.params.col_types[c],
                                 self.params.col_types_def[c]))
            self.obj_group.addButton(self.lst_obj[-1])
            self.obj_group.setId(self.lst_obj[-1], c)

        htable.setNonScroll()

        self.vbox.addWidget(htable)

        if self.params.lang == 'jp':
            self.txt_cnf = ('<font color="red">目的変数を１つ選択し，'
                    'targetの列にチェックをいれてください。')
            if self.params.task.lower() == 'classification':
                self.txt_cnf += '<br>目的変数はカテゴリ変数である必要があります。</font>'
            else:
                self.txt_cnf += '<br>目的変数は量的変数である必要があります。</font>'
        else:
            self.txt_cnf = ('<font color="red">Select one variable as target variable,'
                            'then set the column of "target" of the variable checked.')
            if self.params.task.lower() == 'classification':
                self.txt_cnf += '<br>Target variable must be a categorical variable.</font>'
            else:
                self.txt_cnf += '<br>Target variable must be a numerical variable.</font>'
        self.lbl_cnf = QLabel(self.txt_cnf, self.inner)

        self.vbox.addWidget(self.lbl_cnf)

        self.vbox.addStretch(1)

        self.btn = QPushButton('Next', self.inner)
        self.btn.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        if self.params.lang == 'en':
            self.btn.clicked.connect(lambda: self.button_func('Overfitting'))
        else:
            self.btn.clicked.connect(lambda: self.button_func('過学習'))
        if self.obj_group.checkedButton() is None:
            self.btn.setEnabled(False)
        else:
            self.lbl_cnf.setText('<br>')
            self.btn.setEnabled(True)

        self.vbox.addWidget(self.btn)

    def __make_cell(self, c, name, col_type, col_type_def):
        cell = QWidget(self.inner)
        rbtn = QRadioButton('', cell)
        rbtn.toggled.connect(lambda: self.rbtn_clicked(name + '_' + str(c)))
        hbl = QHBoxLayout(cell)
        hbl.addWidget(rbtn)
        hbl.setContentsMargins(0, 0, 0, 0)
        hbl.setAlignment(Qt.AlignCenter)
        cell.setLayout(hbl)
        if name == 'cat':
            if col_type == 'object':
                rbtn.setChecked(True)
            self.lst_cat.append(rbtn)
        elif name == 'num':
            if col_type != 'object':
                rbtn.setChecked(True)
            if col_type_def == 'object':
                rbtn.setEnabled(False)
            self.lst_num.append(rbtn)
        elif name == 'obj':
            if col_type == 'object' and self.params.task == 'Regression':
                rbtn.setEnabled(False)
            elif col_type != 'object' and self.params.task == 'Classification':
                rbtn.setEnabled(False)
            if self.params.columns[c] == self.params.objective:
                rbtn.setChecked(True)
            self.lst_obj.append(rbtn)

        return cell

    def rbtn_clicked(self, text):
        name, idx = text.split('_')
        idx = int(idx)
        if len(self.lst_obj) <= idx:
            return

        if self.lst_num[idx].isChecked():
            if self.params.task == 'Classification':
                self.obj_group.setExclusive(False)
                self.lst_obj[idx].setChecked(False)
                self.obj_group.setExclusive(True)
                self.lst_obj[idx].setEnabled(False)
            elif self.params.task == 'Regression':
                self.lst_obj[idx].setEnabled(True)

            self.params.col_types[idx] = self.params.col_types_def[idx]
        elif self.lst_cat[idx].isChecked():
            if self.params.task == 'Classification':
                self.lst_obj[idx].setEnabled(True)
            elif self.params.task == 'Regression':
                self.obj_group.setExclusive(False)
                self.lst_obj[idx].setChecked(False)
                self.obj_group.setExclusive(True)
                self.lst_obj[idx].setEnabled(False)

            self.params.col_types[idx] = 'object'

        if self.obj_group.checkedButton() is None:
            self.params.objective = None
            self.lbl_cnf.setText(self.txt_cnf)
            self.btn.setEnabled(False)
        else:
            self.params.objective =\
                self.params.columns[self.obj_group.checkedId()]
            self.lbl_cnf.setText('<br>')
            self.btn.setEnabled(True)

        self.params.col_types_changed = True
 class Overfitting(Content):

    def __init__(self, parent=None, button_func=None, params=None):
        super().__init__(parent, 'Overfitting', params)

        self.button_func = button_func

        path = os.path.abspath(os.path.dirname(__file__)) + '/static/'

        # Text for hyper-parameter tuning
        path1 = path + 'hyperparameter'
        text = self.get_text(path1)
        if self.params.lang == 'en':
            self.set_paragraph('Hyper-parameter tuning', text=text, img=path1)
        else:
            self.set_paragraph('ハイパーパラメータチューニング', text=text, img=path1)

        # Text for overfitting
        path2 = path + 'overfitting'
        text = self.get_text(path2)
        if self.params.lang == 'en':
            self.set_paragraph('Overfitting', text=text, img=path2)
        else:
            self.set_paragraph('過学習', text=text, img=path2)

        # Text for cross validation
        path3 = path + 'cross_validation'
        text = self.get_text(path3)
        if self.params.lang == 'en':
            self.set_paragraph('Cross validation', text=text, img=path3)
        else:
            self.set_paragraph('交差検証', text=text, img=path3)

        self.vbox.addStretch(1)

        self.btn = QPushButton('Next', self.inner)
        self.btn.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        if self.params.lang == 'en':
            self.btn.clicked.connect(lambda: self.button_func('Analysis'))
        else:
            self.btn.clicked.connect(lambda: self.button_func('分析の実行'))

        self.vbox.addWidget(self.btn)
 class Analysis(Analyzer):

    def __init__(self, parent=None, button_func=None, params=None):
        super().__init__(parent, 'Analysis', params)

        self.button_func = button_func

        self.preprocess()

        if self.params.lang == 'en':
            text = ('First 5 rows of your features are shown below.\n'
                    'Confirm that the data was normalized and\n'
                    'categorical variables (if any) are converted into dummy '
                    'variables.\n'
                    '(Categorical variable A that has values X, Y, and Z are '
                    'converted into dummy variables, A_X, A_Y, and A_Z.)')
            self.set_paragraph('Features', text=text)
        else:
            text = ('説明変数の先頭5行を以下に示します．\n'
                    'データの正規化（Normalization）が行われていること，\n'
                    'カテゴリ変数があればダミー変数を用いて量的変数に変換されていることを確認してください．\n'
                    '（X, Y, Zという値をとるカテゴリ変数AはA_X, A_Y, A_Zという変数に変換されます）')
            self.set_paragraph('説明変数', text=text)

        nr = 5

        table1 = NonScrollTable(self.inner)

        table1.setRowCount(nr)
        table1.setColumnCount(len(self.params.X.columns))
        table1.setHorizontalHeaderLabels(self.params.X.columns)

        for r in range(nr):
            for c in range(len(self.params.X.columns)):
                item = QTableWidgetItem(str(round(self.params.X.iat[r, c], 4)))
                item.setFlags(Qt.ItemIsEnabled)
                table1.setItem(r, c, item)

        table1.setNonScroll()

        self.vbox.addWidget(table1)

        if self.params.lang == 'en':
            text = ('MALSS selected appropriate algorithms '
                    'according to your task and data.\n'
                    'Selected algorithms are shown below.')
            self.set_paragraph('Algorithms', text=text)
        else:
            text = ('MALSSは分析タスクとデータに応じて適切なアルゴリズムを選択します．\n'
                    'アルゴリズム選択結果を以下の示します．')
            self.set_paragraph('アルゴリズム', text=text)

        nr = len(self.params.algorithms)

        table2 = NonScrollTable(self.inner)

        table2.setRowCount(nr)
        table2.setColumnCount(1)
        table2.setHorizontalHeaderLabels(['Algorithms'])

        for r in range(nr):
            item = QTableWidgetItem(self.params.algorithms[r][0])
            item.setFlags(Qt.ItemIsEnabled)
            table2.setItem(r, 0, item)

        table2.setNonScroll()

        self.vbox.addWidget(table2)

        if self.params.lang == 'en':
            text = ('MALSS automatically perform cross validation analysis '
                    'with grid search hyper-parameter tuning.\n'
                    'Clik "Analyze" to start.\n'
                    '(This will take tens of minutes.)')
            self.set_paragraph('', text=text)
        else:
            text = ('MALSSはグリッドサーチによるハイパーパラメータチューニング，'
                    '交差検証を自動で行います．\n'
                    'それでは分析を始めましょう．Anayzeボタンを押してください．\n'
                    '（分析には数分～数十分かかります）')
            self.set_paragraph('', text=text)

        self.vbox.addStretch(1)

        btn = QPushButton('Analyze', self.inner)
        btn.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        if self.params.lang == 'en':
            next_page = 'Results'
        else:
            next_page = '結果の確認'
        btn.clicked.connect(lambda: self.button_clicked(
            self.params.mdl, self.params.X, self.params.y, next_page))

        self.vbox.addWidget(btn)

        lists = ['task', 'supervised_learning', 'dummy', 'hyperparameter',
                 'overfitting', 'cross_validation', 'learning_curve',
                 'bias_variance']
        if self.params.lang == 'jp':
            lists = [l + '_jp' for l in lists]
        else:
            lists = [l + '_en' for l in lists]
        self.wait_ani.set_lists(lists)

    def preprocess(self):
        if self.params.col_types_changed:
            try:
                # engine='python' is to avoid pandas's bug.
                data = pd.read_csv(self.params.fpath, header=0, engine='python',
                                dtype=self.make_dtype(self.params.columns,
                                                        self.params.col_types))
            except Exception:
                import traceback
                self.params.error = traceback.format_exc()
                self.button_func('Error')
                return

            self.params.col_types_changed = False

            X = data.drop(self.params.objective, axis=1)
            y = data.loc[:, self.params.objective]

            self.params.mdl = MALSS(self.params.task.lower())
            self.params.X, self.params.y =\
                self.params.mdl.fit(X, y,
                                    algorithm_selection_only=True)

            self.params.algorithms = self.params.mdl.get_algorithms()
        elif self.params.results is not None:
            self.add_algorithm(self.params.mdl, self.params.algorithms,
                               self.params.results)

    def analyzed(self, signalData):
        self.wait_ani.hide()
        if 'error' in signalData:
            self.params.error = signalData['error']
            self.button_func('Error')
        else:
            if self.params.results is None:
                self.params.results = signalData
            else:
                # Update results of re-analyzed algorithms
                for name, results in signalData['algorithms'].items():
                    self.params.results['algorithms'][name]['grid_scores'] =\
                        results['grid_scores']
                    self.params.results['algorithms'][name]['learning_curve'] =\
                        results['learning_curve']

                # Update best algorithm
                if signalData['best_algorithm']['score'] >\
                        self.params.results['best_algorithm']['score']:
                    self.params.results['best_algorithm']['estimator'] =\
                        signalData['best_algorithm']['estimator']
                    self.params.results['best_algorithm']['score'] =\
                        signalData['best_algorithm']['score']

            if self.params.lang == 'en':
                self.button_func('Results')
            else:
                self.button_func('結果の確認')
 class MenuView(QScrollArea):

    def __init__(self, parent=None, update_func=None, params=None):
        super().__init__(parent)

        self.setMaximumWidth(200)

        self.params = params

        self.H1_HEIGHT = 50
        self.H2_HEIGHT = 50
        self.SIDE_MARGIN = 5
        self.H1_FONT_SIZE = 18
        self.H2_FONT_SIZE = 18
        self.H3_FONT_SIZE = 16
        self.TEXT_FONT_SIZE = 14

        style = '''
            QPushButton:flat{
                text-align: left;
                padding: 1ex;
            }
            QPushButton:pressed{
                background-color: silver;
            }
            QPushButton:hover:!pressed{
                font: bold;
            }
            '''
        self.setStyleSheet(style)

        self.update_func = update_func

        self.inner = QWidget(self)

        self.vbox = QVBoxLayout(self.inner)
        self.vbox.setSpacing(0)
        self.vbox.setContentsMargins(0, 0, 0, 0)
        self.vbox.setAlignment(Qt.AlignTop)

        topframe = QFrame()
        topframe.setStyleSheet('background-color: white')
        topframe.setFixedHeight(self.H1_HEIGHT)

        lbl_h1 = QLabel('Contents', topframe)
        fnt = lbl_h1.font()
        fnt.setPointSize(self.H1_FONT_SIZE)
        lbl_h1.setFont(fnt)
        lbl_h1.setFixedHeight(self.H1_HEIGHT)
        lbl_h1.setMargin(self.SIDE_MARGIN)

        self.vbox.addWidget(topframe)

        self.list_button = []
        if self.params.lang == 'en':
            self.edit_button('Introduction')
        else:
            self.edit_button('はじめに')

        self.inner.setLayout(self.vbox)

        self.setWidget(self.inner)

    def buttonClicked(self, text):
        if self.update_func is not None:
            self.update_func(text)

    def edit_button(self, text, delete=False, delete_after=False):
        if delete:
            """
            Delete a specific page with 'text'.
            """
            for i in range(self.vbox.count()):
                widget = self.vbox.itemAt(i).widget()
                if type(widget) == QPushButton:
                    if widget.text() == '-' + text:
                        self.vbox.removeWidget(widget)
                        widget.deleteLater()
                        widget = None
            return
        
        if delete_after:
            """
            Delete pages after the 'text' page.
            """
            delete_flag = False
            del_widgets = []
            for i in range(self.vbox.count()):
                widget = self.vbox.itemAt(i).widget()
                if type(widget) == QPushButton:
                    if widget.text() == '-' + text:
                        delete_flag = True
                        continue
                    if delete_flag:
                        del_widgets.append(widget)
            for widget in del_widgets:
                text = widget.text()[1:]
                if text in self.list_button:
                    self.list_button.remove(text)
                self.vbox.removeWidget(widget)
                widget.deleteLater()
                widget = None
            return

        if text not in self.list_button:
            self.list_button.append(text)
            btn = QPushButton('-' + text, self.inner)
            btn.setFlat(True)
            fnt = btn.font()
            fnt.setPointSize(self.TEXT_FONT_SIZE)
            btn.setFont(fnt)
            btn.clicked.connect(lambda: self.buttonClicked(text))
            self.vbox.addWidget(btn)

        self.buttonClicked(text)
 class Results(ResultsBase):
    def __init__(self, parent=None, button_func=None, params=None):
        super().__init__(parent, 'Results', params)

        self.button_func = button_func

        self.make_tables(self.params.results['algorithms'],
                         self.params.algorithms)

        self.vbox.addStretch()

        self.btn_re = QPushButton('Re-analyze', self.inner)
        self.btn_re.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        if self.params.lang == 'en':
            self.btn_re.clicked.connect(lambda: self.button_func('Analysis'))
        else:
            self.btn_re.clicked.connect(lambda: self.button_func('分析の実行'))
        self.btn_re.setEnabled(False)

        self.btn_next = QPushButton('Continue without any changes', self.inner)
        self.btn_next.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        if self.params.lang == 'en':
            self.btn_next.clicked.connect(lambda: self.button_func(
                'Bias and Variance'))
        else:
            self.btn_next.clicked.connect(lambda: self.button_func(
                'バイアスとバリアンス'))

        self.vbox.addWidget(self.btn_re)
        self.vbox.addWidget(self.btn_next)
 class Results2(ResultsBase):
    def __init__(self, parent=None, button_func=None, params=None):
        super().__init__(parent, 'Results2', params)

        self.button_func = button_func

        self.make_tables(self.params.results_fs['algorithms'],
                         self.params.algorithms_fs)

        self.vbox.addStretch()

        self.btn_re = QPushButton('Re-analyze', self.inner)
        self.btn_re.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        if self.params.lang == 'en':
            self.btn_re.clicked.connect(
                lambda: self.button_func('Feature selection'))
        else:
            self.btn_re.clicked.connect(
                lambda: self.button_func('特徴量選択'))
        self.btn_re.setEnabled(False)

        self.btn_next = QPushButton('Continue without any changes', self.inner)
        self.btn_next.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        if self.params.lang == 'en':
            self.btn_next.clicked.connect(lambda: self.button_func(
                'Learning curve 2'))
        else:
            self.btn_next.clicked.connect(lambda: self.button_func(
                '学習曲線２'))

        self.vbox.addWidget(self.btn_re)
        self.vbox.addWidget(self.btn_next)
 class BiasVariance(Content):

    def __init__(self, parent=None, button_func=None, params=None):
        super().__init__(parent, 'Bias and Variance', params)

        self.button_func = button_func

        path = os.path.abspath(os.path.dirname(__file__)) + '/static/'

        # Text for learning curve
        path1 = path + 'learning_curve'
        text = self.get_text(path1)
        if self.params.lang == 'en':
            self.set_paragraph('Learning curve', text=text, img=path1)
        else:
            self.set_paragraph('学習曲線', text=text, img=path1)

        # Text for bias and variance
        path2 = path + 'bias_variance'
        text = self.get_text(path2)
        if self.params.lang == 'en':
            self.set_paragraph('Bias and Variance', text=text, img=path2)
        else:
            self.set_paragraph('バイアスとバリアンス', text=text, img=path2)

        if self.params.lang == 'en':
            text = ("Let's check out the learning curves. "
                    'Click "Next" to continue.')
            self.set_paragraph('', text=text)
        else:
            text = ('それでは学習曲線を確認してみましょう．'
                    'Nextボタンを押してください．')
            self.set_paragraph('', text=text)

        self.vbox.addStretch(1)

        self.btn = QPushButton('Next', self.inner)
        self.btn.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        if self.params.lang == 'en':
            self.btn.clicked.connect(lambda: self.button_func(
                'Learning curve'))
        else:
            self.btn.clicked.connect(lambda: self.button_func('学習曲線'))

        self.vbox.addWidget(self.btn)
 class LearningCurve(LearningCurveBase):
    def __init__(self, parent=None, button_func=None, params=None):
        super().__init__(parent, 'LearningCurve', params)

        self.button_func = button_func

        path = os.path.abspath(os.path.dirname(__file__)) + '/static/'

        path1 = path + 'check_curve'
        text = self.get_text(path1)
        if self.params.lang == 'en':
            self.set_paragraph('', text=text)
        else:
            self.set_paragraph('', text=text)

        self.plot_curve(self.params.results['algorithms'])

        self.vbox.addStretch()

        btn_fs = QPushButton('Try feature selection', self.inner)
        btn_fs.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        btn_fs.clicked.connect(self.__button_clicked)

        self.btn_next = QPushButton('Continue', self.inner)
        self.btn_next.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        if self.params.lang == 'en':
            self.btn_next.clicked.connect(lambda: self.button_func(
                'Prediction'))
        else:
            self.btn_next.clicked.connect(lambda: self.button_func(
                '予測'))

        self.vbox.addWidget(btn_fs)
        self.vbox.addWidget(self.btn_next)

        # "parent.parent()" must be modified.
        self.wait_ani = WaitingAnimation(parent.parent())
        self.wait_ani.hide()

        lists = ['task', 'supervised_learning', 'dummy', 'hyperparameter',
                 'overfitting', 'cross_validation', 'learning_curve',
                 'bias_variance']
        if self.params.lang == 'jp':
            lists = [l + '_jp' for l in lists]
        else:
            lists = [l + '_en' for l in lists]
        self.wait_ani.set_lists(lists)

    def resizeEvent(self, event):
        # To be modified.
        self.wait_ani.resize(self.parent().parent().size())
        event.accept()

        QScrollArea.resizeEvent(self, event)

    def __button_clicked(self):
        self.__feature_selection()

    def __feature_selection(self):
        self.mdl_fs = copy.deepcopy(self.params.mdl)

        self.thread = FeatureSelectionWorker(self.mdl_fs)
        self.thread.finSignal.connect(self.__feature_selected)
        self.thread.start()
        self.wait_ani.show()

    def __feature_selected(self, signalData):
        self.wait_ani.hide()
        if 'error' in signalData:
            self.params.error = signalData['error']
            self.button_func('Error')
        else:
            if len(signalData['mdl'].data.X.columns) < len(self.params.X.columns):
                # some features deleted
                self.params.X_fs = signalData['mdl'].data.X

                self.params.mdl_fs = signalData['mdl']

                self.params.algorithms_fs = self.params.mdl_fs.get_algorithms()
                if self.params.lang == 'en':
                    self.button_func('Feature selection')
                else:
                    self.button_func('特徴量選択')
            else:
                # no features deleted
                self.params.not_deleted = True
                if self.params.lang == 'en':
                    self.button_func('Prediction')
                else:
                    self.button_func('予測')
 class LearningCurve2(LearningCurveBase):
    def __init__(self, parent=None, button_func=None, params=None):
        super().__init__(parent, 'LearningCurve 2', params)

        self.button_func = button_func

        path = os.path.abspath(os.path.dirname(__file__)) + '/static/'

        path1 = path + 'learning_curve_2'
        text = self.get_text(path1)
        if self.params.lang == 'en':
            self.set_paragraph('', text=text)
        else:
            self.set_paragraph('', text=text)

        self.plot_curve(self.params.results_fs['algorithms'])

        if self.params.lang == 'en':
            text = ('Finally, MALSS output analysis results, and you can '
                    'predict unknown data (if you have).\n'
                    'Press "Next" to continue.')
            self.set_paragraph('', text=text)
        else:
            text = ('最後に学習結果の出力と，未知データがあればその予測を'
                    '行いましょう．\nNextを押してください')
            self.set_paragraph('', text=text)

        self.vbox.addStretch()

        self.btn_next = QPushButton('Next', self.inner)
        self.btn_next.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        if self.params.lang == 'en':
            self.btn_next.clicked.connect(lambda: self.button_func(
                'Prediction'))
        else:
            self.btn_next.clicked.connect(lambda: self.button_func(
                '予測'))

        self.vbox.addWidget(self.btn_next)
 class FeatureSelection(Analyzer):

    def __init__(self, parent=None, button_func=None, params=None):
        super().__init__(parent, 'Feature selection', params)

        self.button_func = button_func

        self.preprocess()

        if self.params.lang == 'en':
            text = ('Selected features are shown below.')
            self.set_paragraph('Features', text=text)
        else:
            text = ('特徴量選択の結果を以下に示します．')
            self.set_paragraph('説明変数', text=text)

        nr = len(self.params.X.columns)

        table1 = NonScrollTable(self.inner)

        table1.setRowCount(nr)
        table1.setColumnCount(2)
        table1.setHorizontalHeaderLabels(['Original', 'Selected Features'])

        for r in range(nr):
            item = QTableWidgetItem(self.params.X.columns[r])
            item.setFlags(Qt.ItemIsEnabled)
            table1.setItem(r, 0, item)

            if self.params.X.columns[r] in self.params.X_fs.columns:
                item = QTableWidgetItem(self.params.X.columns[r])
            else:
                item = QTableWidgetItem('')
            item.setFlags(Qt.ItemIsEnabled)
            table1.setItem(r, 1, item)

        table1.setNonScroll()

        self.vbox.addWidget(table1)

        if self.params.lang == 'en':
            text = ('MALSS selected appropriate algorithms '
                    'according to your task and data.\n'
                    'Selected algorithms are shown below.\n'
                    '(Selected algorithms may be changed due to '
                    'the result of feature selection.)')
            self.set_paragraph('Algorithms', text=text)
        else:
            text = ('MALSSは分析タスクとデータに応じて適切なアルゴリズムを選択します．\n'
                    'アルゴリズム選択結果を以下の示します．\n'
                    '（特徴量が減ったことで選ばれるアルゴリズムが変わることがあります．）')
            self.set_paragraph('アルゴリズム', text=text)

        nr = len(self.params.algorithms_fs)

        table2 = NonScrollTable(self.inner)

        table2.setRowCount(nr)
        table2.setColumnCount(1)
        table2.setHorizontalHeaderLabels(['Algorithms'])

        for r in range(nr):
            item = QTableWidgetItem(self.params.algorithms_fs[r][0])
            item.setFlags(Qt.ItemIsEnabled)
            table2.setItem(r, 0, item)

        table2.setNonScroll()

        self.vbox.addWidget(table2)

        if self.params.lang == 'en':
            text = ('Clik "Analyze" to re-analyze with selected features.\n'
                    '(This will take tens of minutes.)')
            self.set_paragraph('', text=text)
        else:
            text = ('それでは特徴量選択した説明変数を用いて分析をしてみましょう，\n'
                    'Anayzeボタンを押してください．\n'
                    '（分析には数分～数十分かかります）')
            self.set_paragraph('', text=text)

        self.vbox.addStretch(1)

        btn = QPushButton('Analyze', self.inner)
        btn.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        if self.params.lang == 'en':
            next_page = 'Results 2'
        else:
            next_page = '結果の確認２'
        btn.clicked.connect(lambda: self.button_clicked(
            self.params.mdl_fs, self.params.X_fs, self.params.y, next_page))

        self.vbox.addWidget(btn)

        lists = ['task', 'supervised_learning', 'dummy', 'hyperparameter',
                 'overfitting', 'cross_validation', 'learning_curve',
                 'bias_variance']
        if self.params.lang == 'jp':
            lists = [l + '_jp' for l in lists]
        else:
            lists = [l + '_en' for l in lists]
        self.wait_ani.set_lists(lists)

    def preprocess(self):
        if self.params.results_fs is not None:
            self.add_algorithm(self.params.mdl_fs, self.params.algorithms_fs,
                               self.params.results_fs)

    def analyzed(self, signalData):
        self.wait_ani.hide()
        if 'error' in signalData:
            self.params.error = signalData['error']
            self.button_func('Error')
        else:
            if self.params.results_fs is None:
                self.params.results_fs = signalData
            else:
                for name, results in signalData['algorithms'].items():
                    self.params.results_fs['algorithms'][name]['grid_scores'] =\
                        results['grid_scores']
                    self.params.results_fs['algorithms'][name]['learning_curve'] =\
                        results['learning_curve']

            if self.params.lang == 'en':
                self.button_func('Results 2')
            else:
                self.button_func('結果の確認２')
 class Prediction(Content):

    def __init__(self, parent=None, button_func=None, params=None):
        super().__init__(parent, 'Prediction', params)

        self.button_func = button_func

        if params.lang == 'jp':
            text=('最も性能のよいモデルは以下のアルゴリズム，'
                  'ハイパーパラメータでした．')
            if self.params.not_deleted:
                text += '\n（特徴量選択の結果，説明変数は削減されませんでした．）'
            self.set_paragraph('最良のモデル', text=text)
        else:
            text=('Algorithm and hyper-parameters of the best model '
                  'are shown below.')
            if self.params.not_deleted:
                text += '\n(No features were deleted by feature selection.)'
            self.set_paragraph('Best model', text=text)

        self.show_best_algorithm()

        if params.lang == 'jp':
            self.set_paragraph(
                '学習結果の出力',
                text=('学習結果をresultsというフォルダ内に出力します．\n'
                      '予測モデルを出力するディレクトリを選択してください。\n'
                      '同名のファイルがある場合上書きされますので気をつけてください．'))
        else:
            self.set_paragraph(
                'Output your results',
                text=('You can output your results in the folder named'
                      '"results".\n'
                      'Choose your output directory.\n'
                      'Note that tha file will be overwritten.'))

        hbox1 = QHBoxLayout()
        hbox1.setContentsMargins(10, 10, 10, 10)

        lbl_dir = QLabel('Location:', self.inner)
        self.le_dir = QLineEdit(self.inner)
        do_btn = QPushButton('Browse...', self.inner)
        do_btn.clicked.connect(self.dir_open_dialog)

        hbox1.addWidget(lbl_dir)
        hbox1.addWidget(self.le_dir)
        hbox1.addWidget(do_btn)

        self.vbox.addLayout(hbox1)

        if self.params.out_dir is not None:
            self.le_dir.setText(self.params.out_dir)

        if params.lang == 'jp':
            self.set_paragraph(
                '未知データの予測',
                text=('学習したモデルで予測を行いたいデータ（目的変数の無いデータ）'
                      'があればファイルを選択してください．\n'
                      '入力ファイルは学習用データと説明変数の並び順が同じで，'
                      '目的変数の無いCSVファイルである必要があります\n'
                      '予測結果は入力ファイルと同じディレクトリにpredict.csv'
                      'という名前で出力されます．同名のファイルは上書きされます'
                      'ので気をつけてください．'))
        else:
            self.set_paragraph(
                'Prediction',
                text=('If you have a data to predict target variable, '
                      'choose your input file.\n'
                      'Input file must have same features as training data '
                      '(same order) and must not have target variable.\n'
                      'The results save as predict.csv in the same directory '
                      'as the input file. Note that the file will be '
                      'overwritten.'))

        hbox2 = QHBoxLayout()
        hbox2.setContentsMargins(10, 10, 10, 10)

        lbl_file = QLabel('Location:', self.inner)
        self.le_file = QLineEdit(self.inner)
        fo_btn = QPushButton('Browse...', self.inner)
        fo_btn.clicked.connect(self.file_open_dialog)

        hbox2.addWidget(lbl_file)
        hbox2.addWidget(self.le_file)
        hbox2.addWidget(fo_btn)

        self.vbox.addLayout(hbox2)

        if self.params.path_pred is not None:
            self.le_file.setText(self.params.path_pred)

        hbox3 = QHBoxLayout()
        hbox3.setContentsMargins(10, 10, 10, 10)

        self.btn = QPushButton('Output', self.inner)
        self.btn.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        self.btn.clicked.connect(self.__button_clicked)
        self.btn.setEnabled(False)

        hbox3.addStretch(1)
        hbox3.addWidget(self.btn)

        self.vbox.addLayout(hbox3)

        self.vbox.addStretch(1)

    def file_open_dialog(self):
        fname = QFileDialog.getOpenFileName(self, 'File open', '')
        self.le_file.setText(fname[0])
        self.params.path_pred = fname[0]

    def dir_open_dialog(self):
        dname = QFileDialog.getExistingDirectory(self, 'Directory open', '')
        dname += '/results'
        self.le_dir.setText(dname)
        self.btn.setEnabled(True)
        self.params.out_dir = dname

    def show_best_algorithm(self):
        self.best_algo_name = None
        self.best_param_names = None
        self.best_params = None
        self.best_score = -float('Inf')
        self.best_is_fs = False
        for name, results in self.params.results['algorithms'].items():
            grid_scores = results['grid_scores']
            for params, score, std in grid_scores:
                if score > self.best_score:
                    self.best_algo_name = name
                    self.best_param_names = list(params.keys())
                    self.best_params = list(params.values())
                    self.best_score = score
        if self.params.results_fs is not None:
            for name, results in self.params.results_fs['algorithms'].items():
                grid_scores = results['grid_scores']
                for params, score, std in grid_scores:
                    if score > self.best_score:
                        self.best_algo_name = name
                        self.best_param_names = list(params.keys())
                        self.best_params = list(params.values())
                        self.best_score = score
                        self.best_is_fs = True

        table1 = NonScrollTable(self.inner)

        table1.setRowCount(1)
        table1.setColumnCount(len(self.best_params) + 3)
        table1.setHorizontalHeaderLabels(
            ['Algorithm', 'Feature selection'] + self.best_param_names +
            ['Score'])

        item = QTableWidgetItem(self.best_algo_name)
        item.setFlags(Qt.ItemIsEnabled)
        table1.setItem(0, 0, item)

        if self.best_is_fs:
            item = QTableWidgetItem('Yes')
        else:
            item = QTableWidgetItem('No')
        item.setFlags(Qt.ItemIsEnabled)
        table1.setItem(0, 1, item)

        for c, v in enumerate(self.best_params):
            item = QTableWidgetItem(str(round(v, 4)))
            item.setFlags(Qt.ItemIsEnabled)
            table1.setItem(0, c + 2, item)

        item = QTableWidgetItem(str(round(self.best_score, 4)))
        item.setFlags(Qt.ItemIsEnabled)
        table1.setItem(0, len(self.best_params) + 2, item)

        table1.setNonScroll()

        self.vbox.addWidget(table1)

    def __button_clicked(self):
        self.__output()

        if self.params.path_pred is not None:
            self.__predict()

    def __output(self):
        if not os.path.exists(self.params.out_dir):
            os.mkdir(self.params.out_dir)

        with open(self.params.out_dir + '/result.txt', 'w') as fo:
            fo.write(
                'Training file: ' + os.path.basename(self.params.fpath) + '\n')
            fo.write(
                'Sample size: ' + str(len(self.params.X)) + '\n')
            fo.write('Columns (types):\n')
            for i, col in enumerate(self.params.columns):
                fo.write('  ' + col + ' (' + self.params.col_types[i] + ')\n')

            fo.write('\nBest result:\n')
            fo.write('  Feature selection: ')
            fo.write('Yes\n') if self.best_is_fs else fo.write('No\n')
            fo.write('  Features:\n')
            X = self.params.X_fs if self.best_is_fs else self.params.X
            for col in X.columns:
                fo.write('    ' + col + '\n')
            fo.write('  Algorithm: ' + self.best_algo_name + '\n')
            fo.write('  Parameters:\n')
            for i, name in enumerate(self.best_param_names):
                fo.write(
                    '    ' + name + ': ' + str(self.best_params[i]) + '\n')
            fo.write('  Score: ' + str(self.best_score) + '\n')

            fo.write('\nAll results\n')
            fo.write('  Feature selection: No\n')
            fo.write('    Features:\n')
            for col in self.params.X.columns:
                fo.write('      ' + col + '\n')
            fo.write('    Algorithms:\n')
            for name, rslt in self.params.results['algorithms'].items():
                self.__write_result(fo, name, rslt)

            if self.params.results_fs is not None:
                fo.write('\n  Feature selection: Yes\n')
                fo.write('    Features:\n')
                for col in self.params.X_fs.columns:
                    fo.write('      ' + col + '\n')
                fo.write('    Algorithms:\n')
                for name, rslt in self.params.results_fs['algorithms'].items():
                    self.__write_result(fo, name, rslt, 'Feature selected')

        self.__plot_curves()

    def __write_result(self, fo, name, result, suffix_lc=''):
        fo.write('      ' + name + '\n')
        fo.write('        Grid scores:\n')
        for pname in result['grid_scores'][0][0].keys():
            fo.write('          ' + pname + '\t')
        fo.write('Score\n')
        for params, score, std in result['grid_scores']:
            for val in params.values():
                fo.write('          ' + str(round(val, 6)) + '\t')
            fo.write(str(round(score, 4)) + '\n')
        fname = 'Learning curve_' + name
        if suffix_lc != '':
            fname += '_' + suffix_lc
        fname += '.png'
        fo.write('        Learning curve: ' + fname + '\n')

    def __plot_curves(self):
        ylim = self.__get_ylim(self.params.results['algorithms'])
        if self.params.results_fs is not None:
            ylim2 = self.__get_ylim(self.params.results_fs['algorithms'])
            if ylim2[0] < ylim[0]:
                ylim[0] = ylim2[0]
            if ylim2[1] > ylim[1]:
                ylim[1] = ylim2[1]

        for name, val in self.params.results['algorithms'].items():
            self.__plot_curve(name, val, ylim)

        if self.params.results_fs is not None:
            for name, val in self.params.results_fs['algorithms'].items():
                self.__plot_curve(name, val, ylim, 'Feature selected')

    def __plot_curve(self, name, val, ylim, suffix=''):
        x = val['learning_curve']['x']
        y_train = val['learning_curve']['y_train']
        y_cv = val['learning_curve']['y_cv']

        plt.plot(x, y_train, 'o-', color='dodgerblue',
                 label='Training score')
        plt.plot(x, y_cv, 'o-', color='darkorange',
                 label='Cross-validation score')
        plt.title(name)
        plt.xlabel('Training examples')
        plt.ylabel('Score')
        plt.grid(True)
        plt.ylim(ylim)
        plt.legend(loc="lower right")
        fname = self.params.out_dir + '/Learning curve_' + name
        if suffix != '':
            fname += '_' + suffix
        fname += '.png'
        plt.savefig(fname, bbox_inches='tight')
        plt.close()

    def __get_ylim(self, algorithms):
        ymin = float('Inf')
        ymax = -float('Inf')

        for name, val in algorithms.items():
            ymin = min([ymin, min(val['learning_curve']['y_cv'])])
            ymax = max([ymax, max(val['learning_curve']['y_train'])])
        margin = 0.05 * (ymax - ymin)

        return [ymin - margin, ymax + margin]

    def __predict(self):
        columns = []
        col_types = []
        for i in range(len(self.params.columns)):
            if self.params.columns[i] != self.params.objective:
                columns.append(self.params.columns[i])
                col_types.append(self.params.col_types[i])
        try:
            # engine='python' is to avoid pandas's bug.
            X = pd.read_csv(self.params.path_pred, header=0, engine='python',
                            dtype=self.make_dtype(columns, col_types))
        except Exception:
            import traceback
            self.params.error = traceback.format_exc()
            self.button_func('Error')
            return

        if self.best_is_fs:
            estimator = self.params.results_fs['best_algorithm']['estimator']
            mdl = self.params.mdl_fs
        else:
            estimator = self.params.results['best_algorithm']['estimator']
            mdl = self.params.mdl
        pred = mdl.predict(X, estimator)
        pd.Series(pred).to_csv(
            os.path.dirname(self.params.path_pred) + '/predict.csv',
            index=False, header=False)
 class Error(Content):
    def __init__(self, parent=None, button_func=None, params=None):
        super().__init__(parent, 'Error', params)

        if self.params.lang == 'en':
            text = ('Unexpected error occured.\n'
                    'Please exit the application and solve the problem.')
        else:
            text = ('予期せぬエラーが発生しました。\n'
                    'アプリケーションを終了し，問題を解決してください。')
        self.set_paragraph('Unexpected error', text=text)

        self.set_paragraph('Traceback log', text=self.params.error)

        self.vbox.addStretch(1)

        btn = QPushButton('Exit', self.inner)
        btn.setStyleSheet('QPushButton{font: bold; font-size: 15pt; background-color: white;};')
        btn.clicked.connect(QCoreApplication.instance().quit)

        self.vbox.addWidget(btn)

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QApplication, QFrame,
                             QVBoxLayout, QSplitter, QDesktopWidget)
from .params import Params
from .introduction import Introduction
from .type_of_task import TypeOfTask
from .set_file import SetFile
from .data_check import DataCheck
from .overfitting import Overfitting
from .analysis import Analysis
from .menuview import MenuView
from .results import Results, Results2
from .bias_variance import BiasVariance
from .learning_curve import LearningCurve, LearningCurve2
from .feature_selection import FeatureSelection
from .prediction import Prediction
from .error import Error

# coding: utf-8



class App(QWidget):
    def __init__(self, lang='en'):
        super().__init__()

        self.params = Params(lang)
        self.initUI()

    def initUI(self):
        self.txt2func = {
            'はじめに': Introduction, 'Introduction': Introduction,
            '分析タスク': TypeOfTask, 'Task': TypeOfTask,
            '入力データ': SetFile, 'Input data': SetFile,
            'データの確認': DataCheck, 'Data check': DataCheck,
            '過学習': Overfitting, 'Overfitting': Overfitting,
            '分析の実行': Analysis, 'Analysis': Analysis,
            '結果の確認': Results, 'Results': Results,
            'バイアスとバリアンス': BiasVariance, 'Bias and Variance': BiasVariance,

            '学習曲線': LearningCurve, 'Learning curve': LearningCurve,
