@@ -729,16 +729,24 @@ def graph_total_dispatch(tools):
729729
730730 tools .bar_label ()
731731
732+
732733@graph (
733734 "energy_balance" ,
734735 title = "Energy Balance For Every Month" ,
735736 supports_multi_scenario = True ,
736- is_long = True
737+ is_long = True ,
737738)
738739def energy_balance (tools ):
739740 # Get dispatch dataframe
740- cols = ["timestamp" , "gen_tech" , "gen_energy_source" , "DispatchGen_MW" , "scenario_name" , "scenario_index" ,
741- "Curtailment_MW" ]
741+ cols = [
742+ "timestamp" ,
743+ "gen_tech" ,
744+ "gen_energy_source" ,
745+ "DispatchGen_MW" ,
746+ "scenario_name" ,
747+ "scenario_index" ,
748+ "Curtailment_MW" ,
749+ ]
742750 df = tools .get_dataframe ("dispatch.csv" , drop_scenario_info = False )[cols ]
743751 df = tools .transform .gen_type (df )
744752
@@ -749,11 +757,16 @@ def energy_balance(tools):
749757 # Sum dispatch across all the projects of the same type and timepoint
750758 key_columns = ["timestamp" , "gen_type" , "scenario_name" , "scenario_index" ]
751759 df = df .groupby (key_columns , as_index = False ).sum ()
752- df = df .melt (id_vars = key_columns , value_vars = ["Dispatch" , "Dispatch Limit" ], var_name = "Type" )
760+ df = df .melt (
761+ id_vars = key_columns , value_vars = ["Dispatch" , "Dispatch Limit" ], var_name = "Type"
762+ )
753763 df = df .rename ({"gen_type" : "Source" }, axis = 1 )
754764
755- discharge = df [(df ["Source" ] == "Storage" ) & (df ["Type" ] == "Dispatch" )].drop (["Source" , "Type" ], axis = 1 ).rename (
756- {"value" : "discharge" }, axis = 1 )
765+ discharge = (
766+ df [(df ["Source" ] == "Storage" ) & (df ["Type" ] == "Dispatch" )]
767+ .drop (["Source" , "Type" ], axis = 1 )
768+ .rename ({"value" : "discharge" }, axis = 1 )
769+ )
757770
758771 # Get load dataframe
759772 load = tools .get_dataframe ("load_balance.csv" , drop_scenario_info = False )
@@ -764,23 +777,21 @@ def energy_balance(tools):
764777 load = load .groupby (key_columns , as_index = False ).sum ()
765778
766779 # Subtract storage dispatch from generation and add it to the storage charge to get net flow
767- load = load .merge (
768- discharge ,
769- how = "left" ,
770- on = key_columns ,
771- validate = "one_to_one"
772- )
780+ load = load .merge (discharge , how = "left" , on = key_columns , validate = "one_to_one" )
773781 load ["ZoneTotalCentralDispatch" ] -= load ["discharge" ]
774782 load ["StorageNetCharge" ] += load ["discharge" ]
775783 load = load .drop ("discharge" , axis = 1 )
776784
777785 # Rename and convert from wide to long format
778- load = load .rename ({
779- "ZoneTotalCentralDispatch" : "Total Generation (excl. storage discharge)" ,
780- "TXPowerNet" : "Transmission Losses" ,
781- "StorageNetCharge" : "Storage Net Flow" ,
782- "zone_demand_mw" : "Demand" ,
783- }, axis = 1 ).sort_index (axis = 1 )
786+ load = load .rename (
787+ {
788+ "ZoneTotalCentralDispatch" : "Total Generation (excl. storage discharge)" ,
789+ "TXPowerNet" : "Transmission Losses" ,
790+ "StorageNetCharge" : "Storage Net Flow" ,
791+ "zone_demand_mw" : "Demand" ,
792+ },
793+ axis = 1 ,
794+ ).sort_index (axis = 1 )
784795 load = load .melt (id_vars = key_columns , var_name = "Source" )
785796 load ["Type" ] = "Dispatch"
786797
@@ -796,26 +807,34 @@ def energy_balance(tools):
796807 FREQUENCY = "1W"
797808
798809 def groupby_time (df ):
799- return df .groupby ([
800- "scenario_name" ,
801- "period" ,
802- "Source" ,
803- "Type" ,
804- tools .pd .Grouper (key = "datetime" , freq = FREQUENCY , origin = "start" )
805- ])["value" ]
810+ return df .groupby (
811+ [
812+ "scenario_name" ,
813+ "period" ,
814+ "Source" ,
815+ "Type" ,
816+ tools .pd .Grouper (key = "datetime" , freq = FREQUENCY , origin = "start" ),
817+ ]
818+ )["value" ]
806819
807820 df = groupby_time (df ).sum ().reset_index ()
808821
809822 # Get the state of charge data
810- soc = tools .get_dataframe ("StateOfCharge.csv" , dtype = {"STORAGE_GEN_TPS_1" : str }, drop_scenario_info = False )
811- soc = soc .rename ({"STORAGE_GEN_TPS_2" : "timepoint" , "StateOfCharge" : "value" }, axis = 1 )
823+ soc = tools .get_dataframe (
824+ "StateOfCharge.csv" , dtype = {"STORAGE_GEN_TPS_1" : str }, drop_scenario_info = False
825+ )
826+ soc = soc .rename (
827+ {"STORAGE_GEN_TPS_2" : "timepoint" , "StateOfCharge" : "value" }, axis = 1
828+ )
812829 # Sum over all the projects that are in the same scenario with the same timepoint
813830 soc = soc .groupby (["timepoint" , "scenario_name" ], as_index = False ).sum ()
814831 soc ["Source" ] = "State Of Charge"
815832 soc ["value" ] /= 1e6 # Convert to TWh
816833
817834 # Group by time
818- soc = tools .transform .timestamp (soc , use_timepoint = True , key_col = "timepoint" ).astype ({"period" : str })
835+ soc = tools .transform .timestamp (
836+ soc , use_timepoint = True , key_col = "timepoint"
837+ ).astype ({"period" : str })
819838 soc ["Type" ] = "Dispatch"
820839 soc = groupby_time (soc ).mean ().reset_index ()
821840
@@ -827,35 +846,47 @@ def groupby_time(df):
827846 # Plot
828847 # Get the colors for the lines
829848 colors = tools .get_colors ()
830- colors .update ({
831- "Transmission Losses" : "brown" ,
832- "Storage Net Flow" : "cadetblue" ,
833- "Demand" : "black" ,
834- "Total Generation (excl. storage discharge)" : "black" ,
835- "State Of Charge" : "green"
836- })
849+ colors .update (
850+ {
851+ "Transmission Losses" : "brown" ,
852+ "Storage Net Flow" : "cadetblue" ,
853+ "Demand" : "black" ,
854+ "Total Generation (excl. storage discharge)" : "black" ,
855+ "State Of Charge" : "green" ,
856+ }
857+ )
837858
838859 # plot
839860 num_periods = df ["period" ].nunique ()
840861 pn = tools .pn
841- plot = pn .ggplot (df ) + \
842- pn .geom_line (pn .aes (x = "day" , y = "value" , color = "Source" , linetype = "Type" )) + \
843- pn .facet_grid ("period ~ scenario_name" ) + \
844- pn .labs (y = "Contribution to Energy Balance (TWh)" ) + \
845- pn .scales .scale_color_manual (values = colors , aesthetics = "color" , na_value = colors ["Other" ]) + \
846- pn .scales .scale_x_continuous (
847- name = "Month" ,
848- labels = ["J" , "F" , "M" , "A" , "M" , "J" , "J" , "A" , "S" , "O" , "N" , "D" ],
849- breaks = (15 , 46 , 76 , 106 , 137 , 167 , 198 , 228 , 259 , 289 , 319 , 350 ),
850- limits = (0 , 366 )) + \
851- pn .scales .scale_linetype_manual (
852- values = {"Dispatch Limit" : "dotted" , "Dispatch" : "solid" }
853- ) + \
854- pn .theme (
855- figure_size = (pn .options .figure_size [0 ] * tools .num_scenarios , pn .options .figure_size [1 ] * num_periods ))
862+ plot = (
863+ pn .ggplot (df )
864+ + pn .geom_line (pn .aes (x = "day" , y = "value" , color = "Source" , linetype = "Type" ))
865+ + pn .facet_grid ("period ~ scenario_name" )
866+ + pn .labs (y = "Contribution to Energy Balance (TWh)" )
867+ + pn .scales .scale_color_manual (
868+ values = colors , aesthetics = "color" , na_value = colors ["Other" ]
869+ )
870+ + pn .scales .scale_x_continuous (
871+ name = "Month" ,
872+ labels = ["J" , "F" , "M" , "A" , "M" , "J" , "J" , "A" , "S" , "O" , "N" , "D" ],
873+ breaks = (15 , 46 , 76 , 106 , 137 , 167 , 198 , 228 , 259 , 289 , 319 , 350 ),
874+ limits = (0 , 366 ),
875+ )
876+ + pn .scales .scale_linetype_manual (
877+ values = {"Dispatch Limit" : "dotted" , "Dispatch" : "solid" }
878+ )
879+ + pn .theme (
880+ figure_size = (
881+ pn .options .figure_size [0 ] * tools .num_scenarios ,
882+ pn .options .figure_size [1 ] * num_periods ,
883+ )
884+ )
885+ )
856886
857887 tools .save_figure (plot .draw ())
858888
889+
859890@graph (
860891 "curtailment_per_period" ,
861892 title = "Percent of total dispatchable capacity curtailed" ,
0 commit comments