Ejemplo n.º 1
0
    def _make_plot(self):
        plt.close(1)
        fig_margin = {'top': 25, 'bottom': 35, 'left': 35, 'right':25}
        fig_layout = {'height': '100%', 'width': '100%' }
        layout_args = {'fig_margin': fig_margin, 'layout': fig_layout,
                       'max_aspect_ratio': 1.618}
        self.voigt_fig = plt.figure(1, title='Voigt profile', **layout_args)
        self.voigt_plot = plt.plot(self.freq, self.h, scales={'y': LogScale()})
        plt.xlabel("Δν / ΔνD")

        plt.close(2)
        self.abs_fig = plt.figure(2, title='(αᶜ + αˡ) / α₅₀₀', **layout_args)
        self.abs_plot = plt.plot(self.freq, self.xq, scales={'y': LogScale()})
        plt.xlabel("Δν / ΔνD")

        plt.close(3)
        self.int_fig = plt.figure(3, title='Intensity', **layout_args)
        self.int_plot = plt.plot(self.freq, self.prof, scales={'y': LogScale()})
        plt.xlabel("Δν / ΔνD")

        plt.close(4)
        self.source_fig = plt.figure(4, title='Source Function', **layout_args)
        self.source_plot = plt.plot(np.log10(self.tau500), self.source_function,
                                    scales={'y': LogScale()})
        plt.xlabel("lg(τ₅₀₀)")
        self.tau_labels = plt.label(['τᶜ = 1', 'τˡ = 1'], colors=['black'],
                                    x=np.array([np.log10(self.tau500_cont),
                                                np.log10(self.tau500_line)]),
                                    y=np.array([self.source_function_cont,
                                                self.source_function_line]),
                                    y_offset=-25, align='middle')
        self.tau_line_plot = plt.plot(np.array([np.log10(self.tau500_line),
                                                np.log10(self.tau500_line)]),
                                      np.array([self.source_function_line / 1.5,
                                                self.source_function_line * 1.5]),
                                      colors=['black'])
        self.tau_cont_plot = plt.plot(np.array([np.log10(self.tau500_cont),
                                                np.log10(self.tau500_cont)]),
                                      np.array([self.source_function_cont / 1.5,
                                                self.source_function_cont * 1.5]),
                                      colors=['black'])
Ejemplo n.º 2
0
def Interactive_Pareto_front(N,I_for,E_for,d_for,S0,Smax,Smin,env_min,c,solutions_optim_relea,results1_optim_relea,results2_optim_relea):
    
    members_num = np.shape(I_for)[0]
    
    population_size = np.shape(solutions_optim_relea)[0]
    sdpen = np.zeros([members_num,population_size])
    sdpen_mean = np.zeros(population_size)
    sdpen_std = np.zeros(population_size)
    sd = np.zeros([members_num,population_size])
    sd_mean = np.zeros(population_size)
    sd_std = np.zeros(population_size)
    
    for i in range(population_size):
        S_opt,env_opt,w_opt,r_opt = syst_sim(N,I_for+solutions_optim_relea[i],E_for,d_for,S0,Smax,env_min)
        sdpen[:,i] = np.sum(np.maximum(d_for-r_opt,np.zeros(np.shape(d_for)))**2,axis = 1)
        sdpen_mean[i] = np.mean(sdpen[:,i])
        sdpen_std[i] = np.std(sdpen[:,i])
        sd[:,i] = np.sum(np.maximum(d_for-r_opt,np.zeros(np.shape(d_for))),axis = 1)
        sd_mean[i] = np.mean(sd[:,i])
        sd_std[i] = np.std(sd[:,i])
    
    # Interactive Pareto front
    def update_operation(i):
        S,env,w,r    = syst_sim(N,I_for+solutions_optim_relea[i],E_for,d_for,S0,Smax,env_min)
        fig_wd.title = 'Total supply deficit = '+str((sd_mean[i]).astype('int'))+' ± '+str((sd_std[i]).astype('int'))+' ML'
        fig_in.title = 'Natural + pumped inflows - Total pumped vol = {:.0f} ML'.format(results2_optim_relea[i]/c)
        return       S,solutions_optim_relea[i],r,results1_optim_relea[i],results2_optim_relea[i],i
    
    def solution_selected(change):
        if pareto_front.selected == None:
            pareto_front.selected = [0]
        storage.y = update_operation(pareto_front.selected[0])[0]
        deficit.y = np.maximum(d_for-update_operation(pareto_front.selected[0])[2],np.zeros(np.shape(d_for)))
        pump_inflows.y = update_operation(pareto_front.selected[0])[1]
        tot_inflows.y = update_operation(pareto_front.selected[0])[1] + I_for
        pareto_front_ensemble.x = np.reshape([results2_optim_relea for i in range(0, members_num)],(members_num,population_size))[:,pareto_front.selected[0]]
        pareto_front_ensemble.y = sdpen[:,pareto_front.selected[0]]
        pareto_front_ensemble.unselected_style={'opacity': 0.1}
        pareto_front_ensemble.selected_style={'opacity': 0.1}
        pareto_front_ensemble.opacity = [0.1]*members_num
        
    x_sc_pf = LinearScale()
    y_sc_pf = LinearScale(min = 0,max = 4000)
    
    x_ax_pf = Axis(label='Total Pumping Cost [£]', scale=x_sc_pf)
    y_ax_pf = Axis(label='Total Squared Deficit [ML^2]', scale=y_sc_pf, orientation='vertical')
    
    pareto_front = plt.scatter(results2_optim_relea[:],results1_optim_relea[:],scales={'x': x_sc_pf, 'y': y_sc_pf},colors=['deepskyblue'], interactions={'hover':'tooltip','click': 'select'})
    pareto_front.unselected_style={'opacity': 0.8}
    pareto_front.selected_style={'fill': 'red', 'stroke': 'yellow', 'width': '1125px', 'height': '125px'}
    
    if pareto_front.selected == []:
        pareto_front.selected = [0]
        
    pareto_front_ensemble = plt.Scatter(x=np.reshape([results2_optim_relea for i in range(0, members_num)],(members_num,population_size))[:,pareto_front.selected[0]],
                                        y=sdpen[:,pareto_front.selected[0]],scales={'x': x_sc_pf, 'y': y_sc_pf},
                                        colors=['red'], 
                                        interactions={'hover':'tooltip','click': 'select'})
    pareto_front_ensemble.unselected_style={'opacity': 0.1}
    pareto_front_ensemble.selected_style={'opacity': 0.1}
    pareto_front_ensemble.opacity = [0.1]*members_num
        
    fig_pf = plt.Figure(marks=[pareto_front,pareto_front_ensemble],title = 'Pareto front', axes=[x_ax_pf, y_ax_pf],layout={'width': '500px', 'height': '500px'}, 
                        animation_duration=500)
    
    pareto_front.observe(solution_selected,'selected')    
    
    S,env,w,r    = syst_sim(N,I_for+solutions_optim_relea[pareto_front.selected[0]],E_for,d_for,S0,Smax,env_min)
    
    x_sc_in = OrdinalScale(min=1,max=N)
    y_sc_in = LinearScale(min=0,max=100)
    x_ax_in = Axis(label='week', scale=x_sc_in)
    y_ax_in = Axis(label='ML/week', scale=y_sc_in, orientation='vertical')
    x_sc_st = LinearScale(min=0,max=N)
    y_sc_st = LinearScale(min=0,max=160)
    x_ax_st = Axis(label='week', scale=x_sc_st)#,tick_values=[0.5,1.5,2.5,3.5])
    y_ax_st = Axis(label='ML', scale=y_sc_st, orientation='vertical')
    x_sc_wd = LinearScale(min=0.5,max=N+0.5)
    y_sc_wd = LinearScale(min=0,max=100);
    x_ax_wd = Axis(label='week', scale=x_sc_wd,tick_values=[1,2,3,4,5,6,7,8])
    y_ax_wd = Axis(label='ML/week', scale=y_sc_wd, orientation='vertical')
   
    pump_inflows = plt.Lines(x=np.arange(1,N+1),
                             y=solutions_optim_relea[pareto_front.selected[0]],
                             scales={'x': x_sc_in, 'y': y_sc_in},
                             colors=['orange'],
                             opacities = [1],
                             stroke_width = 1,
                             marker = 'circle',
                             marker_size = 10,
                             labels = ['pump (Qreg_inf)'], 
                             fill = 'bottom',
                             fill_opacities = [1],
                             fill_colors = ['orange']*members_num*N)
    tot_inflows = plt.Lines(x = np.arange(1,N+1), 
                            y = solutions_optim_relea[pareto_front.selected[0]]+I_for,
                            scales={'x': x_sc_wd, 'y': y_sc_wd},
                            colors=['blue'],
                            opacities = [1]*members_num,
                            stroke_width = 0.5,
                            marker = 'circle',
                            marker_size = 10,
                            labels = ['nat (I) + pump (Qreg_inf)'],
                            fill = 'bottom',
                            fill_opacities = [1/members_num]*members_num*N,
                            fill_colors = ['blue']*members_num*N)
    fig_in   = plt.Figure(marks = [tot_inflows,pump_inflows],axes=[x_ax_in, y_ax_in],layout={'max_width': '480px', 'max_height': '250px'},
                        scales={'x': x_sc_in, 'y': y_sc_in}, animation_duration=1000,legend_location = 'bottom-right')
    
    storage           = plt.plot(x=np.arange(0,N+1),y=S,scales={'x': x_sc_st, 'y': y_sc_st},
                                  colors=['blue'], stroke_width = 0.1,
                                  fill = 'bottom', fill_opacities = [0.1]*members_num)
    max_storage       = plt.plot(x=np.arange(0,N+1),
                                 y=[Smax]*(N+1),
                                 colors=['red'],
                                 scales={'x': x_sc_st, 'y': y_sc_st})
    max_storage_label = plt.label(text = ['Max storage'], 
                                  x=[0],
                                  y=[Smax+10],
                                  colors=['red'])
    fig_st            = plt.Figure(marks = [storage,max_storage,max_storage_label], 
                                   title = 'Reservoir storage volume', 
                                   axes=[x_ax_st, y_ax_st],
                                   layout={'width': '1000px', 'height': '350px'}, 
                                   animation_duration=1000,
                                   scales={'x': x_sc_st, 'y': y_sc_st})

    deficit = plt.Lines(x = np.arange(1,N+1), 
                        y = np.maximum(d_for-r,np.zeros(np.shape(r))),
                        scales={'x': x_sc_wd, 'y': y_sc_wd},
                        colors=['red'],
                        stroke_width = 1,
                        opacities = [1]*members_num,
                        marker = 'circle',
                        marker_size = 10,
                        labels = ['max(0,d-Qreg_rel)'],
                        fill = 'bottom',
                        fill_opacities = [1/members_num]*members_num,
                        fill_colors = ['red']*members_num)

    fig_wd = plt.Figure(marks = [deficit],axes=[x_ax_wd, y_ax_wd],
                        layout={'max_width': '480px', 'max_height': '250px'},
                        animation_duration=1000,
                        legend_location = 'bottom-right')
    
    storage.y  = update_operation(pareto_front.selected[0])[0]
    deficit.y  = np.maximum(d_for-update_operation(pareto_front.selected[0])[2],np.zeros(np.shape(d_for)))
    pump_inflows.y = update_operation(pareto_front.selected[0])[1]
    tot_inflows.y = update_operation(pareto_front.selected[0])[1] + I_for

    
    storage.observe(solution_selected, ['x', 'y'])
    deficit.observe(solution_selected, ['x', 'y'])
    pump_inflows.observe(solution_selected, ['x', 'y'])
    tot_inflows.observe(solution_selected, ['x', 'y'])
    
    return fig_pf,fig_wd,fig_st,fig_in,pareto_front
Ejemplo n.º 3
0
def Interactive_Pareto_front_act(N,I_act,E_act,d_act,S0,Smax,Smin,env_min,c,solutions_optim_relea_2,results1_optim_relea_2,results2_optim_relea_2,sel_policy):
    
    population_size = np.shape(solutions_optim_relea_2)[0]
    sdpen_act_4 = np.zeros(population_size); pcost_act_4 = np.zeros(population_size)
    
    for i in range(population_size):
    
        pinfl_policy_4 = np.array(solutions_optim_relea_2[i])
    
        S_act_4,env_act_4,w_act_4,r_act_4    = syst_sim(N,I_act+pinfl_policy_4,E_act,d_act,S0,Smax,env_min)
        sdpen_act_4[i]       = (np.sum((np.maximum(d_act-r_act_4,[0]*N))**2)).astype('int')
        pcost_act_4[i]       = (np.sum(np.array(pinfl_policy_4)*c)).astype('int')    
        
    def update_operation_act_4(i):
        u            = solutions_optim_relea_2[i]
        S,env,w,r    = syst_sim(N,I_act+u,E_act,d_act,S0,Smax,env_min)
        fig_4b.title = 'Total supply deficit = '+str((np.sum((np.maximum(d_act-r,[0]*N)))).astype('int'))+' ML'
        fig_4d.title = 'Natural + pumped inflows - Total pumped vol = '+str((np.sum(np.array(u))).astype('int'))+' ML'
        return       S,u,r,i
    
    def solution_selected_act_4(change):
        if pareto_front_act_4.selected  == None:
            pareto_front_act_4.selected = [0] 
        deficit_4.y = np.maximum(d_act-update_operation_act_4(pareto_front_act_4.selected[0])[2], [0]*N)
        storage_4.y  = update_operation_act_4(pareto_front_act_4.selected[0])[0]
        pump_inflows_4.y = [update_operation_act_4(pareto_front_act_4.selected[0])[1]]
        tot_inflows_4.y = [update_operation_act_4(pareto_front_act_4.selected[0])[1]+I_act[0]]
        
    def on_hover_4pf(self, target):
        hover_elem_id = list(target.values())[1]['index']
        
    def on_element_click_4pf(self, target):
        click_elem_id = list(target.values())[1]['index']
        colors = ['deepskyblue']*population_size
        colors[click_elem_id] = 'red'
        pareto_front_4.colors = colors
    

    x_sc_2pf = LinearScale()
    y_sc_2pf = LinearScale()
    x_ax_2pf = Axis(label='Total Pumping Cost [£]', 
                    scale=x_sc_2pf)
    y_ax_2pf = Axis(label='Total Squared Deficit [ML^2]', 
                    scale=y_sc_2pf, 
                    orientation='vertical')
    
    pareto_front_4                  = plt.scatter(results2_optim_relea_2[:],
                                                  results1_optim_relea_2[:],
                                                  scales={'x': x_sc_2pf, 'y': y_sc_2pf},
                                                  colors=['deepskyblue'], 
                                                  opacity = [0.11]*population_size,
                                                  interactions={'hover':'tooltip'})
    pareto_front_4.tooltip          = None
    pareto_front_act_4                  = plt.scatter(pcost_act_4[:],sdpen_act_4[:],scales={'x': x_sc_2pf, 'y': y_sc_2pf},
                                                colors=['green'], interactions={'hover':'tooltip'})

    pareto_front_act_4.unselected_style = {'opacity': 0}
    pareto_front_act_4.selected_style   = {'fill': 'black', 'stroke': 'black', 'width': '1125px', 'height': '125px'}
    pareto_front_4.selected_style   = {'fill': 'red', 'stroke': 'red', 'width': '1125px', 'height': '125px'}
    pareto_front_act_4.tooltip          = None

    fig_4pf                         = plt.Figure(marks = [pareto_front_4,pareto_front_act_4 ],title = 'Pareto front', axes=[x_ax_2pf, y_ax_2pf],
                                               layout={'width': '500px', 'height': '500px'}, animation_duration=1000)
    
    if pareto_front_act_4.selected      == []:
        pareto_front_4.selected     = [sel_policy]
        pareto_front_act_4.selected     = [sel_policy]
    pareto_front_act_4.observe(solution_selected_act_4,'selected')
    pareto_front_act_4.on_hover(on_hover_4pf)
    pareto_front_4.on_hover(on_hover_4pf)
    
    x_sc_2b     = OrdinalScale(min=1,
                               max=N)
    y_sc_2b     = LinearScale(min=0,
                              max=100)
    x_ax_2b     = Axis(label='week', 
                       scale=x_sc_2b)
    y_ax_2b     = Axis(label='ML/week', 
                       scale=y_sc_2b, 
                       orientation='vertical')
    deficit_4   = plt.Lines(x=np.arange(1,N+1),
                            y=np.maximum(d_act-r_act_4,[0]*N),
                            colors=['red'],
                            opacities = [1],
                            stroke_width = 0.5, 
                            marker = 'circle',
                            marker_size = 15,
                            labels = ['max(0,d-Qreg_rel)'],
                            fill = 'bottom',
                            fill_opacities = [0.5],
                            fill_colors = ['red'],
                            display_legend = False,
                            scales={'x': x_sc_2b, 'y': y_sc_2b})  

    fig_4b      = plt.Figure(marks = [deficit_4],
                             axes=[x_ax_2b, y_ax_2b],
                             layout={'width': '480px', 'height': '250px'},
                             scales={'x': x_sc_2b, 'y': y_sc_2b}, 
                             animation_duration=1000,
                             legend_location = 'bottom-right', 
                             legend_style = {'fill': 'white', 'opacity': 0.5})
    
    x_sc_2c             = LinearScale(min=0,
                                      max=N)
    y_sc_2c             = LinearScale(min=0,
                                      max=160)
    x_ax_2c             = Axis(label='week', 
                               scale=x_sc_2c)
    y_ax_2c             = Axis(label='ML', 
                               scale=y_sc_2c, 
                               orientation='vertical')  
    max_storage_2       = plt.plot(x=np.arange(0,N+1),
                                   y=[Smax]*(N+1),
                                   colors=['red'],
                                   scales={'x': x_sc_2c, 'y': y_sc_2c})
    max_storage_label_2 = plt.label(text = ['Max storage'],
                                    x=[0],
                                    y=[Smax+10],
                                    colors=['red'])
    storage_4           = plt.Lines(x=np.arange(0,N+1),
                                    y=S_act_4,
                                    colors=['blue'],
                                    scales={'x': x_sc_2c, 'y': y_sc_2c},
                                    fill = 'bottom',fill_opacities = [0.8],
                                    fill_colors = ['blue'])
    fig_4c              = plt.Figure(marks = [storage_4,max_storage_2,max_storage_label_2],
                                     title = 'Reservoir storage (s)',
                                     axes=[x_ax_2c, y_ax_2c],
                                     layout={'width': '1000px', 'height': '350px'}, 
                                     animation_duration=1000,
                                     scales={'x': x_sc_2c, 'y': y_sc_2c})

    x_sc_2d = OrdinalScale(min=1,
                           max=N)
    y_sc_2d = LinearScale(min=0,
                          max=100)
    x_ax_2d = Axis(label='week', 
                   scale=x_sc_2d)
    y_ax_2d = Axis(label='ML/week', 
                   scale=y_sc_2d, 
                   orientation='vertical')    

    pump_inflows_4  = plt.Lines(x=np.arange(1,N+1),
                                y=[pinfl_policy_4],
                                colors=['orange'],
                                opacities = [1], 
                                stroke_width = 0.5, 
                                marker = 'circle',
                                marker_size = 15,
                                fill = 'bottom',
                                fill_opacities = [1],
                                fill_colors = ['orange'],
                                labels = ['pump (Qreg_inf)'], 
                                display_legend = True,
                                scales={'x': x_sc_2d, 'y': y_sc_2d})
    tot_inflows_4  = plt.Lines(x=np.arange(1,N+1),
                                y=[pinfl_policy_4+I_act[0]],
                                colors=['blue'],
                                opacities = [1], 
                                stroke_width = 1, 
                                marker = 'circle',
                                marker_size = 15,
                                fill = 'bottom',
                                fill_opacities = [0.5],
                                fill_colors = ['blue'],
                                labels = ['nat (I) + pump (Qreg_inf)'], 
                                display_legend = True,
                                scales={'x': x_sc_2d, 'y': y_sc_2d})
    
    fig_4d     = plt.Figure(marks = [tot_inflows_4,pump_inflows_4],
                            title = 'Natural + pumped inflows', 
                            axes=[x_ax_2d, y_ax_2d],
                            layout={'width': '480px', 'height': '250px'},
                            scales={'x': x_sc_2d, 'y': y_sc_2d}, 
                            animation_duration=1000,
                            legend_location = 'top', 
                            legend_style = {'fill': 'white', 'opacity': 0.5})
    
    deficit_4.y = np.maximum(d_act-update_operation_act_4(sel_policy)[2],[0]*N)
    storage_4.y  = update_operation_act_4(sel_policy)[0]
    pump_inflows_4.y = [update_operation_act_4(sel_policy)[1]]
    tot_inflows_4.y = [update_operation_act_4(sel_policy)[1]+I_act[0]]
    
    deficit_4.observe(solution_selected_act_4, ['x', 'y'])
    storage_4.observe(solution_selected_act_4, ['x', 'y'])
    pump_inflows_4.observe(solution_selected_act_4, ['x', 'y'])
    tot_inflows_4.observe(solution_selected_act_4, ['x', 'y'])
    
    return fig_4b,fig_4c,fig_4d,fig_4pf
Ejemplo n.º 4
0
def Interactive_Pareto_front_det(N,I_sel,E,d_sel,S0,Smax,Smin,env_min,c,solutions_optim_relea_2,results1_optim_relea_2,results2_optim_relea_2):
    
    def update_operation_2(i):
        u            = solutions_optim_relea_2[i]
        S,env,w,r    = syst_sim(N,I_sel+u,E,d_sel,S0,Smax,env_min)
        fig_2b.title = 'Total supply deficit = '+str((np.sum((np.maximum(d_sel-r,[0]*N)))).astype('int'))+' ML'
        fig_2d.title = 'Natural + pumped inflows - Total pumped vol = '+str((np.sum(np.array(u))).astype('int'))+' ML'
        return       S,u,r,i
    
    def solution_selected_2(change):
        if pareto_front_2.selected  == None:
            pareto_front_2.selected = [0]
        deficit_2.y = np.maximum(d_sel-update_operation_2(pareto_front_2.selected[0])[2],[0]*N)
        storage_2.y  = update_operation_2(pareto_front_2.selected[0])[0]
        pump_inflows_2.y = [update_operation_2(pareto_front_2.selected[0])[1]]
        tot_inflows_2.y = [update_operation_2(pareto_front_2.selected[0])[1]+I_sel[0]]
        
    x_sc_2pf = LinearScale();y_sc_2pf = LinearScale()
    x_ax_2pf = Axis(label='Total Pumping Cost [£]', scale=x_sc_2pf)
    y_ax_2pf = Axis(label='Total Squared Deficit [ML^2]', scale=y_sc_2pf, orientation='vertical')
    pareto_front_2                  = plt.scatter(results2_optim_relea_2[:],results1_optim_relea_2[:],scales={'x': x_sc_2pf, 'y': y_sc_2pf},
                                                colors=['deepskyblue'], interactions={'hover':'tooltip','click': 'select'})
    pareto_front_2.unselected_style = {'opacity': 0.4}
    pareto_front_2.selected_style   = {'fill': 'red', 'stroke': 'yellow', 'width': '1125px', 'height': '125px'}
    def_tt                          = Tooltip(fields=['x', 'y','index'],labels=['Pumping cost','Squared deficit', 'sol index'], 
                                            formats=['.1f', '.1f', '.0f'])
    pareto_front_2.tooltip          = def_tt
    fig_2pf                         = plt.Figure(marks = [pareto_front_2],title = 'Pareto front', axes=[x_ax_2pf, y_ax_2pf],
                                               layout={'width': '500px', 'height': '500px'}, animation_duration=1000)
    if pareto_front_2.selected      == []:
        pareto_front_2.selected     = [0]
    pareto_front_2.observe(solution_selected_2,'selected')    
    
    S,env,w,r = syst_sim(N,I_sel+solutions_optim_relea_2[pareto_front_2.selected[0]],E,d_sel,S0,Smax,env_min)
    
    x_sc_2b    = OrdinalScale(min=1,max=N);y_sc_2b = LinearScale(min=0,max=100)
    x_ax_2b = Axis(label='week', scale=x_sc_2b)
    y_ax_2b = Axis(label='ML/week', scale=y_sc_2b, orientation='vertical')

    deficit_2 = plt.Lines(x=np.arange(1,N+1),
                          y=np.maximum(d_sel-r,[0]*N),
                          colors=['red'],
                          opacities = [1],
                          stroke_width = 0.5, 
                          marker = 'circle',
                          marker_size = 15,
                          labels = ['max(0,d-Qreg_rel)'],
                          fill = 'bottom',
                          fill_opacities = [0.5],
                          fill_colors = ['red'],
                          display_legend = False,
                          scales={'x': x_sc_2b, 'y': y_sc_2b})    
    fig_2b     = plt.Figure(marks = [deficit_2],
                            axes=[x_ax_2b, y_ax_2b],
                            layout={'width': '480px', 'height': '250px'},
                            scales={'x': x_sc_2b, 'y': y_sc_2b}, 
                            animation_duration=1000,
                            legend_location = 'bottom-right', 
                            legend_style = {'fill': 'white', 'opacity': 0.5})
    
    x_sc_2c             = LinearScale(min=0,max=N)
    y_sc_2c             = LinearScale(min=0,max=160)
    x_ax_2c             = Axis(label='week', 
                               scale=x_sc_2c)
    y_ax_2c             = Axis(label='ML', 
                               scale=y_sc_2c, 
                               orientation='vertical')
    storage_2           = plt.Lines(x=np.arange(0,N+1),
                                y=S,colors=['blue'],
                                scales={'x': x_sc_2c, 'y': y_sc_2c},
                                fill = 'bottom',
                                fill_opacities = [0.8],
                                fill_colors = ['blue'])
    max_storage_2       = plt.plot(x=np.arange(0,N+1),
                                   y=[Smax]*(N+1),
                                   colors=['red'],
                                   scales={'x': x_sc_2c, 'y': y_sc_2c})
    max_storage_label_2 = plt.label(text = ['Max storage'], 
                                    x=[0],
                                    y=[Smax+10],
                                    colors=['red'])
    fig_2c              = plt.Figure(marks = [storage_2,max_storage_2,max_storage_label_2],
                                     title = 'Reservoir storage (s)',
                                     axes=[x_ax_2c, y_ax_2c],
                                     layout={'width': '1000px', 'height': '350px'}, 
                                     animation_duration=1000,
                                     scales={'x': x_sc_2c, 'y': y_sc_2c})
    
    x_sc_2d    = OrdinalScale(min=1,
                              max=N)
    y_sc_2d = LinearScale(min=0,
                          max=100)
    x_ax_2d = Axis(label='week', 
                   scale=x_sc_2d)
    y_ax_2d = Axis(label='ML/week', 
                   scale=y_sc_2d, 
                   orientation='vertical')
    # Stacked bars
    pump_inflows_2  = plt.Lines(x=np.arange(1,N+1),
                                y=(solutions_optim_relea_2[pareto_front_2.selected[0]]),
                                colors=['orange'],
                                opacities = [1], 
                                stroke_width = 0.5, 
                                marker = 'circle',
                                marker_size = 15,
                                fill = 'bottom',
                                fill_opacities = [1],
                                fill_colors = ['orange'],
                                labels = ['pump (Qreg_inf)'], 
                                display_legend = True,
                                scales={'x': x_sc_2d, 'y': y_sc_2d})
    tot_inflows_2  = plt.Lines(x=np.arange(1,N+1),
                                y=(solutions_optim_relea_2[pareto_front_2.selected[0]]+I_sel[0]),
                                colors=['blue'],
                                opacities = [1], 
                                stroke_width = 1, 
                                marker = 'circle',
                                marker_size = 15,
                                fill = 'bottom',
                                fill_opacities = [0.5],
                                fill_colors = ['blue'],
                                labels = ['nat (I) + pump (Qreg_inf)'], 
                                display_legend = True,
                                scales={'x': x_sc_2d, 'y': y_sc_2d})
    fig_2d     = plt.Figure(marks = [tot_inflows_2,pump_inflows_2],
                            title = 'Natural + pumped inflows', 
                            axes=[x_ax_2d, y_ax_2d],
                            layout={'width': '480px', 'height': '250px'}, 
                            scales={'x': x_sc_2d, 'y': y_sc_2d}, 
                            animation_duration=1000,
                            legend_location = 'top', 
                            legend_style = {'fill': 'white', 'opacity': 0.5})
    

    deficit_2.y = np.maximum(d_sel-update_operation_2(pareto_front_2.selected[0])[2],[0]*N)
    storage_2.y  = update_operation_2(pareto_front_2.selected[0])[0]
    pump_inflows_2.y = [update_operation_2(pareto_front_2.selected[0])[1]]
    tot_inflows_2.y = [update_operation_2(pareto_front_2.selected[0])[1]+I_sel[0]]
    
    deficit_2.observe(solution_selected_2, ['x', 'y'])
    storage_2.observe(solution_selected_2, ['x', 'y'])
    pump_inflows_2.observe(solution_selected_2, ['x', 'y'])
    tot_inflows_2.observe(solution_selected_2, ['x', 'y'])
    
    return fig_2pf,fig_2b,fig_2c,fig_2d,pareto_front_2
def Interactive_Pareto_front(simtime,I,E,d,S0,Smax,ms,env_min, demand_plot,solutions_optim_relea,results1_optim_relea,results2_optim_relea):
    def syst_sim(simtime,I,E,d,S0,Smax,env_min,Qreg):
    
        # Declare output variables
    
        S = [0]*(simtime+1) # reservoir storage in ML
    
        spill = [0]*(simtime) # spillage in ML
    
        env = [env_min]*(simtime) # environmental compensation flow
        
        S[0] = S0 # initial storage
    
        for t in range(simtime): # Loop for each time-step (week)
    
            # If at week t the inflow (I) is lower than the minimum environmental compensation (env_min), 
            # then the environmental compensation (env) = inflow (I)  
            if env_min >= I[t] :
                env[t] = I[t]
            # If the minimum environmental compensation is higher than the water resource available (S + I - E)
            # then the environmental compensation is equal to the higher value between 0 and the resource available
            if env_min >= S[t] + I[t] - E[t]:
                env[t] = max(0,S[t] + I[t] - E[t]) # S[t] = Smin then env[t] = I[t] and S[t+1] < Smin
            # If the demand is higher than the water resource available (S + I - E - env)
            # then the release for water supply is equal to the higher value between 0 and the resource available            
            if d[t] >= S[t] + I[t] - E[t] - env[t]:
                Qreg[t] = min(Qreg[t],max(0,S[t] + I[t] - E[t] - env[t]))
            # The spillage is equal to the higher value between 0 and the resource available exceeding the reservoir capacity
            spill[t] = max(0,S[t] + I[t] - Qreg[t] - env[t] - E[t] - Smax)
            # The final storage (initial storage in the next step) is equal to the storage + inflow - outflows
            S[t+1] = S[t] + I[t] - Qreg[t] - env[t]- E[t] - spill[t]
            
        return S,env,spill,Qreg
    
    def update_operation_4(i):
        Qreg = solutions_optim_relea[i]
        S,env,spill,Qreg1 = syst_sim(simtime,I,E,d,S0,Smax,env_min,Qreg)
        lspen = np.sum((np.maximum(ms-S,[0]*(simtime+1)))).astype('int')
        fig_4a.title = 'Reservoir storage - Minimum storage violation = '+str(lspen)+' ML'
        sdpen = (np.sum((np.maximum(d-Qreg1,[0]*simtime))**2)).astype('int')
        fig_4b.title = 'Supply vs Demand - Total squared deficit = '+str(sdpen)+' ML^2'
        return S,env,spill,Qreg1
    
    def solution_selected(change):
        if pareto_front.selected == None:
            pareto_front.selected = [0]
        y_vals_4a = update_operation_4(pareto_front.selected[0])[0]
        storage_4.y = y_vals_4a
        y_vals_4b = update_operation_4(pareto_front.selected[0])[3]
        releases_4.y = y_vals_4b
    
    x_sc_pf = LinearScale();y_sc_pf = LinearScale()
    x_ax_pf = Axis(label='Total squared deficit [ML^2]', scale=x_sc_pf)
    y_ax_pf = Axis(label='Minimum storage violation [ML]', scale=y_sc_pf, orientation='vertical')
    pareto_front = plt.scatter(results1_optim_relea[:],results2_optim_relea[:],scales={'x': x_sc_pf, 'y': y_sc_pf},
                               colors=['deepskyblue'], interactions={'hover':'tooltip','click': 'select'})
    pareto_front.unselected_style={'opacity': 0.4}
    pareto_front.selected_style={'fill': 'red', 'stroke': 'yellow', 'width': '1125px', 'height': '125px'}
    def_tt = Tooltip(fields=['x', 'y'],labels=['Water deficit', 'Min storage'], formats=['.1f', '.1f'])
    pareto_front.tooltip=def_tt
    fig_pf = plt.Figure(marks = [pareto_front],title = 'Interactive Pareto front', axes=[x_ax_pf, y_ax_pf],
                        layout={'width': '500px', 'height': '500px'}, animation_duration=1000)
    
    if pareto_front.selected == []:
        pareto_front.selected = [0]
    
    pareto_front.observe(solution_selected,'selected')
    
    S,env,w,u1 = syst_sim(simtime,I,E,d,S0,Smax,env_min,solutions_optim_relea[pareto_front.selected[0]])

    x_sc_1 = LinearScale();y_sc_1 = LinearScale(min=0,max=35);x_ax_1 = Axis(label='week', scale=x_sc_1);y_ax_1 = Axis(label='ML/week', scale=y_sc_1, orientation='vertical')
    
    x_sc_2a             = LinearScale(min=0,max=simtime);y_sc_2a = LinearScale(min=0,max=200);x_ax_2a = Axis(label='week', scale=x_sc_2a,tick_values=np.arange(8)+0.5);y_ax_2a = Axis(label='ML', scale=y_sc_2a, orientation='vertical')
    max_storage_2       = plt.plot(x=np.arange(0,simtime+1),y=[Smax]*(simtime+1),colors=['red'],scales={'x': x_sc_2a, 'y': y_sc_2a})
    max_storage_label_2 = plt.label(text = ['Max storage'], x=[0],y=[Smax+15],colors=['red'])

    min_storage_3 = plt.plot(np.arange(0,simtime+1),ms,scales={'x': x_sc_2a, 'y': y_sc_2a},colors=['red'],opacities = [1],line_style = 'dashed',
                           fill = 'bottom',fill_opacities = [0.4],fill_colors = ['red'], stroke_width = 1)
    min_storage_label_3 = plt.label(text = ['Min storage'], x=[0],y=[ms[0]-10],colors=['red'])
    
    storage_4 = Lines(x=range(simtime+1),y=S,scales={'x': x_sc_2a, 'y': y_sc_2a}, fill = 'bottom',fill_opacities = [0.7]*simtime,
                      fill_colors = ['blue'])
    fig_4a = plt.Figure(marks = [min_storage_3,storage_4,max_storage_2,max_storage_label_2,min_storage_label_3], 
                        axes=[x_ax_2a, y_ax_2a],layout={'width': '480px', 'height': '250px'},animation_duration=1000)
    
    releases_4 = plt.bar(np.arange(1,simtime+1),u1,colors=['green'],opacities = [0.7]*simtime,scales={'x': x_sc_1, 'y': y_sc_1},
                                labels = ['release'], display_legend = True, stroke_width = 1)
    fig_4b = plt.Figure(marks = [demand_plot, releases_4], axes=[x_ax_1, y_ax_1],layout={'width': '480px', 'height': '250px'},
                        animation_duration=1000,legend_location = 'top-left',legend_style = {'fill': 'white', 'opacity': 0.5})
                                                                                                                  
    storage_4.y  = update_operation_4(pareto_front.selected[0])[0]
    releases_4.y = update_operation_4(pareto_front.selected[0])[3]
                         
    storage_4.observe(solution_selected, ['x', 'y'])
    releases_4.observe(solution_selected, ['x', 'y'])
    
    return fig_4a,fig_4b,fig_pf
def Interactive_release_single(simtime,I,E,d,S0,Smax,env_min, demand_plot):
    def syst_sim(simtime,I,E,d,S0,Smax,env_min,Qreg):
    
        # Declare output variables
    
        S = [0]*(simtime+1) # reservoir storage in ML
    
        spill = [0]*(simtime) # spillage in ML
    
        env = [env_min]*(simtime) # environmental compensation flow
        
        S[0] = S0 # initial storage
    
        for t in range(simtime): # Loop for each time-step (week)
    
            # If at week t the inflow (I) is lower than the minimum environmental compensation (env_min), 
            # then the environmental compensation (env) = inflow (I)  
            if env_min >= I[t] :
                env[t] = I[t]
            # If the minimum environmental compensation is higher than the water resource available (S + I - E)
            # then the environmental compensation is equal to the higher value between 0 and the resource available
            if env_min >= S[t] + I[t] - E[t]:
                env[t] = max(0,S[t] + I[t] - E[t]) # S[t] = Smin then env[t] = I[t] and S[t+1] < Smin
            # If the demand is higher than the water resource available (S + I - E - env)
            # then the release for water supply is equal to the higher value between 0 and the resource available            
            if d[t] >= S[t] + I[t] - E[t] - env[t]:
                Qreg[t] = min(Qreg[t],max(0,S[t] + I[t] - E[t] - env[t]))
            # The spillage is equal to the higher value between 0 and the resource available exceeding the reservoir capacity
            spill[t] = max(0,S[t] + I[t] - Qreg[t] - env[t] - E[t] - Smax)
            # The final storage (initial storage in the next step) is equal to the storage + inflow - outflows
            S[t+1] = S[t] + I[t] - Qreg[t] - env[t]- E[t] - spill[t]
            
        return S,env,spill,Qreg
    
    # Interactive operating rule definition
    def update_operation_2(Qreg):
        S,env,spill,Qreg1 = syst_sim(simtime,I,E,d,S0,Smax,env_min,Qreg)
        sdpen = (np.sum((np.maximum(d-Qreg1,[0]*simtime))**2)).astype('int')
        fig_2b.title = 'Supply vs Demand - Total squared deficit = '+str(sdpen)+' ML^2'
        return S,Qreg1
    
    def policy_changed_2a(change):
        y_vals_2a = update_operation_2([release1.value,release2.value,release3.value,release4.value,
                                        release5.value,release6.value,release7.value,release8.value])[0]
        storage_2.y = y_vals_2a
        
    def policy_changed_2b(change):
        y_vals_2b = update_operation_2([release1.value,release2.value,release3.value,release4.value,
                                        release5.value,release6.value,release7.value,release8.value])[1]
        releases_2.y = y_vals_2b
        
    release1 = widgets.FloatSlider(min = 0, max = 40, step=1, value = 0, description = 'Week 1',orientation='vertical',layout={'width': '100px'})
    release1.observe(policy_changed_2a,'value')
    release1.observe(policy_changed_2b,'value')
    release2 = widgets.FloatSlider(min = 0, max = 40, step=1, value = 0, description = 'Week 2',orientation='vertical',layout={'width': '100px'})
    release2.observe(policy_changed_2a,'value')
    release2.observe(policy_changed_2b,'value')
    release3 = widgets.FloatSlider(min = 0, max = 40, step=1, value = 0, description = 'Week 3',orientation='vertical',layout={'width': '100px'})
    release3.observe(policy_changed_2a,'value')
    release3.observe(policy_changed_2b,'value')
    release4 = widgets.FloatSlider(min = 0, max = 40, step=1, value = 0, description = 'Week 4',orientation='vertical',layout={'width': '100px'})
    release4.observe(policy_changed_2a,'value')
    release4.observe(policy_changed_2b,'value')
    release5 = widgets.FloatSlider(min = 0, max = 40, step=1, value = 0, description = 'Week 5',orientation='vertical',layout={'width': '100px'})
    release5.observe(policy_changed_2a,'value')
    release5.observe(policy_changed_2b,'value')
    release6 = widgets.FloatSlider(min = 0, max = 40, step=1, value = 0, description = 'Week 6',orientation='vertical',layout={'width': '100px'})
    release6.observe(policy_changed_2a,'value')
    release6.observe(policy_changed_2b,'value')
    release7 = widgets.FloatSlider(min = 0, max = 40, step=1, value = 0, description = 'Week 7',orientation='vertical',layout={'width': '100px'})
    release7.observe(policy_changed_2a,'value')
    release7.observe(policy_changed_2b,'value')
    release8 = widgets.FloatSlider(min = 0, max = 40, step=1, value = 0, description = 'Week 8',orientation='vertical',layout={'width': '100px'})
    release8.observe(policy_changed_2a,'value')
    release8.observe(policy_changed_2b,'value')
    
    u=[release1.value,release2.value,release3.value,release4.value,release5.value,release6.value,release7.value,release8.value]
    
    S,env,w,u1 = syst_sim(simtime,I,E,d,S0,Smax,env_min,np.array([0]*simtime))
    sdpen = np.sum((np.maximum(d-u1,[0]*simtime))**2).astype('int')

    x_sc_1 = LinearScale();y_sc_1 = LinearScale(min=0,max=35);x_ax_1 = Axis(label='week', scale=x_sc_1);y_ax_1 = Axis(label='ML/week', scale=y_sc_1, orientation='vertical')
    
    x_sc_2a             = LinearScale(min=0,max=simtime);y_sc_2a = LinearScale(min=0,max=200);x_ax_2a = Axis(label='week', scale=x_sc_2a,tick_values=np.arange(8)+0.5);y_ax_2a = Axis(label='ML', scale=y_sc_2a, orientation='vertical')
    storage_2           = Lines(x=np.arange(0,simtime+1),y=S,colors=['blue'],scales={'x': x_sc_2a, 'y': y_sc_2a},fill = 'bottom',fill_opacities = [0.8],fill_colors = ['blue'])
    max_storage_2       = plt.plot(x=np.arange(0,simtime+1),y=[Smax]*(simtime+1),colors=['red'],scales={'x': x_sc_2a, 'y': y_sc_2a})
    max_storage_label_2 = plt.label(text = ['Max storage'], x=[0],y=[Smax+15],colors=['red'])
    fig_2a              = plt.Figure(marks = [storage_2,max_storage_2,max_storage_label_2],title = 'Reservoir storage volume',
                                     axes=[x_ax_2a, y_ax_2a],layout={'width': '950px', 'height': '300px'}, 
                                       animation_duration=1000,scales={'x': x_sc_2a, 'y': y_sc_2a})
    
    releases_2 = plt.bar(np.arange(1,simtime+1),u1,colors=['green'],opacities = [0.7]*simtime,
                        labels = ['release'], display_legend = True, stroke_width = 1,scales={'x': x_sc_1, 'y': y_sc_1})
    fig_2b   = plt.Figure(marks = [demand_plot,releases_2],axes=[x_ax_1, y_ax_1],
                        layout={'min_width': '950px', 'max_height': '300px'}, 
                        animation_duration=0,legend_location = 'top-left',legend_style = {'fill': 'white', 'opacity': 0.5})
    
    storage_2.y  = update_operation_2(u)[0]
    releases_2.y = update_operation_2(u)[1]
    
    storage_2.observe(policy_changed_2a, ['x', 'y'])
    releases_2.observe(policy_changed_2b, ['x', 'y'])
    
    return fig_2a,fig_2b,release1,release2,release3,release4,release5,release6,release7,release8
def Interactive_policy_auto(N, 
                            I_hist, e_hist, 
                            s_0, s_min, s_max, 
                            u_0, u_1, u_mean, u_max,
                            env_min, d_hist, 
                            rc, 
                            results1_optim,results2_optim,sol_optim):
    
    # Function to update the release policy when clicking on the points of the Pareto front
    def update_operating_policy_2(i):
        
        u_ref,s_ref_1,s_ref_2 = sol_optim[i]
        x0 = [0,       u_0]
        x1 = [s_ref_1, u_ref]
        x2 = [s_ref_2, u_ref]
        x3 = [1,       u_1]
        param = [x0, x1, x2, x3, u_mean]
        u_frac = four_points_policy(param)/u_mean
        
        Qreg = {'releases' : {'file_name' : 'Reservoir_operating_policy.Operating_policy_functions',
                             'function' : 'four_points_policy',
                             'param': param},
                'inflows' : [],
                'rel_inf' : []}
        
        Qenv, Qspill, u, I_reg, s, E = Res_sys_sim(I_hist, e_hist, s_0, s_min, s_max, env_min, d_hist, Qreg)
        
        MSV = (np.sum((np.maximum(rc-s,[0]*(N+1))))).astype('int')
        fig_2c.title = 'Reservoir storage volume - MSV = '+str(MSV)+' ML'
        
        TSD = (np.sum((np.maximum(d_hist-u,[0]*N))**2)).astype('int')
        fig_2b.title = 'Supply vs Demand - Total squared deficit = '+str(TSD)+' ML^2'
        
        return u_frac, Qenv, Qspill, u, I_reg, s
    
    # Function to update the figures when clicking on the points of the Pareto front
    def update_figure_2(change):
        
        policy_function.y = update_operating_policy_2(pareto_front.selected[0])[0]
        releases.y = update_operating_policy_2(pareto_front.selected[0])[3]
        storage.y = update_operating_policy_2(pareto_front.selected[0])[5]
    
    # Fig_pf: Pareto front  
    x_sc_pf = LinearScale();y_sc_pf = LinearScale()
    x_ax_pf = Axis(label='Total squared deficit [ML^2]', scale=x_sc_pf)
    y_ax_pf = Axis(label='Minimum storage violation [ML]', scale=y_sc_pf, orientation='vertical')
    
    pareto_front = plt.scatter(results1_optim[:],results2_optim[:],
                               scales={'x': x_sc_pf, 'y': y_sc_pf},
                               colors=['deepskyblue'], 
                               interactions={'hover':'tooltip','click': 'select'})
    
    pareto_front.unselected_style={'opacity': 0.4}
    pareto_front.selected_style={'fill': 'red', 'stroke': 'yellow', 'width': '1125px', 'height': '125px'}
    def_tt = Tooltip(fields=['index','x', 'y'],
                     labels=['index','Water deficit', 'Min storage'], 
                     formats=['.d','.1f', '.1f'])
    pareto_front.tooltip=def_tt
    
    fig_pf = plt.Figure(marks = [pareto_front],title = 'Interactive Pareto front', 
                        axes=[x_ax_pf, y_ax_pf],
                        layout={'width': '400px', 'height': '400px'}, animation_duration=1000)
    
    if pareto_front.selected == []:
        pareto_front.selected = [0]
    
    pareto_front.observe(update_figure_2,'selected')
    
    # Initial simulation applting the point of the Pareto Fron selected by default 
    u_ref,s_ref_1,s_ref_2 = sol_optim[pareto_front.selected[0]]
    x0 = [0,       u_0]
    x1 = [s_ref_1, u_ref]
    x2 = [s_ref_2, u_ref]
    x3 = [1,       u_1]
    param = [x0, x1, x2, x3, u_mean]
    u_frac = four_points_policy(param)/u_mean
    
    Qreg = {'releases' : {'file_name' : 'Reservoir_operating_policy.Operating_policy_functions',
                         'function' : 'four_points_policy',
                         'param': param},
            'inflows' : [],
            'rel_inf' : []}
    
    Qenv, Qspill, u, I_reg, s, E = Res_sys_sim(I_hist, e_hist, s_0, s_min, s_max, env_min, d_hist, Qreg)
    
    # Fig 2a: Policy function
    s_frac = np.arange(0,1.01,0.01)
    
    x_sc_2a = LinearScale(min=0,max=1); y_sc_2a = LinearScale(min=0,max=u_max/u_mean);
    x_ax_2a = Axis(label='Storage fraction', scale=x_sc_2a); 
    y_ax_2a = Axis(label='Release fraction', scale=y_sc_2a, orientation='vertical')
    
    policy_function           = Lines(x   = s_frac,
                              y      = u_frac ,
                              colors = ['blue'],
                              scales = {'x': x_sc_2a, 'y': y_sc_2a})
    
    fig_2a             = plt.Figure(marks = [policy_function],
                                   title = 'Policy function',
                                   axes=[x_ax_2a, y_ax_2a],
                                   layout={'width': '400px', 'height': '375px'}, 
                                   animation_duration=1000,
                                   scales={'x': x_sc_2a, 'y': y_sc_2a})
    
    policy_function.observe(update_figure_2, ['x', 'y'])
    
    # Fig 2b: Releases vs Demand
    x_sc_2b = LinearScale(min=0,max=N);         y_sc_2b = LinearScale(min=0,max=u_max);
    x_ax_2b = Axis(label='week', scale=x_sc_2b); y_ax_2b = Axis(label='ML/week', scale=y_sc_2b, orientation='vertical')
    
    demand             = Bars(x   = np.arange(1,N+1),
                              y      = d_hist,
                              colors = ['gray'],
                              scales = {'x': x_sc_2b, 'y': y_sc_2b})
    
    releases           = Bars(x   = np.arange(1,N+1),
                              y      = u,
                              colors = ['green'],
                              scales = {'x': x_sc_2b, 'y': y_sc_2b})
    
    TSD = (np.sum((np.maximum(d_hist-u,[0]*N))**2)).astype('int')
    
    fig_2b             = plt.Figure(marks = [demand, releases],
                                   title = 'Supply vs Demand - TSD = '+str(TSD)+' ML^2',
                                   axes=[x_ax_2b, y_ax_2b],
                                   layout={'width': '950px', 'height': '250px'}, 
                                   animation_duration=1000,
                                   scales={'x': x_sc_2b, 'y': y_sc_2b})
    
    releases.observe(update_figure_2, ['x', 'y'])
    
    # Fig 2c: Storage
    x_sc_2c = LinearScale();                    y_sc_2c = LinearScale(min=0,max=200);
    x_ax_2c = Axis(label='week', scale=x_sc_2c); y_ax_2c = Axis(label='ML', scale=y_sc_2c, orientation='vertical')
    
    storage           = Lines(x      = np.arange(0,N+1),
                              y      = s ,
                              colors = ['blue'],
                              scales = {'x': x_sc_2c, 'y': y_sc_2c},
                              fill   = 'bottom',fill_opacities = [0.8],fill_colors = ['blue'])
    
    max_storage       = plt.plot(x=np.arange(0,N+1),
                                 y=[s_max]*(N+1),
                                 colors=['red'],
                                 scales={'x': x_sc_2c, 'y': y_sc_2c})
    
    max_storage_label = plt.label(text = ['Max storage'], 
                                  x=[0],
                                  y=[s_max+15],
                                  colors=['red'])
    
    min_storage = plt.plot(np.arange(0,N+1),rc,
                             scales={'x': x_sc_2c, 'y': y_sc_2c},
                             colors=['red'],opacities = [1],
                             line_style = 'dashed',
                             fill = 'bottom',fill_opacities = [0.4],fill_colors = ['red'], stroke_width = 1)
    min_storage_label = plt.label(text = ['Min storage'], 
                                    x=[0],
                                    y=[rc[0]-10],
                                    colors=['red'])
    
    MSV = (np.sum((np.maximum(rc-s,[0]*(N+1))))).astype('int')
    
    fig_2c             = plt.Figure(marks = [storage,max_storage,max_storage_label,
                                            min_storage,min_storage_label],
                                   title = 'Reservoir storage volume - MSV = '+str(MSV)+' ML',
                                   axes=[x_ax_2c, y_ax_2c],
                                   layout={'width': '950px', 'height': '250px'}, 
                                   animation_duration=1000,
                                   scales={'x': x_sc_2c, 'y': y_sc_2c})
    
    storage.observe(update_figure_2, ['x', 'y'])
    
    return fig_pf, fig_2a,fig_2b,fig_2c
def Interactive_policy_manual(N, 
                              I_hist, e_hist, 
                              s_0, s_min, s_max, 
                              u_0, u_1, u_mean, u_max,
                              env_min, d_hist, 
                              rc):
    
    #Function to update the release policy when changing the parameters with the sliders
    def update_operating_policy_1(s_ref_1,s_ref_2,u_ref):
        if s_ref_1 > s_ref_2:
            s_ref_1 = s_ref_2   
        x0 = [0,       u_0]
        x1 = [s_ref_1, u_ref]
        x2 = [s_ref_2, u_ref]
        x3 = [1,       u_1]
        param = [x0, x1, x2, x3, u_mean]
        u_frac = four_points_policy(param)/u_mean
        
        Qreg = {'releases' : {'file_name' : 'Reservoir_operating_policy.Operating_policy_functions',
                             'function' : 'four_points_policy',
                             'param': param},
                'inflows' : [],
                'rel_inf' : []}
        
        Qenv, Qspill, u, I_reg, s, E = Res_sys_sim(I_hist, e_hist, s_0, s_min, s_max, env_min, d_hist, Qreg)
        
        TSD = (np.sum((np.maximum(d_hist-u,[0]*N))**2)).astype('int')
        fig_1b.title = 'Supply vs Demand - TSD = '+str(TSD)+' ML^2'
        
        MSV = (np.sum((np.maximum(rc-s,[0]*(N+1))))).astype('int')
        fig_1c.title = 'Reservoir storage volume - MSV = '+str(MSV)+' ML'
    
        return u_frac, Qenv, Qspill, u, I_reg, s
    
    # Function to update the figures when changing the parameters with the sliders
    def update_figure_1(change):
        policy_function.y = update_operating_policy_1(s_ref_1.value,s_ref_2.value,u_ref.value)[0]
        releases.y = update_operating_policy_1(s_ref_1.value,s_ref_2.value,u_ref.value)[3]
        storage.y = update_operating_policy_1(s_ref_1.value,s_ref_2.value,u_ref.value)[5]
    
    # Definition of the sliders    
    u_ref = widgets.FloatSlider(min=0.5, max=u_1, value=1, step=0.05,
                                description = 'u_ref: ',
                                continuous_update = False)
    u_ref.observe(update_figure_1,names = 'value')
    
    s_ref_1 = widgets.FloatSlider(min=0, max=1, value=0.25, step=0.05, 
                                  description = 's_ref_1: ',
                                  continuous_update=False)
    s_ref_1.observe(update_figure_1,names = 'value')
    
    s_ref_2 = widgets.FloatSlider(min=0, max=1, value=0.75, step=0.05,
                                  description = 's_ref_2: ',
                                  continuous_update=False)
    s_ref_2.observe(update_figure_1,names = 'value')
    
    # Initial simulation applying the default slider values of the parameters 
    x0 = [0,       u_0]
    x1 = [s_ref_1.value, u_ref.value]
    x2 = [s_ref_2.value, u_ref.value]
    x3 = [1,       u_1]
    param = [x0, x1, x2, x3, u_mean]
    u_frac = four_points_policy(param)/u_mean

    Qreg = {'releases' : {'file_name' : 'Reservoir_operating_policy.Operating_policy_functions',
                         'function' : 'four_points_policy',
                         'param': param},
            'inflows' : [],
            'rel_inf' : []}
    
    Qenv, Qspill, u, I_reg, s, E = Res_sys_sim(I_hist, e_hist, s_0, s_min, s_max, env_min, d_hist, Qreg)
    
    ### Figures ###
    # Fig 1a: Policy function
    s_frac = np.arange(0,1.01,0.01)
    
    x_sc_1a = LinearScale(min=0,max=1); y_sc_1a = LinearScale(min=0,max=u_1);
    x_ax_1a = Axis(label='Storage fraction', scale=x_sc_1a); 
    y_ax_1a = Axis(label='Release fraction', scale=y_sc_1a, orientation='vertical')
    
    policy_function           = Lines(x   = s_frac,
                              y      = u_frac,
                              colors = ['blue'],
                              scales = {'x': x_sc_1a, 'y': y_sc_1a})
    
    fig_1a             = plt.Figure(marks = [policy_function],
                                   title = 'Policy function',
                                   axes=[x_ax_1a, y_ax_1a],
                                   layout={'width': '400px', 'height': '375px'}, 
                                   animation_duration=1000,
                                   scales={'x': x_sc_1a, 'y': y_sc_1a})
    
    policy_function.observe(update_figure_1, ['x', 'y'])
    
    # Fig 1b: Releases vs Demand
    x_sc_1b = LinearScale(min=0,max=N);         y_sc_1b = LinearScale(min=0,max=u_max);
    x_ax_1b = Axis(label='week', scale=x_sc_1b); y_ax_1b = Axis(label='ML/week', scale=y_sc_1b, orientation='vertical')
    
    demand             = Bars(x   = np.arange(1,N+1),
                              y      = d_hist,
                              colors = ['gray'],
                              scales = {'x': x_sc_1b, 'y': y_sc_1b})
    
    releases           = Bars(x   = np.arange(1,N+1),
                              y      = u,
                              colors = ['green'],
                              scales = {'x': x_sc_1b, 'y': y_sc_1b})
    
    TSD = (np.sum((np.maximum(d_hist-u,[0]*N))**2)).astype('int')
    
    fig_1b             = plt.Figure(marks = [demand, releases],
                                   title = 'Supply vs Demand - TSD = '+str(TSD)+' ML^2',
                                   axes=[x_ax_1b, y_ax_1b],
                                   layout={'width': '950px', 'height': '250px'}, 
                                   animation_duration=1000,
                                   scales={'x': x_sc_1b, 'y': y_sc_1b})
    
    releases.observe(update_figure_1, ['x', 'y'])
    
    # Fig 1c: Storage
    x_sc_1c = LinearScale();                    y_sc_1c = LinearScale(min=0,max=200);
    x_ax_1c = Axis(label='week', scale=x_sc_1c); y_ax_1c = Axis(label='ML', scale=y_sc_1c, orientation='vertical')
    
    storage           = Lines(x      = np.arange(0,N+1),
                              y      = s ,
                              colors = ['blue'],
                              scales = {'x': x_sc_1c, 'y': y_sc_1c},
                              fill   = 'bottom',fill_opacities = [0.8],fill_colors = ['blue'])
    
    max_storage       = plt.plot(x=np.arange(0,N+1),
                                 y=[s_max]*(N+1),
                                 colors=['red'],
                                 scales={'x': x_sc_1c, 'y': y_sc_1c})
    
    max_storage_label = plt.label(text = ['Max storage'], 
                                  x=[0],
                                  y=[s_max+15],
                                  colors=['red'])
    
    min_storage = plt.plot(np.arange(0,N+1),rc,
                             scales={'x': x_sc_1c, 'y': y_sc_1c},
                             colors=['red'],opacities = [1],
                             line_style = 'dashed',
                             fill = 'bottom',fill_opacities = [0.4],fill_colors = ['red'], stroke_width = 1)
    min_storage_label = plt.label(text = ['Min storage'], 
                                    x=[0],
                                    y=[rc[0]-10],
                                    colors=['red'])
    
    MSV = (np.sum((np.maximum(rc-s,[0]*(N+1))))).astype('int')
    
    fig_1c             = plt.Figure(marks = [storage,max_storage,max_storage_label,
                                            min_storage,min_storage_label],
                                   title = 'Reservoir storage volume - MSV = '+str(MSV)+' ML',
                                   axes=[x_ax_1c, y_ax_1c],
                                   layout={'width': '950px', 'height': '250px'}, 
                                   animation_duration=1000,
                                   scales={'x': x_sc_1c, 'y': y_sc_1c})
    
    storage.observe(update_figure_1, ['x', 'y'])
    
    return fig_1a,fig_1b,fig_1c, u_ref,s_ref_1,s_ref_2
Ejemplo n.º 9
0
def slab():
    """
    Displays a widget illustrating line formation in a homogenous slab.

    Runs only in Jupyter notebook or JupyterLab. Requires bqplot.
    """
    # Don't display some ipywidget warnings
    warnings.simplefilter(action='ignore', category=FutureWarning)

    def _compute_slab(i0, source, tau_cont, tau_line):
        """
        Calculates slab line profile.
        """
        NPT = 101
        MAX_DX = 5.
        x = np.arange(NPT) - (NPT - 1.) / 2
        x *= MAX_DX / x.max()
        tau = tau_cont + tau_line * np.exp(-x * x)
        extinc = np.exp(-tau)
        intensity = float(i0) * extinc + float(source) * (1. - extinc)
        return (x, intensity)

    I0 = 15
    S = 65
    x, y = _compute_slab(I0, S, 0.5, 0.9)
    base = np.zeros_like(x)
    fig = plt.figure(title='Slab line formation')
    int_plot = plt.plot(x, y, 'b-')
    source_line = plt.plot(x, base + S, 'k--')
    i0_line = plt.plot(x, base + I0, 'k:')
    labels = plt.label(['I₀', 'I', 'S'],
                       x=np.array([int_plot.x[0] + 0.2, int_plot.x[-1] - 0.2,
                                   int_plot.x[0] + 0.2]),
                       y=np.array([i0_line.y[0], int_plot.y[0],
                                   source_line.y[0]]) + 2,
                       colors=['black'])
    plt.ylim(0, 100)
    i0_slider = IntSlider(min=0, max=100, value=I0, description=r'$I_0$')
    s_slider = IntSlider(min=0, max=100, value=S, description=r'$S$')
    tau_c_slider = FloatSlider(min=0, max=1., step=0.01, value=0.5,
                               description=r'$\tau_{\mathrm{cont}}$')
    tau_l_slider = FloatSlider(min=0, max=10., step=0.01, value=0.9,
                               description=r'$\tau_{\mathrm{line}}$')

    def plot_update(i0=I0, source=S, tau_cont=0.5, tau_line=0.9):
        _, y = _compute_slab(i0, source, tau_cont, tau_line)
        int_plot.y = y
        source_line.y = base + source
        i0_line.y = base + i0
        labels.y = np.array([i0, y[0], source]) + 2

    widg = interactive(plot_update, i0=i0_slider, source=s_slider,
                       tau_cont=tau_c_slider, tau_line=tau_l_slider)
    help_w = HTMLMath("<p><b>Purpose: </b>"
      "This widget-based procedure is used for "
      "studying spectral line formation in a "
      "homogeneous slab.</p>"
      "<p><b>Inputs:</b></p>"
      "<ul>"
      r"   <li>$I_0$: The incident intensity.</li>"
      r"   <li>$S$: The source function.</li>"
      r"   <li>$\tau_{\mathrm{cont}}$ : The continuum optical depth.</li>"
      r"   <li>$\tau_{\mathrm{line}}$ : The integrated optical depth in the spectral line.</li>"
      "</ul>")
    return HBox([VBox([widg, help_w],
                      layout=Layout(width='33%', top='50px', left='5px')),
                 Box([fig], layout=Layout(width='66%'))],
                layout=Layout(border='50px'))