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'])
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
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
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
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'))