Passed
Push — master ( 7d2c3d...b4b259 )
by Simon
01:56 queued 11s
created

hyperactive.dashboards.progress_board.streamlit_backend   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 153
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 99
dl 0
loc 153
rs 10
c 0
b 0
f 0
wmc 23

7 Methods

Rating   Name   Duplication   Size   Complexity  
A StreamlitBackend.__init__() 0 11 2
A StreamlitBackend.create_plots() 0 7 1
B StreamlitBackend.filter_data() 0 29 6
A StreamlitBackend.plotly() 0 26 4
A StreamlitBackend.pyplot() 0 23 5
A StreamlitBackend.create_info() 0 20 3
A StreamlitBackend.get_progress_data() 0 7 2
1
# Author: Simon Blanke
2
# Email: [email protected]
3
# License: MIT License
4
5
import numbers
6
import numpy as np
7
import pandas as pd
8
import matplotlib.pyplot as plt
9
import plotly.express as px
10
11
try:
12
    from progress_io import ProgressIO
13
except:
14
    from .progress_io import ProgressIO
15
16
17
pd.options.mode.chained_assignment = "raise"
18
19
20
color_scale = px.colors.sequential.Jet
21
22
23
class StreamlitBackend:
24
    def __init__(self, search_ids):
25
        self.search_ids = search_ids
26
        self.search_id_dict = {}
27
28
        _io_ = ProgressIO("./")
29
30
        for search_id in search_ids:
31
            self.search_id_dict[search_id] = {}
32
33
            self.search_id_dict[search_id]["prog_d"] = _io_.load_progress(search_id)
34
            self.search_id_dict[search_id]["filt_f"] = _io_.load_filter(search_id)
35
36
    def get_progress_data(self, search_id):
37
        progress_data = self.search_id_dict[search_id]["prog_d"]
38
39
        if progress_data is None:
40
            return
41
42
        return progress_data[~progress_data.isin([np.nan, np.inf, -np.inf]).any(1)]
43
44
    def pyplot(self, progress_data):
45
        if progress_data is None or len(progress_data) <= 1:
46
            return None
47
48
        nth_iter = progress_data["nth_iter"]
49
        score_best = progress_data["score_best"]
50
        nth_process = list(progress_data["nth_process"])
51
52
        if np.all(nth_process == nth_process[0]):
53
            fig, ax = plt.subplots()
54
            plt.plot(nth_iter, score_best)
55
        else:
56
            fig, ax = plt.subplots()
57
            ax.set_xlabel("nth iteration")
58
            ax.set_ylabel("best score")
59
60
            for i in np.unique(nth_process):
61
                nth_iter_p = nth_iter[nth_process == i]
62
                score_best_p = score_best[nth_process == i]
63
                plt.plot(nth_iter_p, score_best_p, label=str(i) + ". process")
64
            plt.legend()
65
66
        return fig
67
68
    def filter_data(self, df, filter_df):
69
        prog_data_columns = list(df.columns)
70
71
        if len(df) > 1:
72
            for column in prog_data_columns:
73
                if column not in list(filter_df["parameter"]):
74
                    continue
75
76
                filter_ = filter_df[filter_df["parameter"] == column]
77
                lower, upper = (
78
                    filter_["lower bound"].values[0],
79
                    filter_["upper bound"].values[0],
80
                )
81
82
                col_data = df[column]
83
84
                if isinstance(lower, numbers.Number):
85
                    lower = float(lower)
86
                else:
87
                    lower = np.min(col_data)
88
89
                if isinstance(upper, numbers.Number):
90
                    upper = float(upper)
91
                else:
92
                    upper = np.max(col_data)
93
94
                df = df[(df[column] >= lower) & (df[column] <= upper)]
95
96
        return df
97
98
    def plotly(self, progress_data, search_id):
99
        if progress_data is None or len(progress_data) <= 1:
100
            return None
101
102
        filter_df = self.search_id_dict[search_id]["filt_f"]
103
104
        progress_data = progress_data.drop(
105
            ["nth_iter", "score_best", "nth_process", "best"], axis=1
106
        )
107
108
        if filter_df is not None:
109
            progress_data = self.filter_data(progress_data, filter_df)
110
111
        # remove score
112
        prog_data_columns = list(progress_data.columns)
113
        prog_data_columns.remove("score")
114
115
        fig = px.parallel_coordinates(
116
            progress_data,
117
            dimensions=prog_data_columns,
118
            color="score",
119
            color_continuous_scale=color_scale,
120
        )
121
        fig.update_layout(autosize=False, width=1200, height=540)
122
123
        return fig
124
125
    def create_plots(self, search_id):
126
        progress_data = self.get_progress_data(search_id)
127
128
        pyplot_fig = self.pyplot(progress_data)
129
        plotly_fig = self.plotly(progress_data, search_id)
130
131
        return pyplot_fig, plotly_fig
132
133
    def create_info(self, search_id):
134
        progress_data = self.get_progress_data(search_id)
135
        if progress_data is None or len(progress_data) <= 1:
136
            return None
137
138
        progress_data_best = progress_data[progress_data["best"] == 1]
139
140
        progress_data_best = progress_data_best.drop(
141
            ["nth_iter", "score_best", "nth_process", "best"], axis=1
142
        )
143
144
        progress_data_best = progress_data_best.sort_values("score")
145
        last_best = progress_data_best.tail(5)
146
        last_best = last_best.rename(
147
            columns={
148
                "score": "best 5 scores",
149
            }
150
        )
151
152
        return last_best
153