

import dash

from catboost import CatBoostClassifier, CatBoostRegressor
from xgboost import XGBClassifier, XGBRegressor
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor

from explainerdashboard.explainers import ClassifierExplainer, RegressionExplainer
from explainerdashboard.datasets import titanic_survive, titanic_fare, titanic_embarked, titanic_names
from explainerdashboard.dashboards import ExplainerDashboard


def get_classification_explainer(xgboost=False, include_y=True):
    X_train, y_train, X_test, y_test = titanic_survive()
    if xgboost:
        model = XGBClassifier().fit(X_train, y_train)
    else:
        model = RandomForestClassifier(n_estimators=50, max_depth=10).fit(X_train, y_train)
    if include_y:
        explainer = ClassifierExplainer(
                            model, X_test, y_test, 
                            cats=['Sex', 'Deck', 'Embarked'],
                            labels=['Not survived', 'Survived'])
    else:
        explainer = ClassifierExplainer(
                            model, X_test, 
                            cats=['Sex', 'Deck', 'Embarked'],
                            labels=['Not survived', 'Survived'])

    explainer.calculate_properties()
    return explainer


def get_regression_explainer(xgboost=False, include_y=True):
    X_train, y_train, X_test, y_test = titanic_fare()
    train_names, test_names = titanic_names()
    if xgboost:
        model = XGBRegressor().fit(X_train, y_train)
    else:
        model = RandomForestRegressor(n_estimators=50, max_depth=10).fit(X_train, y_train)

    if include_y:
        reg_explainer = RegressionExplainer(model, X_test, y_test, 
                                        cats=['Sex', 'Deck', 'Embarked'], 
                                        idxs=test_names, 
                                        units="$")
    else:
        reg_explainer = RegressionExplainer(model, X_test, 
                                        cats=['Sex', 'Deck', 'Embarked'], 
                                        idxs=test_names, 
                                        units="$")

    reg_explainer.calculate_properties()
    return reg_explainer

def get_multiclass_explainer(xgboost=False, include_y=True):
    X_train, y_train, X_test, y_test = titanic_embarked()
    train_names, test_names = titanic_names()
    if xgboost:
        model = XGBClassifier().fit(X_train, y_train)
    else:
        model = RandomForestClassifier(n_estimators=50, max_depth=10).fit(X_train, y_train)

    if include_y:
        if xgboost:
            multi_explainer = ClassifierExplainer(model, X_test, y_test,
                                            model_output='logodds',
                                            cats=['Sex', 'Deck'], 
                                            labels=['Queenstown', 'Southampton', 'Cherbourg'])
        else:
            multi_explainer = ClassifierExplainer(model, X_test, y_test,
                                            cats=['Sex', 'Deck'], 
                                            labels=['Queenstown', 'Southampton', 'Cherbourg'])
    else:
        if xgboost:
            multi_explainer = ClassifierExplainer(model, X_test, 
                                            model_output='logodds',
                                            cats=['Sex', 'Deck'], 
                                            labels=['Queenstown', 'Southampton', 'Cherbourg'])
        else:
            multi_explainer = ClassifierExplainer(model, X_test, 
                                            cats=['Sex', 'Deck'], 
                                            labels=['Queenstown', 'Southampton', 'Cherbourg'])

    multi_explainer.calculate_properties()
    return multi_explainer


def get_catboost_classifier():
    X_train, y_train, X_test, y_test = titanic_survive()
    train_names, test_names = titanic_names()

    model = CatBoostClassifier(iterations=100, verbose=0).fit(X_train, y_train)
    explainer = ClassifierExplainer(
                        model, X_test, y_test, 
                        cats=[{'Gender': ['Sex_female', 'Sex_male', 'Sex_nan']}, 
                                            'Deck', 'Embarked'],
                        labels=['Not survived', 'Survived'],
                        idxs=test_names)

    X_cats, y_cats = explainer.X_merged, explainer.y.astype("int")
    model = CatBoostClassifier(iterations=5, verbose=0).fit(X_cats, y_cats, cat_features=[5, 6, 7])
    explainer = ClassifierExplainer(model, X_cats, y_cats, idxs=X_test.index)
    explainer.calculate_properties(include_interactions=False)
    return explainer


def get_catboost_regressor():
    X_train, y_train, X_test, y_test = titanic_fare()

    model = CatBoostRegressor(iterations=5, verbose=0).fit(X_train, y_train)
    explainer = RegressionExplainer(model, X_test, y_test, 
                                    cats=["Sex", 'Deck', 'Embarked'])
    X_cats, y_cats = explainer.X_merged, explainer.y
    model = CatBoostRegressor(iterations=5, verbose=0).fit(X_cats, y_cats, cat_features=[5, 6, 7])
    explainer = RegressionExplainer(model, X_cats, y_cats, idxs=X_test.index)
    explainer.calculate_properties(include_interactions=False)
    return explainer


def test_classification_dashboard(dash_duo):
    explainer = get_classification_explainer()
    db = ExplainerDashboard(explainer, title="testing", responsive=False)
    dash_duo.start_server(db.app)
    dash_duo.wait_for_text_to_equal("h1", "testing", timeout=30)
    assert dash_duo.get_logs() == [], "browser console should contain no error"


def test_regression_dashboard(dash_duo):
    explainer = get_regression_explainer()
    db = ExplainerDashboard(explainer, title="testing", responsive=False)
    dash_duo.start_server(db.app)
    dash_duo.wait_for_text_to_equal("h1", "testing", timeout=20)
    assert dash_duo.get_logs() == [], "browser console should contain no error"

def test_simple_classification_dashboard(dash_duo):
    explainer = get_classification_explainer()
    db = ExplainerDashboard(explainer, title="testing", responsive=False, simple=True)
    dash_duo.start_server(db.app)
    dash_duo.wait_for_text_to_equal("#simple-classifier-composite-title", "testing", timeout=20)
    assert dash_duo.get_logs() == [], "browser console should contain no error"


def test_simple_regression_dashboard(dash_duo):
    explainer = get_regression_explainer()
    db = ExplainerDashboard(explainer, title="testing", responsive=False, simple=True)
    dash_duo.start_server(db.app)
    dash_duo.wait_for_text_to_equal("#simple-regression-composite-title", "testing", timeout=20)
    assert dash_duo.get_logs() == [], "browser console should contain no error"


def test_multiclass_dashboard(dash_duo):
    explainer = get_multiclass_explainer()
    db = ExplainerDashboard(explainer, title="testing", responsive=False)
    dash_duo.start_server(db.app)
    dash_duo.wait_for_text_to_equal("h1", "testing", timeout=30)
    assert dash_duo.get_logs() == [], "browser console should contain no error"


def test_xgboost_classification_dashboard(dash_duo):
    explainer = get_classification_explainer(xgboost=True)
    db = ExplainerDashboard(explainer, title="testing", responsive=False)
    dash_duo.start_server(db.app)
    dash_duo.wait_for_text_to_equal("h1", "testing", timeout=30)
    assert dash_duo.get_logs() == [], "browser console should contain no error"


def test_xgboost_regression_dashboard(dash_duo):
    explainer = get_regression_explainer(xgboost=True)
    db = ExplainerDashboard(explainer, title="testing", responsive=False)
    dash_duo.start_server(db.app)
    dash_duo.wait_for_text_to_equal("h1", "testing", timeout=30)
    assert dash_duo.get_logs() == [], "browser console should contain no error"


def test_xgboost_multiclass_dashboard(dash_duo):
    explainer = get_multiclass_explainer(xgboost=True)
    db = ExplainerDashboard(explainer, title="testing", responsive=False)
    dash_duo.start_server(db.app)
    dash_duo.wait_for_text_to_equal("h1", "testing", timeout=30)
    assert dash_duo.get_logs() == [], "browser console should contain no error"


def test_classification_dashboard_no_y(dash_duo):
    explainer = get_classification_explainer(include_y=False)
    db = ExplainerDashboard(explainer, title="testing", responsive=False)
    dash_duo.start_server(db.app)
    dash_duo.wait_for_text_to_equal("h1", "testing", timeout=30)
    assert dash_duo.get_logs() == [], "browser console should contain no error"


def test_regression_dashboard_no_y(dash_duo):
    explainer = get_regression_explainer(include_y=False)
    db = ExplainerDashboard(explainer, title="testing", responsive=False)
    dash_duo.start_server(db.app)
    dash_duo.wait_for_text_to_equal("h1", "testing", timeout=30)
    assert dash_duo.get_logs() == [], "browser console should contain no error"


def test_multiclass_dashboard_no_y(dash_duo):
    explainer = get_multiclass_explainer(include_y=False)
    db = ExplainerDashboard(explainer, title="testing", responsive=False)
    dash_duo.start_server(db.app)
    dash_duo.wait_for_text_to_equal("h1", "testing", timeout=30)
    assert dash_duo.get_logs() == [], "browser console should contain no error"


def test_catboost_classification_dashboard(dash_duo):
    explainer = get_catboost_classifier()
    db = ExplainerDashboard(explainer, title="testing", responsive=False)
    dash_duo.start_server(db.app)
    dash_duo.wait_for_text_to_equal("h1", "testing", timeout=30)
    assert dash_duo.get_logs() == [], "browser console should contain no error"


def test_cat_boost_regression_dashboard(dash_duo):
    explainer = get_catboost_regressor()
    db = ExplainerDashboard(explainer, title="testing", responsive=False)
    dash_duo.start_server(db.app)
    dash_duo.wait_for_text_to_equal("h1", "testing", timeout=30)
    assert dash_duo.get_logs() == [], "browser console should contain no error"
[((551, 568), 'explainerdashboard.datasets.titanic_survive', 'titanic_survive', ([], {}), '()\n', (566, 568), False, 'from explainerdashboard.datasets import titanic_survive, titanic_fare, titanic_embarked, titanic_names\n'), ((1362, 1376), 'explainerdashboard.datasets.titanic_fare', 'titanic_fare', ([], {}), '()\n', (1374, 1376), False, 'from explainerdashboard.datasets import titanic_survive, titanic_fare, titanic_embarked, titanic_names\n'), ((1407, 1422), 'explainerdashboard.datasets.titanic_names', 'titanic_names', ([], {}), '()\n', (1420, 1422), False, 'from explainerdashboard.datasets import titanic_survive, titanic_fare, titanic_embarked, titanic_names\n'), ((2286, 2304), 'explainerdashboard.datasets.titanic_embarked', 'titanic_embarked', ([], {}), '()\n', (2302, 2304), False, 'from explainerdashboard.datasets import titanic_survive, titanic_fare, titanic_embarked, titanic_names\n'), ((2335, 2350), 'explainerdashboard.datasets.titanic_names', 'titanic_names', ([], {}), '()\n', (2348, 2350), False, 'from explainerdashboard.datasets import titanic_survive, titanic_fare, titanic_embarked, titanic_names\n'), ((3825, 3842), 'explainerdashboard.datasets.titanic_survive', 'titanic_survive', ([], {}), '()\n', (3840, 3842), False, 'from explainerdashboard.datasets import titanic_survive, titanic_fare, titanic_embarked, titanic_names\n'), ((3873, 3888), 'explainerdashboard.datasets.titanic_names', 'titanic_names', ([], {}), '()\n', (3886, 3888), False, 'from explainerdashboard.datasets import titanic_survive, titanic_fare, titanic_embarked, titanic_names\n'), ((3986, 4168), 'explainerdashboard.explainers.ClassifierExplainer', 'ClassifierExplainer', (['model', 'X_test', 'y_test'], {'cats': "[{'Gender': ['Sex_female', 'Sex_male', 'Sex_nan']}, 'Deck', 'Embarked']", 'labels': "['Not survived', 'Survived']", 'idxs': 'test_names'}), "(model, X_test, y_test, cats=[{'Gender': ['Sex_female',\n    'Sex_male', 'Sex_nan']}, 'Deck', 'Embarked'], labels=['Not survived',\n    'Survived'], idxs=test_names)\n", (4005, 4168), False, 'from explainerdashboard.explainers import ClassifierExplainer, RegressionExplainer\n'), ((4488, 4549), 'explainerdashboard.explainers.ClassifierExplainer', 'ClassifierExplainer', (['model', 'X_cats', 'y_cats'], {'idxs': 'X_test.index'}), '(model, X_cats, y_cats, idxs=X_test.index)\n', (4507, 4549), False, 'from explainerdashboard.explainers import ClassifierExplainer, RegressionExplainer\n'), ((4705, 4719), 'explainerdashboard.datasets.titanic_fare', 'titanic_fare', ([], {}), '()\n', (4717, 4719), False, 'from explainerdashboard.datasets import titanic_survive, titanic_fare, titanic_embarked, titanic_names\n'), ((4814, 4890), 'explainerdashboard.explainers.RegressionExplainer', 'RegressionExplainer', (['model', 'X_test', 'y_test'], {'cats': "['Sex', 'Deck', 'Embarked']"}), "(model, X_test, y_test, cats=['Sex', 'Deck', 'Embarked'])\n", (4833, 4890), False, 'from explainerdashboard.explainers import ClassifierExplainer, RegressionExplainer\n'), ((5096, 5157), 'explainerdashboard.explainers.RegressionExplainer', 'RegressionExplainer', (['model', 'X_cats', 'y_cats'], {'idxs': 'X_test.index'}), '(model, X_cats, y_cats, idxs=X_test.index)\n', (5115, 5157), False, 'from explainerdashboard.explainers import ClassifierExplainer, RegressionExplainer\n'), ((5345, 5409), 'explainerdashboard.dashboards.ExplainerDashboard', 'ExplainerDashboard', (['explainer'], {'title': '"""testing"""', 'responsive': '(False)'}), "(explainer, title='testing', responsive=False)\n", (5363, 5409), False, 'from explainerdashboard.dashboards import ExplainerDashboard\n'), ((5684, 5748), 'explainerdashboard.dashboards.ExplainerDashboard', 'ExplainerDashboard', (['explainer'], {'title': '"""testing"""', 'responsive': '(False)'}), "(explainer, title='testing', responsive=False)\n", (5702, 5748), False, 'from explainerdashboard.dashboards import ExplainerDashboard\n'), ((6037, 6114), 'explainerdashboard.dashboards.ExplainerDashboard', 'ExplainerDashboard', (['explainer'], {'title': '"""testing"""', 'responsive': '(False)', 'simple': '(True)'}), "(explainer, title='testing', responsive=False, simple=True)\n", (6055, 6114), False, 'from explainerdashboard.dashboards import ExplainerDashboard\n'), ((6428, 6505), 'explainerdashboard.dashboards.ExplainerDashboard', 'ExplainerDashboard', (['explainer'], {'title': '"""testing"""', 'responsive': '(False)', 'simple': '(True)'}), "(explainer, title='testing', responsive=False, simple=True)\n", (6446, 6505), False, 'from explainerdashboard.dashboards import ExplainerDashboard\n'), ((6812, 6876), 'explainerdashboard.dashboards.ExplainerDashboard', 'ExplainerDashboard', (['explainer'], {'title': '"""testing"""', 'responsive': '(False)'}), "(explainer, title='testing', responsive=False)\n", (6830, 6876), False, 'from explainerdashboard.dashboards import ExplainerDashboard\n'), ((7179, 7243), 'explainerdashboard.dashboards.ExplainerDashboard', 'ExplainerDashboard', (['explainer'], {'title': '"""testing"""', 'responsive': '(False)'}), "(explainer, title='testing', responsive=False)\n", (7197, 7243), False, 'from explainerdashboard.dashboards import ExplainerDashboard\n'), ((7538, 7602), 'explainerdashboard.dashboards.ExplainerDashboard', 'ExplainerDashboard', (['explainer'], {'title': '"""testing"""', 'responsive': '(False)'}), "(explainer, title='testing', responsive=False)\n", (7556, 7602), False, 'from explainerdashboard.dashboards import ExplainerDashboard\n'), ((7897, 7961), 'explainerdashboard.dashboards.ExplainerDashboard', 'ExplainerDashboard', (['explainer'], {'title': '"""testing"""', 'responsive': '(False)'}), "(explainer, title='testing', responsive=False)\n", (7915, 7961), False, 'from explainerdashboard.dashboards import ExplainerDashboard\n'), ((8264, 8328), 'explainerdashboard.dashboards.ExplainerDashboard', 'ExplainerDashboard', (['explainer'], {'title': '"""testing"""', 'responsive': '(False)'}), "(explainer, title='testing', responsive=False)\n", (8282, 8328), False, 'from explainerdashboard.dashboards import ExplainerDashboard\n'), ((8623, 8687), 'explainerdashboard.dashboards.ExplainerDashboard', 'ExplainerDashboard', (['explainer'], {'title': '"""testing"""', 'responsive': '(False)'}), "(explainer, title='testing', responsive=False)\n", (8641, 8687), False, 'from explainerdashboard.dashboards import ExplainerDashboard\n'), ((8982, 9046), 'explainerdashboard.dashboards.ExplainerDashboard', 'ExplainerDashboard', (['explainer'], {'title': '"""testing"""', 'responsive': '(False)'}), "(explainer, title='testing', responsive=False)\n", (9000, 9046), False, 'from explainerdashboard.dashboards import ExplainerDashboard\n'), ((9333, 9397), 'explainerdashboard.dashboards.ExplainerDashboard', 'ExplainerDashboard', (['explainer'], {'title': '"""testing"""', 'responsive': '(False)'}), "(explainer, title='testing', responsive=False)\n", (9351, 9397), False, 'from explainerdashboard.dashboards import ExplainerDashboard\n'), ((9680, 9744), 'explainerdashboard.dashboards.ExplainerDashboard', 'ExplainerDashboard', (['explainer'], {'title': '"""testing"""', 'responsive': '(False)'}), "(explainer, title='testing', responsive=False)\n", (9698, 9744), False, 'from explainerdashboard.dashboards import ExplainerDashboard\n'), ((779, 896), 'explainerdashboard.explainers.ClassifierExplainer', 'ClassifierExplainer', (['model', 'X_test', 'y_test'], {'cats': "['Sex', 'Deck', 'Embarked']", 'labels': "['Not survived', 'Survived']"}), "(model, X_test, y_test, cats=['Sex', 'Deck', 'Embarked'],\n    labels=['Not survived', 'Survived'])\n", (798, 896), False, 'from explainerdashboard.explainers import ClassifierExplainer, RegressionExplainer\n'), ((1009, 1119), 'explainerdashboard.explainers.ClassifierExplainer', 'ClassifierExplainer', (['model', 'X_test'], {'cats': "['Sex', 'Deck', 'Embarked']", 'labels': "['Not survived', 'Survived']"}), "(model, X_test, cats=['Sex', 'Deck', 'Embarked'], labels\n    =['Not survived', 'Survived'])\n", (1028, 1119), False, 'from explainerdashboard.explainers import ClassifierExplainer, RegressionExplainer\n'), ((1636, 1744), 'explainerdashboard.explainers.RegressionExplainer', 'RegressionExplainer', (['model', 'X_test', 'y_test'], {'cats': "['Sex', 'Deck', 'Embarked']", 'idxs': 'test_names', 'units': '"""$"""'}), "(model, X_test, y_test, cats=['Sex', 'Deck', 'Embarked'],\n    idxs=test_names, units='$')\n", (1655, 1744), False, 'from explainerdashboard.explainers import ClassifierExplainer, RegressionExplainer\n'), ((1898, 1999), 'explainerdashboard.explainers.RegressionExplainer', 'RegressionExplainer', (['model', 'X_test'], {'cats': "['Sex', 'Deck', 'Embarked']", 'idxs': 'test_names', 'units': '"""$"""'}), "(model, X_test, cats=['Sex', 'Deck', 'Embarked'], idxs=\n    test_names, units='$')\n", (1917, 1999), False, 'from explainerdashboard.explainers import ClassifierExplainer, RegressionExplainer\n'), ((2592, 2736), 'explainerdashboard.explainers.ClassifierExplainer', 'ClassifierExplainer', (['model', 'X_test', 'y_test'], {'model_output': '"""logodds"""', 'cats': "['Sex', 'Deck']", 'labels': "['Queenstown', 'Southampton', 'Cherbourg']"}), "(model, X_test, y_test, model_output='logodds', cats=[\n    'Sex', 'Deck'], labels=['Queenstown', 'Southampton', 'Cherbourg'])\n", (2611, 2736), False, 'from explainerdashboard.explainers import ClassifierExplainer, RegressionExplainer\n'), ((2909, 3029), 'explainerdashboard.explainers.ClassifierExplainer', 'ClassifierExplainer', (['model', 'X_test', 'y_test'], {'cats': "['Sex', 'Deck']", 'labels': "['Queenstown', 'Southampton', 'Cherbourg']"}), "(model, X_test, y_test, cats=['Sex', 'Deck'], labels=[\n    'Queenstown', 'Southampton', 'Cherbourg'])\n", (2928, 3029), False, 'from explainerdashboard.explainers import ClassifierExplainer, RegressionExplainer\n'), ((3174, 3309), 'explainerdashboard.explainers.ClassifierExplainer', 'ClassifierExplainer', (['model', 'X_test'], {'model_output': '"""logodds"""', 'cats': "['Sex', 'Deck']", 'labels': "['Queenstown', 'Southampton', 'Cherbourg']"}), "(model, X_test, model_output='logodds', cats=['Sex',\n    'Deck'], labels=['Queenstown', 'Southampton', 'Cherbourg'])\n", (3193, 3309), False, 'from explainerdashboard.explainers import ClassifierExplainer, RegressionExplainer\n'), ((3484, 3596), 'explainerdashboard.explainers.ClassifierExplainer', 'ClassifierExplainer', (['model', 'X_test'], {'cats': "['Sex', 'Deck']", 'labels': "['Queenstown', 'Southampton', 'Cherbourg']"}), "(model, X_test, cats=['Sex', 'Deck'], labels=[\n    'Queenstown', 'Southampton', 'Cherbourg'])\n", (3503, 3596), False, 'from explainerdashboard.explainers import ClassifierExplainer, RegressionExplainer\n'), ((3902, 3947), 'catboost.CatBoostClassifier', 'CatBoostClassifier', ([], {'iterations': '(100)', 'verbose': '(0)'}), '(iterations=100, verbose=0)\n', (3920, 3947), False, 'from catboost import CatBoostClassifier, CatBoostRegressor\n'), ((4384, 4427), 'catboost.CatBoostClassifier', 'CatBoostClassifier', ([], {'iterations': '(5)', 'verbose': '(0)'}), '(iterations=5, verbose=0)\n', (4402, 4427), False, 'from catboost import CatBoostClassifier, CatBoostRegressor\n'), ((4733, 4775), 'catboost.CatBoostRegressor', 'CatBoostRegressor', ([], {'iterations': '(5)', 'verbose': '(0)'}), '(iterations=5, verbose=0)\n', (4750, 4775), False, 'from catboost import CatBoostClassifier, CatBoostRegressor\n'), ((4993, 5035), 'catboost.CatBoostRegressor', 'CatBoostRegressor', ([], {'iterations': '(5)', 'verbose': '(0)'}), '(iterations=5, verbose=0)\n', (5010, 5035), False, 'from catboost import CatBoostClassifier, CatBoostRegressor\n'), ((601, 616), 'xgboost.XGBClassifier', 'XGBClassifier', ([], {}), '()\n', (614, 616), False, 'from xgboost import XGBClassifier, XGBRegressor\n'), ((665, 718), 'sklearn.ensemble.RandomForestClassifier', 'RandomForestClassifier', ([], {'n_estimators': '(50)', 'max_depth': '(10)'}), '(n_estimators=50, max_depth=10)\n', (687, 718), False, 'from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor\n'), ((1455, 1469), 'xgboost.XGBRegressor', 'XGBRegressor', ([], {}), '()\n', (1467, 1469), False, 'from xgboost import XGBClassifier, XGBRegressor\n'), ((1518, 1570), 'sklearn.ensemble.RandomForestRegressor', 'RandomForestRegressor', ([], {'n_estimators': '(50)', 'max_depth': '(10)'}), '(n_estimators=50, max_depth=10)\n', (1539, 1570), False, 'from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor\n'), ((2383, 2398), 'xgboost.XGBClassifier', 'XGBClassifier', ([], {}), '()\n', (2396, 2398), False, 'from xgboost import XGBClassifier, XGBRegressor\n'), ((2447, 2500), 'sklearn.ensemble.RandomForestClassifier', 'RandomForestClassifier', ([], {'n_estimators': '(50)', 'max_depth': '(10)'}), '(n_estimators=50, max_depth=10)\n', (2469, 2500), False, 'from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor\n')]