Beispiel #1
0
def post_solve(instance, outdir):
    """
    Export results.

    load_balance.csv is a wide table of energy balance components for every
    zone and timepoint. Each component registered with
    Zone_Power_Injections and Zone_Power_Withdrawals will
    become a column.

    """
    write_table(instance,
                instance.LOAD_ZONES,
                instance.TIMEPOINTS,
                output_file=os.path.join(outdir, "load_balance.csv"),
                headings=(
                    "load_zone",
                    "timestamp",
                ) + tuple(instance.Zone_Power_Injections +
                          instance.Zone_Power_Withdrawals),
                values=lambda m, z, t: (
                    z,
                    m.tp_timestamp[t],
                ) + tuple(
                    getattr(m, component)[z, t] for component in
                    (m.Zone_Power_Injections + m.Zone_Power_Withdrawals)))
Beispiel #2
0
def post_solve(instance, outdir):
    """
    Export storage build information to storage_builds.txt, and storage
    dispatch info to storage_dispatch.txt
    """
    import switch_model.reporting as reporting
    reporting.write_table(
        instance, instance.STORAGE_GEN_BLD_YRS,
        output_file=os.path.join(outdir, "storage_builds.txt"),
        headings=("generation_project", "period", "load_zone", 
                  "IncrementalPowerCapacityMW", "IncrementalEnergyCapacityMWh",
                  "OnlinePowerCapacityMW", "OnlineEnergyCapacityMWh" ),
        values=lambda m, g, bld_yr: (
            g, bld_yr, m.gen_load_zone[g],
            m.BuildGen[g, bld_yr], m.BuildStorageEnergy[g, bld_yr],
            m.GenCapacity[g, bld_yr], m.StorageEnergyCapacity[g, bld_yr]
            ))
    reporting.write_table(
        instance, instance.STORAGE_GEN_TPS,
        output_file=os.path.join(outdir, "storage_dispatch.txt"),
        headings=("generation_project", "timepoint", "load_zone", 
                  "ChargeMW", "DischargeMW", "StateOfCharge"),
        values=lambda m, g, t: (
            g, m.tp_timestamp[t], m.gen_load_zone[g],
            m.ChargeStorage[g, t], m.DispatchGen[g, t],
            m.StateOfCharge[g, t]
            ))
Beispiel #3
0
def post_solve(model, outdir):
    """
    Export annual emissions, carbon cap, and implicit carbon costs (where
    appropriate). The dual values of the carbon cap constraint represent an
    implicit carbon cost for purely linear optimization problems. For mixed
    integer optimization problems, the dual values lose practical
    interpretations, so dual values are only exported for purely linear
    models. If you include minimum build requirements, discrete unit sizes,
    discrete unit commitment, or other integer decision variables, the dual
    values will not be exported.
    """
    def get_row(model, period):
        row = [period, model.AnnualEmissions[period], 
               model.carbon_cap_tco2_per_yr[period]]
        # Only print the carbon cap dual value if it exists and if the problem
        # is purely linear.
        if not model.has_discrete_variables() and model.Enforce_Carbon_Cap[period] in model.dual:
            row.append(model.dual[model.Enforce_Carbon_Cap[period]] / 
                       model.bring_annual_costs_to_base_year[period])
        else:
            row.append('.')
        row.append(model.carbon_cost_dollar_per_tco2[period])
        row.append(model.carbon_cost_dollar_per_tco2[period] * \
                   model.AnnualEmissions[period])
        return row

    reporting.write_table(
        model, model.PERIODS,
        output_file=os.path.join(outdir, "emissions.txt"),
        headings=("PERIOD", "AnnualEmissions_tCO2_per_yr", 
                  "carbon_cap_tco2_per_yr", "carbon_cap_dual_future_dollar_per_tco2",
                  "carbon_cost_dollar_per_tco2", "carbon_cost_annual_total"),
        values=get_row)
Beispiel #4
0
def post_solve(instance, outdir):
    """
    Export storage build information to storage_builds.txt, and storage
    dispatch info to storage_dispatch.txt
    """
    import switch_model.reporting as reporting
    reporting.write_table(
        instance, instance.STORAGE_GEN_BLD_YRS,
        output_file=os.path.join(outdir, "storage_builds.txt"),
        headings=("generation_project", "period", "load_zone",
                  "IncrementalPowerCapacityMW", "IncrementalEnergyCapacityMWh",
                  "OnlinePowerCapacityMW", "OnlineEnergyCapacityMWh" ),
        values=lambda m, g, bld_yr: (
            g, bld_yr, m.gen_load_zone[g],
            m.BuildGen[g, bld_yr], m.BuildStorageEnergy[g, bld_yr],
            m.GenCapacity[g, bld_yr], m.StorageEnergyCapacity[g, bld_yr]
            ))
    reporting.write_table(
        instance, instance.STORAGE_GEN_TPS,
        output_file=os.path.join(outdir, "storage_dispatch.txt"),
        headings=("generation_project", "timepoint", "load_zone",
                  "ChargeMW", "DischargeMW", "StateOfCharge"),
        values=lambda m, g, t: (
            g, m.tp_timestamp[t], m.gen_load_zone[g],
            m.ChargeStorage[g, t], m.DispatchGen[g, t],
            m.StateOfCharge[g, t]
            ))
def post_solve(model, outdir):
    """
    Export annual emissions, carbon cap, and implicit carbon costs (where
    appropriate). The dual values of the carbon cap constraint represent an
    implicit carbon cost for purely linear optimization problems. For mixed
    integer optimization problems, the dual values lose practical
    interpretations, so dual values are only exported for purely linear
    models. If you include minimum build requirements, discrete unit sizes,
    discrete unit commitment, or other integer decision variables, the dual
    values will not be exported.
    """
    def get_row(model, period):
        row = [period, model.AnnualEmissions[period],
               model.carbon_cap_tco2_per_yr[period]]
        # Only print the carbon cap dual value if it exists and if the problem
        # is purely linear.
        if not model.has_discrete_variables() and model.Enforce_Carbon_Cap[period] in model.dual:
            row.append(model.dual[model.Enforce_Carbon_Cap[period]] /
                       model.bring_annual_costs_to_base_year[period])
        else:
            row.append('.')
        row.append(model.carbon_cost_dollar_per_tco2[period])
        row.append(model.carbon_cost_dollar_per_tco2[period] * \
                   model.AnnualEmissions[period])
        return row

    reporting.write_table(
        model, model.PERIODS,
        output_file=os.path.join(outdir, "emissions.txt"),
        headings=("PERIOD", "AnnualEmissions_tCO2_per_yr",
                  "carbon_cap_tco2_per_yr", "carbon_cap_dual_future_dollar_per_tco2",
                  "carbon_cost_dollar_per_tco2", "carbon_cost_annual_total"),
        values=get_row)
Beispiel #6
0
def post_solve(instance, outdir):
    """
    Export energy statistics relevant to RPS studies.
    
    """

    import switch_model.reporting as reporting
    def get_row(m, p):
        row = (p,)
        row += (m.RPSFuelEnergy[p] / 1000,)
        row += (m.RPSNonFuelEnergy[p] / 1000,)
        row += (total_generation_in_period(m,p) / 1000,)
        row += ((m.RPSFuelEnergy[p] + m.RPSNonFuelEnergy[p]) / 
            total_generation_in_period(m,p),)
        row += (total_demand_in_period(m, p),)
        row += ((m.RPSFuelEnergy[p] + m.RPSNonFuelEnergy[p]) / 
            total_demand_in_period(m, p),)
        return row
    reporting.write_table(
        instance, instance.RPS_PERIODS,
        output_file=os.path.join(outdir, "rps_energy.txt"),
        headings=("PERIOD", "RPSFuelEnergyGWh", "RPSNonFuelEnergyGWh",
            "TotalGenerationInPeriodGWh", "RPSGenFraction",
            "TotalSalesInPeriodGWh", "RPSSalesFraction"),
        values=get_row)   
Beispiel #7
0
def post_solve(instance, outdir):
    """
    Export energy statistics relevant to RPS studies.

    """

    import switch_model.reporting as reporting

    def get_row(m, p):
        row = (p, )
        row += (m.RPSFuelEnergy[p] / 1000, )
        row += (m.RPSNonFuelEnergy[p] / 1000, )
        row += (total_generation_in_period(m, p) / 1000, )
        row += ((m.RPSFuelEnergy[p] + m.RPSNonFuelEnergy[p]) /
                total_generation_in_period(m, p), )
        row += (total_demand_in_period(m, p), )
        row += ((m.RPSFuelEnergy[p] + m.RPSNonFuelEnergy[p]) /
                total_demand_in_period(m, p), )
        return row

    reporting.write_table(
        instance,
        instance.RPS_PERIODS,
        output_file=os.path.join(outdir, "rps_energy.txt"),
        headings=("PERIOD", "RPSFuelEnergyGWh", "RPSNonFuelEnergyGWh",
                  "TotalGenerationInPeriodGWh", "RPSGenFraction",
                  "TotalSalesInPeriodGWh", "RPSSalesFraction"),
        values=get_row)
Beispiel #8
0
def post_solve(instance, outdir):
    # write_table returns a tuple instead of expanding the indexes, so use
    # "gp" for the tuple instead of "g, p" for the components.
    write_table(
        instance, instance.GEN_PERIODS, 
        output_file=os.path.join(outdir, "gen_cap.txt"),
        headings=("GENERATION_PROJECT", "PERIOD", "GenCapacity",
                  "GenCapitalCosts", "GenFixedOMCosts"),
        values=lambda m, gp: gp + (m.GenCapacity[gp], m.GenCapitalCosts[gp],
                                m.GenFixedOMCosts[gp]))
Beispiel #9
0
def post_solve(instance, outdir):
    # write_table returns a tuple instead of expanding the indexes, so use
    # "gp" for the tuple instead of "g, p" for the components.
    write_table(
        instance,
        instance.GEN_PERIODS,
        output_file=os.path.join(outdir, "gen_cap.txt"),
        headings=("GENERATION_PROJECT", "PERIOD", "GenCapacity",
                  "GenCapitalCosts", "GenFixedOMCosts"),
        values=lambda m, gp: gp +
        (m.GenCapacity[gp], m.GenCapitalCosts[gp], m.GenFixedOMCosts[gp]))
Beispiel #10
0
def post_solve(m, outdir):
    write_table(
        m,
        sorted(m.GEN_PERIODS) if m.options.sorted_output else m.GEN_PERIODS,
        output_file=os.path.join(outdir, "gen_cap.tab"),
        headings=("GENERATION_PROJECT", "PERIOD", "gen_tech", "gen_load_zone",
                  "gen_energy_source", "GenCapacity", "GenCapitalCosts",
                  "GenFixedOMCosts"),
        # Indexes are provided as a tuple, so put (g,p) in parentheses to
        # access the two components of the index individually.
        values=lambda m, g, p:
        (g, p, m.gen_tech[g], m.gen_load_zone[g], m.gen_energy_source[g], m.
         GenCapacity[g, p], m.GenCapitalCosts[g, p], m.GenFixedOMCosts[g, p]))
Beispiel #11
0
def post_solve(instance, outdir):
    write_table(
        instance, instance.GEN_PERIODS,
        output_file=os.path.join(outdir, "gen_cap.txt"),
        headings=("GENERATION_PROJECT", "PERIOD", 
                  "gen_tech", "gen_load_zone", "gen_energy_source",
                  "GenCapacity", "GenCapitalCosts", "GenFixedOMCosts"),
        # Indexes are provided as a tuple, so put (g,p) in parentheses to
        # access the two components of the index individually.
        values=lambda m, (g, p): (
            g, p, 
            m.gen_tech[g], m.gen_load_zone[g], m.gen_energy_source[g],
            m.GenCapacity[g, p], m.GenCapitalCosts[g, p], m.GenFixedOMCosts[g, p]))
Beispiel #12
0
def post_solve(instance, outdir):
    """
    Default export of project dispatch per timepoint in tabular "wide" format.

    """
    write_table(
        instance,
        instance.TIMEPOINTS,
        output_file=os.path.join(outdir, "dispatch.txt"),
        headings=("timestamp", ) + tuple(sorted(instance.GENERATION_PROJECTS)),
        values=lambda m, t:
        (m.tp_timestamp[t], ) + tuple(m.DispatchGen[p, t]
                                      if (p, t) in m.GEN_TPS else 0.0
                                      for p in sorted(m.GENERATION_PROJECTS)))
Beispiel #13
0
def post_solve(instance, outdir):
    """
    Default export of project dispatch per timepoint in tabular "wide" format.

    """
    write_table(
        instance, instance.TIMEPOINTS,
        output_file=os.path.join(outdir, "dispatch.txt"),
        headings=("timestamp",)+tuple(sorted(instance.GENERATION_PROJECTS)),
        values=lambda m, t: (m.tp_timestamp[t],) + tuple(
            m.DispatchGen[p, t] if (p, t) in m.GEN_TPS
            else 0.0
            for p in sorted(m.GENERATION_PROJECTS)
        )
    )
Beispiel #14
0
def post_solve(instance, outdir):
    """
    This rudimentary example copies the export code from load_zones, but uses
    a different file name (load_balance2.txt).
    """
    write_table(
        instance, instance.LOAD_ZONES, instance.TIMEPOINTS,
        output_file=os.path.join(outdir, "load_balance2.txt"),
        headings=("load_zone", "timestamp",) + tuple(
            instance.Zone_Power_Injections +
            instance.Zone_Power_Withdrawals),
        values=lambda m, z, t: (z, m.tp_timestamp[t],) + tuple(
            getattr(m, component)[z, t]
            for component in (
                m.Zone_Power_Injections +
                m.Zone_Power_Withdrawals)))
Beispiel #15
0
def post_solve(instance, outdir):
    """
    Export results.
    
    load_balance.txt is a wide table of energy balance components for every
    zone and timepoint. Each component registered with
    Zone_Power_Injections and Zone_Power_Withdrawals will
    become a column.

    """
    write_table(
        instance, instance.LOAD_ZONES, instance.TIMEPOINTS,
        output_file=os.path.join(outdir, "load_balance.txt"),
        headings=("load_zone", "timestamp",) + tuple(
            instance.Zone_Power_Injections +
            instance.Zone_Power_Withdrawals),
        values=lambda m, z, t: (z, m.tp_timestamp[t],) + tuple(
            getattr(m, component)[z, t]
            for component in (
                m.Zone_Power_Injections +
                m.Zone_Power_Withdrawals)))
Beispiel #16
0
def post_solve(instance, outdir):
    """
    Exported files:
    
    dispatch-wide.txt - Dispatch results timepoints in "wide" format with
    timepoints as rows, generation projects as columns, and dispatch level
    as values
    
    dispatch.csv - Dispatch results in normalized form where each row 
    describes the dispatch of a generation project in one timepoint.
    
    dispatch_annual_summary.csv - Similar to dispatch.csv, but summarized
    by generation technology and period.
    
    dispatch_zonal_annual_summary.csv - Similar to dispatch_annual_summary.csv
    but broken out by load zone. 
    
    dispatch_annual_summary.pdf - A figure of annual summary data. Only written
    if the ggplot python library is installed.
    """
    write_table(
        instance, instance.TIMEPOINTS,
        output_file=os.path.join(outdir, "dispatch-wide.txt"),
        headings=("timestamp",)+tuple(sorted(instance.GENERATION_PROJECTS)),
        values=lambda m, t: (m.tp_timestamp[t],) + tuple(
            m.DispatchGen[p, t] if (p, t) in m.GEN_TPS
            else 0.0
            for p in sorted(m.GENERATION_PROJECTS)
        )
    )


    dispatch_normalized_dat = [{
        "generation_project": g,
        "gen_dbid": instance.gen_dbid[g],
        "gen_tech": instance.gen_tech[g],
        "gen_load_zone": instance.gen_load_zone[g],
        "gen_energy_source": instance.gen_energy_source[g],
        "timestamp": instance.tp_timestamp[t], 
        "tp_weight_in_year_hrs": instance.tp_weight_in_year[t],
        "period": instance.tp_period[t],
        "DispatchGen_MW": value(instance.DispatchGen[g, t]),
        "Energy_GWh_typical_yr": value(
            instance.DispatchGen[g, t] * instance.tp_weight_in_year[t] / 1000),
        "VariableCost_per_yr": value(
            instance.DispatchGen[g, t] * instance.gen_variable_om[g] * 
            instance.tp_weight_in_year[t]),
        "DispatchEmissions_tCO2_per_typical_yr": value(sum(
            instance.DispatchEmissions[g, t, f] * instance.tp_weight_in_year[t]
              for f in instance.FUELS_FOR_GEN[g]
        )) if instance.gen_uses_fuel[g] else 0
    } for g, t in instance.GEN_TPS ]
    dispatch_full_df = pd.DataFrame(dispatch_normalized_dat)
    dispatch_full_df.set_index(["generation_project", "timestamp"], inplace=True)
    dispatch_full_df.to_csv(os.path.join(outdir, "dispatch.csv"))
        

    annual_summary = dispatch_full_df.groupby(['gen_tech', "gen_energy_source", "period"]).sum()
    annual_summary.to_csv(
        os.path.join(outdir, "dispatch_annual_summary.csv"),
        columns=["Energy_GWh_typical_yr", "VariableCost_per_yr", 
                 "DispatchEmissions_tCO2_per_typical_yr"])


    zonal_annual_summary = dispatch_full_df.groupby(
        ['gen_tech', "gen_load_zone", "gen_energy_source", "period"]
    ).sum()
    zonal_annual_summary.to_csv(
        os.path.join(outdir, "dispatch_zonal_annual_summary.csv"),
        columns=["Energy_GWh_typical_yr", "VariableCost_per_yr", 
                 "DispatchEmissions_tCO2_per_typical_yr"]
    )
    
    if can_plot:
        annual_summary_plot = ggplot(
                annual_summary.reset_index(), 
                aes(x='period', weight="Energy_GWh_typical_yr", fill="factor(gen_tech)")
            ) + \
            geom_bar(position="stack") + \
            scale_y_continuous(name='Energy (GWh/yr)') + theme_bw()
        annual_summary_plot.save(filename=os.path.join(outdir, "dispatch_annual_summary.pdf"))
Beispiel #17
0
def post_solve(mod, outdir):
    """
    This module's post solve function calls the plot_inv_decision and
    plot_dis_decision functions to write and plot different outputs.
    
    plot_inv_decision should be used when the quantity is indexed by periods
    
    plot_dis_decision should be used when the quantity is indexed by timepoints
    
    """
    # Import optional dependencies here instead of at the top of the file to
    # avoid breaking tests for installations that don't use this functionality
    import matplotlib.pyplot as plt
    from numpy import nan
    from cycler import cycler
    from matplotlib.backends.backend_pdf import PdfPages

    summaries_dir = os.path.join(outdir, "Summaries")
    if not os.path.exists(summaries_dir):
        os.makedirs(summaries_dir)
    else:
        print "Summaries directory exists, clearing it..."
        for f in os.listdir(summaries_dir):
            os.unlink(os.path.join(summaries_dir, f))

    color_map = plt.get_cmap('gist_rainbow')
    styles = cycle(['-', '--', '-.', ':'])

    #####
    # Round doubles to the first decimal
    #for var in mod.component_objects():
    #    if not isinstance(var, Var):
    #        continue
    #    for key, obj in var.items():
    #        obj.value = round(obj.value,1)
    #    print "Finished rounding variable "+str(var)

    def plot_inv_decision(name, tab, n_data, ind, by_period):
        """
        This function plots an investment decision over all periods on a
        bar plot.
        
        Arguments are:
        
        name: Filename for the output pdf.
        
        tab: Table of data. Format should be a list of lists whose first
        row (the first list) contains column names.
        
        n_data: Number of records to plot. Used to cycle through colors and
        linestyles to differenciate different variables.
        
        ind: Name of the column to be used as index when transforming the
        table into a Pandas Dataframe. Usually represents time.
        
        by_period: A boolean indicating whether the plot should be stacked
        by period (False) or if values should be cummulative (True). In the
        former, x axis represents the investment alternatives and in the
        latter, it represents periods (hence he boolean values required).
        
        """
        if by_period:
            df = pd.DataFrame(tab[1:],
                              columns=tab[0]).set_index(ind).transpose()
            stack = False
            num_col = int(n_data) / 10
        else:
            df = pd.DataFrame(tab[1:], columns=tab[0]).set_index(ind)
            stack = True
            num_col = int(n_data) / 2
        fig = plt.figure()
        inv_ax = fig.add_subplot(111)
        inv_ax.grid(b=False)
        # You have to play with the color map and the line style list to
        # get enough combinations for your particular plot
        inv_ax.set_prop_cycle(
            cycler('color',
                   [color_map(i / n_data) for i in range(0, n_data + 1)]))
        # To locate the legend: "loc" is the point of the legend for which you
        # will specify coordinates. These coords are specified in
        # bbox_to_anchor (can be only 1 point or couple)
        inv_plot = df.plot(kind='bar', ax=inv_ax,
                           stacked=stack).legend(loc='lower left',
                                                 fontsize=8,
                                                 bbox_to_anchor=(0., 1.015, 1.,
                                                                 1.015),
                                                 ncol=num_col,
                                                 mode="expand")
        if by_period:
            plt.xticks(rotation=0, fontsize=10)
            fname = summaries_dir + '/' + name + '.pdf'
        else:
            plt.xticks(rotation=90, fontsize=9)
            fname = summaries_dir + '/' + name + '_stacked_by_p.pdf'
        plt.savefig(fname,
                    bbox_extra_artists=(inv_plot, ),
                    bbox_inches='tight')
        plt.close()

    def plot_dis_decision(name, tab, n_data, ind):
        """
        This function prints a pdf with dispatch decisions plotted over all 
        periods on a line plot and also a close up of each period on the
        subsequent pages of the file.
        
        Arguments are:
        
        name: Filename for the output pdf.
        
        tab: Table of data. Format should be a list of lists whose first
        row (the first list) contains column names.
        
        n_data: Number of records to plot. Used to cycle through colors and
        linestyles to differenciate different variables.
        
        ind: Name of the column to be used as index when transforming the
        table into a Pandas Dataframe. Usually represents time. 
        
        """

        plots = PdfPages(os.path.join(outdir, "Summaries", name) + '.pdf')

        df = pd.DataFrame(tab[1:], columns=tab[0])

        n_scen = mod.SCENARIOS.__len__()
        #num_col = int(n_data * n_scen)/8
        num_col = 6

        for p in ['all'] + [p for p in mod.PERIODS]:
            fig = plt.figure(figsize=(17, 8), dpi=100)
            dis_ax = fig.add_subplot(111)
            dis_ax.grid(b=False)
            # You have to play with the color map and the line style list to
            # get enough combinations for your particular plot.
            # Set up different x axis labels if all periods are being plotted
            if p == 'all':
                dis_ax.set_xticks(
                    [i * 24 for i in range(0,
                                           len(mod.TIMEPOINTS) / 24 + 1)])
                dis_ax.set_xticklabels([
                    mod.tp_timestamp[mod.TIMEPOINTS[i * 24 + 1]]
                    for i in range(0,
                                   len(mod.TIMEPOINTS) / 24)
                ])
                # Technologies have different linestyles and scenarios have
                # different colors
                dis_ax.set_prop_cycle(
                    cycler('color', [
                        color_map(i / float(n_data - 1)) for i in range(n_data)
                    ]) *
                    cycler('linestyle', [next(styles) for i in range(n_scen)]))
                df_to_plot = df.drop([ind], axis=1).replace('', nan)
            else:
                n_scen = mod.PERIOD_SCENARIOS[p].__len__()
                dis_ax.set_xticks(
                    [i * 6 for i in range(0,
                                          len(mod.PERIOD_TPS[p]) / 6 + 1)])
                dis_ax.set_xticklabels([
                    mod.tp_timestamp[mod.PERIOD_TPS[p][t * 6 + 1]]
                    for t in range(0,
                                   len(mod.PERIOD_TPS[p]) / 6)
                ])
                # Technologies have different colors and scenarios have
                # different line styles
                dis_ax.set_prop_cycle(
                    cycler('color', [
                        color_map(i / float(n_data - 1)) for i in range(n_data)
                    ]) *
                    cycler('linestyle', [next(styles) for i in range(n_scen)]))
                # Before plotting, data must be filtered by period
                period_tps = [
                    mod.tp_timestamp[tp] for tp in mod.PERIOD_TPS[p].value
                ]
                df_to_plot = df.loc[df[ind].isin(period_tps)].drop(
                    [ind], axis=1).reset_index(drop=True).dropna(axis=1,
                                                                 how='all')
            # To locate the legend: "loc" is the point of the legend for which
            # you will specify coordinates. These coords are specified in
            # bbox_to_anchor (can be only 1 point or couple)
            dis_plot = df_to_plot.plot(ax=dis_ax, linewidth=1.6).legend(
                loc='lower left',
                fontsize=8,
                bbox_to_anchor=(0., 1.015, 1., 1.015),
                ncol=num_col,
                mode="expand")
            plt.xticks(rotation=90, fontsize=9)
            plots.savefig(bbox_extra_artists=(dis_plot, ), bbox_inches='tight')
            plt.close()
        plots.close()

    print "Printing summaries:\n==================="
    start = time.time()

    # print "renewable energy production"
    # rpsenergy = {s:0.0 for s in mod.SCENARIOS}
    # renergy = {s:0.0 for s in mod.SCENARIOS}
    # energy = {s:0.0 for s in mod.SCENARIOS}
    # for s in mod.SCENARIOS:
    #     for tp in mod.PERIOD_TPS[mod.scenario_period[s]]:
    #         for pr in mod.ERNC_ACTIVE_IN_TP[tp]:
    #             rpsenergy[s] += mod.DispatchProj[pr,tp,s].value*mod.tp_weight[tp] / 1000000.0
    #         for pr in mod.ERNC_ACTIVE_IN_TP1[tp]:
    #             renergy[s] += mod.DispatchProj[pr,tp,s].value*mod.tp_weight[tp] / 1000000.0
    #         for pr in mod.PROJECTS_ACTIVE_IN_TIMEPOINT[tp]:
    #             energy[s] += mod.DispatchProj[pr,tp,s].value*mod.tp_weight[tp]/1000000.0
    # with open(os.path.join(summaries_dir, "rps.tab"),'w') as f:
    #     for p in mod.PERIODS:
    #         ener = sum(energy[s]*mod.scenario_probability[s] for s in mod.PERIOD_SCENARIOS[p])
    #         rpsener = sum((rpsenergy[s]/energy[s]*100.0)*mod.scenario_probability[s] for s in mod.PERIOD_SCENARIOS[p])
    #         rener = sum((renergy[s]/energy[s]*100.0)*mod.scenario_probability[s] for s in mod.PERIOD_SCENARIOS[p])
    #         f.write("Period %s expected: Total - %10.1f TWh // %3.2f ERNC // %3.2f Renewable\n" % (p,ener,rpsener,rener))
    #     for s in mod.SCENARIOS:
    #         f.write("Scen %s: Total - %10.1f TWh // %3.2f ERNC // %3.2f Renewable\n" % (s,energy[s],rpsenergy[s]/energy[s]*100, renergy[s]/energy[s]*100.0))

    if mod.options.export_all:
        mod.options.export_reservoirs = True
        mod.options.export_tech_dispatch = True
        mod.options.export_capacities = True
        mod.options.export_transmission = True

    # table_name = "energy_by_gentech_periods"
    # print table_name+" ..."
    # table = export.write_table(
    #     mod, True, mod.SCENARIOS, mod.GENERATION_TECHNOLOGIES,
    #     output_file=os.path.join(summaries_dir, table_name+".csv"),
    #     headings=("scenario", "gentech", "energy_produced_TWh"),
    #     values=lambda m, s, g: (s, g,
    #         sum(m.DispatchProj[pr,tp,s]*m.tp_weight[tp]
    #         for tp in m.PERIOD_TPS[m.scenario_period[s]]
    #             for pr in m.PROJECTS_ACTIVE_IN_TIMEPOINT[tp]
    #                 if g==m.proj_gen_tech[pr])/1000000.0))

    if mod.options.export_capacities:
        n_elements = mod.GENERATION_TECHNOLOGIES.__len__()
        index = 'gentech'

        table_name = "cummulative_capacity_by_tech_periods"
        print table_name + " ..."
        table = export.write_table(
            mod,
            mod.GENERATION_TECHNOLOGIES,
            output_file=os.path.join(summaries_dir, table_name + ".csv"),
            headings=(index, 'legacy') + tuple(p for p in mod.PERIODS),
            values=lambda m, gt:
            (gt,
             sum(m.BuildGen[g, bldyr] for (g, bldyr) in m.GEN_BLD_YRS
                 if m.gen_tech[g] == gt and bldyr not in m.PERIODS)) + tuple(
                     sum(m.GenCapacity[g, p] for g in m.GENERATION_PROJECTS
                         if m.gen_tech[g] == gt) for p in m.PERIODS))
        plot_inv_decision(table_name, table, n_elements, index, True)

        table_name = "capacity_installed_by_tech_periods"
        print table_name + " ..."
        table = export.write_table(
            mod,
            mod.GENERATION_TECHNOLOGIES,
            output_file=os.path.join(summaries_dir, table_name + ".csv"),
            headings=(index, 'legacy') + tuple(p for p in mod.PERIODS),
            values=lambda m, gt:
            (gt,
             sum(m.BuildGen[g, bldyr] for (g, bldyr) in m.GEN_BLD_YRS
                 if m.gen_tech[g] == gt and bldyr not in m.PERIODS)) + tuple(
                     sum(m.BuildGen[g, p] for g in m.GENERATION_PROJECTS
                         if m.gen_tech[g] == gt) for p in m.PERIODS))
        plot_inv_decision(table_name, table, n_elements, index, False)

    if mod.options.export_transmission:
        n_elements = mod.TRANSMISSION_LINES.__len__()
        index = 'path'

        table_name = "cummulative_transmission_by_path_periods"
        print table_name + " ..."
        table = export.write_table(
            mod,
            True,
            mod.TRANSMISSION_LINES,
            output_file=os.path.join(summaries_dir, table_name + ".csv"),
            headings=(index, 'legacy') + tuple(p for p in mod.PERIODS),
            values=lambda m, tx:
            (tx, m.existing_trans_cap[tx]) + tuple(m.TransCapacity[tx, p]
                                                   for p in m.PERIODS))
        #plot_inv_decision(table_name, table, n_elements, index, True)

        table_name = "transmission_installation_by_path_periods"
        print table_name + " ..."
        table = export.write_table(
            mod,
            True,
            mod.TRANSMISSION_LINES,
            output_file=os.path.join(summaries_dir, table_name + ".csv"),
            headings=(index, 'legacy') + tuple(p for p in mod.PERIODS),
            values=lambda m, tx:
            (tx, m.existing_trans_cap[tx]) + tuple(m.BuildTrans[tx, p]
                                                   for p in m.PERIODS))
        plot_inv_decision(table_name, table, n_elements, index, False)

    if mod.options.export_tech_dispatch:
        n_elements = mod.GENERATION_TECHNOLOGIES.__len__()
        index = 'timepoints'

        gen_projects = {}
        for g in mod.GENERATION_TECHNOLOGIES:
            gen_projects[g] = []
            for prj in mod.PROJECTS:
                if mod.proj_gen_tech[prj] == g:
                    gen_projects[g].append(prj)

        def print_dis(m, tp):
            tup = (m.tp_timestamp[tp], )
            for g in m.GENERATION_TECHNOLOGIES:
                for s in m.SCENARIOS:
                    if s in m.PERIOD_SCENARIOS[m.tp_period[tp]]:
                        tup += (sum(m.DispatchProj[proj, tp, s]
                                    for proj in gen_projects[g]
                                    if (proj, tp,
                                        s) in m.PROJ_DISPATCH_POINTS), )
                    else:
                        tup += ('', )
            return tup

        table_name = "dispatch_proj_by_tech_tps"
        print table_name + " ..."
        table = export.write_table(
            mod,
            True,
            mod.TIMEPOINTS,
            output_file=os.path.join(summaries_dir, table_name + ".csv"),
            headings=("timepoints", ) + tuple(
                str(g) + "-" + str(mod.scenario_stamp[s])
                for g in mod.GENERATION_TECHNOLOGIES for s in mod.SCENARIOS),
            values=print_dis)
        plot_dis_decision(table_name, table, n_elements, index)

    if mod.options.export_reservoirs:
        n_elements = mod.RESERVOIRS.__len__()
        index = 'timepoints'

        def print_res(m, tp):
            tup = (m.tp_timestamp[tp], )
            for r in m.RESERVOIRS:
                for s in m.SCENARIOS:
                    if s in m.PERIOD_SCENARIOS[m.tp_period[tp]]:
                        tup += (m.ReservoirVol[r, tp, s] -
                                m.initial_res_vol[r], )
                    else:
                        tup += ('', )
            return tup

        table_name = "reservoir_final_vols_tp"
        print table_name + " ..."
        table = export.write_table(
            mod,
            True,
            mod.TIMEPOINTS,
            output_file=os.path.join(summaries_dir, table_name + ".csv"),
            headings=("timepoints", ) + tuple(
                str(r) + "-" + str(mod.scenario_stamp[s])
                for r in mod.RESERVOIRS for s in mod.SCENARIOS),
            values=print_res)
        plot_dis_decision(table_name, table, n_elements, index)

        ##############################################################
        # The following is a custom export to get dispatch for certain
        # Chile load zones
        lzs_to_print = ['charrua', 'ancoa']

        lz_hprojs = {}
        for lz in lzs_to_print:
            lz_hprojs[lz] = []
            for proj in mod.LZ_PROJECTS[lz]:
                if proj in mod.HYDRO_PROJECTS:
                    lz_hprojs[lz].append(proj)

        def print_hgen(m, tp):
            tup = (m.tp_timestamp[tp], )
            for lz in lzs_to_print:
                for s in m.SCENARIOS:
                    if s in m.PERIOD_SCENARIOS[m.tp_period[tp]]:
                        tup += (sum(m.DispatchProj[proj, tp, s]
                                    for proj in lz_hprojs[lz]
                                    if (proj, tp,
                                        s) in m.HYDRO_PROJ_DISPATCH_POINTS), )
                    else:
                        tup += ('', )
            return tup

        table_name = "hydro_dispatch_special_nodes_tp"
        print table_name + " ..."
        table = export.write_table(
            mod,
            True,
            mod.TIMEPOINTS,
            output_file=os.path.join(summaries_dir, table_name + ".csv"),
            headings=("timepoints", ) + tuple(
                str(lz) + "-" + str(mod.scenario_stamp[s])
                for lz in lzs_to_print for s in mod.SCENARIOS),
            values=print_hgen)
        #plot_dis_decision(table_name, table, n_elements, index)

    if mod.options.export_load_blocks:

        def print_res(m, ym):
            tup = (ym, )
            for r in m.RESERVOIRS:
                for s in m.SCENARIOS:
                    if s in m.PERIOD_SCENARIOS[m.tp_period[next(
                            iter(m.ym_timepoints[ym]))]]:
                        tup += (m.ReservoirVol[r, ym, s] -
                                m.initial_res_vol[r], )
                    else:
                        tup += ('', )
            return tup

        table_name = "reservoir_vols_load_block"
        print table_name + " ..."
        tab = export.write_table(mod,
                                 True,
                                 mod.YEARMONTHS,
                                 output_file=os.path.join(
                                     summaries_dir, table_name + ".csv"),
                                 headings=("yearmonth", ) + tuple(
                                     str(r) + "-" + str(mod.scenario_stamp[s])
                                     for r in mod.RESERVOIRS
                                     for s in mod.SCENARIOS),
                                 values=print_res)
        n_data = mod.RESERVOIRS.__len__()
        ind = 'yearmonth'
        plots = PdfPages(
            os.path.join(outdir, "Summaries", table_name) + '.pdf')

        df = pd.DataFrame(tab[1:], columns=tab[0])

        n_scen = mod.SCENARIOS.__len__()
        #num_col = int(n_data * n_scen)/8
        num_col = 6

        for p in ['all'] + [p for p in mod.PERIODS]:
            fig = plt.figure(figsize=(17, 8), dpi=100)
            dis_ax = fig.add_subplot(111)
            dis_ax.grid(b=False)
            # You have to play with the color map and the line style list to
            # get enough combinations for your particular plot.
            # Set up different x axis labels if all periods are being plotted
            if p == 'all':
                dis_ax.set_xticks(
                    [i * 5 for i in range(0,
                                          len(mod.YEARMONTHS) / 5 + 1)])
                dis_ax.set_xticklabels([
                    mod.YEARMONTHS[i * 5 + 1]
                    for i in range(0,
                                   len(mod.YEARMONTHS) / 5)
                ])
                # Technologies have different linestyles and scenarios have
                # different colors
                dis_ax.set_prop_cycle(
                    cycler('color', [
                        color_map(i / float(n_data - 1)) for i in range(n_data)
                    ]) *
                    cycler('linestyle', [next(styles) for i in range(n_scen)]))
                df_to_plot = df.drop([ind], axis=1).replace('', nan)
            else:
                n_scen = mod.PERIOD_SCENARIOS[p].__len__()
                dis_ax.set_xticks([i * 5 for i in range(0, 24)])
                dis_ax.set_xticklabels(
                    [mod.YEARMONTHS[i] for i in range(1, 25)])
                # Technologies have different colors and scenarios have
                # different line styles
                dis_ax.set_prop_cycle(
                    cycler('color', [
                        color_map(i / float(n_data - 1)) for i in range(n_data)
                    ]) *
                    cycler('linestyle', [next(styles) for i in range(n_scen)]))
                # Before plotting, data must be filtered by period
                period_yms = [(p + y) * 100 + i for y in [0, 1]
                              for i in range(1, 13)]
                df_to_plot = df.loc[df[ind].isin(period_yms)].drop(
                    [ind], axis=1).reset_index(drop=True).dropna(axis=1,
                                                                 how='all')
            # To locate the legend: "loc" is the point of the legend for which
            # you will specify coordinates. These coords are specified in
            # bbox_to_anchor (can be only 1 point or couple)
            dis_plot = df_to_plot.plot(ax=dis_ax, linewidth=1.6).legend(
                loc='lower left',
                fontsize=8,
                bbox_to_anchor=(0., 1.015, 1., 1.015),
                ncol=num_col,
                mode="expand")
            plt.xticks(rotation=90, fontsize=9)
            plots.savefig(bbox_extra_artists=(dis_plot, ), bbox_inches='tight')
            plt.close()
        plots.close()
    ##############################################################

    def calc_tp_costs_in_period_one_scenario(m, p, s):
        return (sum(
            sum(
                # This are total costs in each tp for a scenario
                getattr(m, tp_cost)[t, s].expr() * m.tp_weight_in_year[t]
                for tp_cost in m.cost_components_tp)
            # Now, summation over timepoints
            for t in m.PERIOD_TPS[p]) *
                # Conversion to lump sum at beginning of period
                uniform_series_to_present_value(0, m.period_length_years[p]) *
                # Conversion to base year
                future_to_present_value(
                    m.discount_rate,
                    (m.period_start[p] - m.base_financial_year)))

    """
    Writing Objective Function value.
    """
    print "total_system_costs.txt..."
    with open(os.path.join(summaries_dir, "total_system_costs.txt"),
              'w+') as f:
        f.write("Total Expected System Costs: %.2f \n" % mod.SystemCost())
        f.write("Total Investment Costs: %.2f \n" %
                sum(mod.AnnualCostPerPeriod[p].expr() for p in mod.PERIODS))
        f.write("Total Expected Operations Costs: %.2f \n" %
                sum(mod.TpCostPerPeriod[p].expr() for p in mod.PERIODS))
        for p in mod.PERIODS:
            f.write("PERIOD %s\n" % p)
            f.write("  Investment Costs: %.2f \n" %
                    mod.AnnualCostPerPeriod[p].expr())
            f.write("  Expected Operations Costs: %.2f \n" %
                    mod.TpCostPerPeriod[p].expr())
            for s in mod.PERIOD_SCENARIOS[p]:
                f.write(
                    "    Operational Costs of scenario %s with probability %s: %.2f\n"
                    % (s, mod.scenario_probability[s],
                       calc_tp_costs_in_period_one_scenario(mod, p, s)))

    print "\nTime taken writing summaries: %.2f s." % (time.time() - start)
Beispiel #18
0
def post_solve(instance, outdir):
    """
    Exported files:
    
    dispatch-wide.txt - Dispatch results timepoints in "wide" format with
    timepoints as rows, generation projects as columns, and dispatch level
    as values
    
    dispatch.csv - Dispatch results in normalized form where each row 
    describes the dispatch of a generation project in one timepoint.
    
    dispatch_annual_summary.csv - Similar to dispatch.csv, but summarized
    by generation technology and period.
    
    dispatch_zonal_annual_summary.csv - Similar to dispatch_annual_summary.csv
    but broken out by load zone. 
    
    dispatch_annual_summary.pdf - A figure of annual summary data. Only written
    if the ggplot python library is installed.
    """
    write_table(
        instance,
        instance.TIMEPOINTS,
        output_file=os.path.join(outdir, "dispatch-wide.txt"),
        headings=("timestamp", ) + tuple(sorted(instance.GENERATION_PROJECTS)),
        values=lambda m, t:
        (m.tp_timestamp[t], ) + tuple(m.DispatchGen[p, t]
                                      if (p, t) in m.GEN_TPS else 0.0
                                      for p in sorted(m.GENERATION_PROJECTS)))

    dispatch_normalized_dat = [{
        "generation_project":
        g,
        "gen_dbid":
        instance.gen_dbid[g],
        "gen_tech":
        instance.gen_tech[g],
        "gen_load_zone":
        instance.gen_load_zone[g],
        "gen_energy_source":
        instance.gen_energy_source[g],
        "timestamp":
        instance.tp_timestamp[t],
        "tp_weight_in_year_hrs":
        instance.tp_weight_in_year[t],
        "period":
        instance.tp_period[t],
        "DispatchGen_MW":
        value(instance.DispatchGen[g, t]),
        "Energy_GWh_typical_yr":
        value(instance.DispatchGen[g, t] * instance.tp_weight_in_year[t] /
              1000),
        "VariableCost_per_yr":
        value(instance.DispatchGen[g, t] * instance.gen_variable_om[g] *
              instance.tp_weight_in_year[t]),
        "DispatchEmissions_tCO2_per_typical_yr":
        value(
            sum(instance.DispatchEmissions[g, t, f] *
                instance.tp_weight_in_year[t]
                for f in instance.FUELS_FOR_GEN[g]))
        if instance.gen_uses_fuel[g] else 0
    } for g, t in instance.GEN_TPS]
    dispatch_full_df = pd.DataFrame(dispatch_normalized_dat)
    dispatch_full_df.set_index(["generation_project", "timestamp"],
                               inplace=True)
    dispatch_full_df.to_csv(os.path.join(outdir, "dispatch.csv"))

    annual_summary = dispatch_full_df.groupby(
        ['gen_tech', "gen_energy_source", "period"]).sum()
    annual_summary.to_csv(os.path.join(outdir, "dispatch_annual_summary.csv"),
                          columns=[
                              "Energy_GWh_typical_yr", "VariableCost_per_yr",
                              "DispatchEmissions_tCO2_per_typical_yr"
                          ])

    zonal_annual_summary = dispatch_full_df.groupby(
        ['gen_tech', "gen_load_zone", "gen_energy_source", "period"]).sum()
    zonal_annual_summary.to_csv(
        os.path.join(outdir, "dispatch_zonal_annual_summary.csv"),
        columns=[
            "Energy_GWh_typical_yr", "VariableCost_per_yr",
            "DispatchEmissions_tCO2_per_typical_yr"
        ])

    if can_plot:
        annual_summary_plot = ggplot(
                annual_summary.reset_index(),
                aes(x='period', weight="Energy_GWh_typical_yr", fill="factor(gen_tech)")
            ) + \
            geom_bar(position="stack") + \
            scale_y_continuous(name='Energy (GWh/yr)') + theme_bw()
        annual_summary_plot.save(
            filename=os.path.join(outdir, "dispatch_annual_summary.pdf"))
Beispiel #19
0
def post_solve(mod, outdir):
    """
    This module's post solve function calls the plot_inv_decision and
    plot_dis_decision functions to write and plot different outputs.
    
    plot_inv_decision should be used when the quantity is indexed by periods
    
    plot_dis_decision should be used when the quantity is indexed by timepoints
    
    """
    # Import optional dependencies here instead of at the top of the file to
    # avoid breaking tests for installations that don't use this functionality
    import matplotlib.pyplot as plt
    from numpy import nan
    from cycler import cycler
    from matplotlib.backends.backend_pdf import PdfPages

    summaries_dir = os.path.join(outdir,"Summaries")
    if not os.path.exists(summaries_dir):
        os.makedirs(summaries_dir)
    else:
        print "Summaries directory exists, clearing it..."
        for f in os.listdir(summaries_dir):
            os.unlink(os.path.join(summaries_dir, f))
            
    color_map = plt.get_cmap('gist_rainbow')
    styles = cycle(['-','--','-.',':'])

    #####
    # Round doubles to the first decimal
    #for var in mod.component_objects():
    #    if not isinstance(var, Var):
    #        continue
    #    for key, obj in var.items():
    #        obj.value = round(obj.value,1)
    #    print "Finished rounding variable "+str(var)

    def plot_inv_decision(name, tab, n_data, ind, by_period):
        """
        This function plots an investment decision over all periods on a
        bar plot.
        
        Arguments are:
        
        name: Filename for the output pdf.
        
        tab: Table of data. Format should be a list of lists whose first
        row (the first list) contains column names.
        
        n_data: Number of records to plot. Used to cycle through colors and
        linestyles to differenciate different variables.
        
        ind: Name of the column to be used as index when transforming the
        table into a Pandas Dataframe. Usually represents time.
        
        by_period: A boolean indicating whether the plot should be stacked
        by period (False) or if values should be cummulative (True). In the
        former, x axis represents the investment alternatives and in the
        latter, it represents periods (hence he boolean values required).
        
        """
        if by_period:
            df = pd.DataFrame(tab[1:], 
                columns = tab[0]).set_index(ind).transpose()
            stack = False
            num_col = int(n_data)/10
        else:
            df = pd.DataFrame(tab[1:], columns = tab[0]).set_index(ind)
            stack = True
            num_col = int(n_data)/2
        fig = plt.figure()
        inv_ax = fig.add_subplot(111)
        inv_ax.grid(b=False)
        # You have to play with the color map and the line style list to 
        # get enough combinations for your particular plot
        inv_ax.set_prop_cycle(cycler('color',
                        [color_map(i/n_data) for i in range(0, n_data+1)]))
        # To locate the legend: "loc" is the point of the legend for which you
        # will specify coordinates. These coords are specified in 
        # bbox_to_anchor (can be only 1 point or couple)        
        inv_plot = df.plot(kind='bar', ax=inv_ax, 
            stacked=stack).legend(loc='lower left', fontsize=8, 
            bbox_to_anchor=(0.,1.015,1.,1.015), ncol=num_col, mode="expand")
        if by_period:
            plt.xticks(rotation=0, fontsize=10)
            fname = summaries_dir+'/'+name+'.pdf'
        else:
            plt.xticks(rotation=90, fontsize=9)
            fname = summaries_dir+'/'+name+'_stacked_by_p.pdf'
        plt.savefig(fname, bbox_extra_artists=(inv_plot,), bbox_inches='tight')
        plt.close()

    def plot_dis_decision(name, tab, n_data, ind):
        """
        This function prints a pdf with dispatch decisions plotted over all 
        periods on a line plot and also a close up of each period on the
        subsequent pages of the file.
        
        Arguments are:
        
        name: Filename for the output pdf.
        
        tab: Table of data. Format should be a list of lists whose first
        row (the first list) contains column names.
        
        n_data: Number of records to plot. Used to cycle through colors and
        linestyles to differenciate different variables.
        
        ind: Name of the column to be used as index when transforming the
        table into a Pandas Dataframe. Usually represents time. 
        
        """
        
        plots = PdfPages(os.path.join(outdir,"Summaries",name)+'.pdf')
        
        df = pd.DataFrame(tab[1:], columns = tab[0])
        
        n_scen = mod.SCENARIOS.__len__()
        #num_col = int(n_data * n_scen)/8
        num_col = 6
        
        for p in ['all']+[p for p in mod.PERIODS]:
            fig = plt.figure(figsize=(17,8), dpi=100)
            dis_ax = fig.add_subplot(111)
            dis_ax.grid(b=False)
            # You have to play with the color map and the line style list to 
            # get enough combinations for your particular plot.
            # Set up different x axis labels if all periods are being plotted
            if p == 'all':
                dis_ax.set_xticks([i*24 
                    for i in range(0,len(mod.TIMEPOINTS)/24+1)])
                dis_ax.set_xticklabels([mod.tp_timestamp[mod.TIMEPOINTS[i*24+1]]
                    for i in range(0,len(mod.TIMEPOINTS)/24)])
                # Technologies have different linestyles and scenarios have 
                # different colors
                dis_ax.set_prop_cycle(cycler('color',
                    [color_map(i/float(n_data-1)) for i in range(n_data)]) * 
                    cycler('linestyle',[next(styles) for i in range(n_scen)]))
                df_to_plot = df.drop([ind], axis=1).replace('', nan)
            else:
                n_scen = mod.PERIOD_SCENARIOS[p].__len__()
                dis_ax.set_xticks([i*6 for i in range(0,len(mod.PERIOD_TPS[p])/6+1)])
                dis_ax.set_xticklabels([mod.tp_timestamp[mod.PERIOD_TPS[p][t*6+1]] 
                    for t in range(0,len(mod.PERIOD_TPS[p])/6)])
                # Technologies have different colors and scenarios have 
                # different line styles                
                dis_ax.set_prop_cycle(cycler('color',
                    [color_map(i/float(n_data-1)) for i in range(n_data)]) * 
                    cycler('linestyle', [next(styles) for i in range(n_scen)]))
                # Before plotting, data must be filtered by period
                period_tps = [mod.tp_timestamp[tp] 
                            for tp in mod.PERIOD_TPS[p].value]
                df_to_plot = df.loc[df[ind].isin(period_tps)].drop([ind], 
                    axis=1).reset_index(drop=True).dropna(axis=1, how='all')
            # To locate the legend: "loc" is the point of the legend for which 
            # you will specify coordinates. These coords are specified in 
            # bbox_to_anchor (can be only 1 point or couple)        
            dis_plot = df_to_plot.plot(ax=dis_ax,
                linewidth=1.6).legend(loc='lower left', fontsize=8,
                bbox_to_anchor=(0., 1.015, 1., 1.015), ncol=num_col, 
                mode="expand")
            plt.xticks(rotation=90, fontsize=9)
            plots.savefig(bbox_extra_artists=(dis_plot,), bbox_inches='tight')
            plt.close()
        plots.close()

    print "Printing summaries:\n==================="
    start=time.time()

    # print "renewable energy production"
    # rpsenergy = {s:0.0 for s in mod.SCENARIOS}
    # renergy = {s:0.0 for s in mod.SCENARIOS}
    # energy = {s:0.0 for s in mod.SCENARIOS}
    # for s in mod.SCENARIOS:
    #     for tp in mod.PERIOD_TPS[mod.scenario_period[s]]:
    #         for pr in mod.ERNC_ACTIVE_IN_TP[tp]:
    #             rpsenergy[s] += mod.DispatchProj[pr,tp,s].value*mod.tp_weight[tp] / 1000000.0
    #         for pr in mod.ERNC_ACTIVE_IN_TP1[tp]:
    #             renergy[s] += mod.DispatchProj[pr,tp,s].value*mod.tp_weight[tp] / 1000000.0
    #         for pr in mod.PROJECTS_ACTIVE_IN_TIMEPOINT[tp]:
    #             energy[s] += mod.DispatchProj[pr,tp,s].value*mod.tp_weight[tp]/1000000.0
    # with open(os.path.join(summaries_dir, "rps.tab"),'w') as f:
    #     for p in mod.PERIODS:
    #         ener = sum(energy[s]*mod.scenario_probability[s] for s in mod.PERIOD_SCENARIOS[p])
    #         rpsener = sum((rpsenergy[s]/energy[s]*100.0)*mod.scenario_probability[s] for s in mod.PERIOD_SCENARIOS[p])
    #         rener = sum((renergy[s]/energy[s]*100.0)*mod.scenario_probability[s] for s in mod.PERIOD_SCENARIOS[p])
    #         f.write("Period %s expected: Total - %10.1f TWh // %3.2f ERNC // %3.2f Renewable\n" % (p,ener,rpsener,rener))
    #     for s in mod.SCENARIOS:
    #         f.write("Scen %s: Total - %10.1f TWh // %3.2f ERNC // %3.2f Renewable\n" % (s,energy[s],rpsenergy[s]/energy[s]*100, renergy[s]/energy[s]*100.0))
    
    if mod.options.export_all:
        mod.options.export_reservoirs = True
        mod.options.export_tech_dispatch = True
        mod.options.export_capacities = True
        mod.options.export_transmission = True 

    # table_name = "energy_by_gentech_periods"
    # print table_name+" ..."
    # table = export.write_table(
    #     mod, True, mod.SCENARIOS, mod.GENERATION_TECHNOLOGIES,
    #     output_file=os.path.join(summaries_dir, table_name+".csv"), 
    #     headings=("scenario", "gentech", "energy_produced_TWh"),
    #     values=lambda m, s, g: (s, g,
    #         sum(m.DispatchProj[pr,tp,s]*m.tp_weight[tp]
    #         for tp in m.PERIOD_TPS[m.scenario_period[s]]
    #             for pr in m.PROJECTS_ACTIVE_IN_TIMEPOINT[tp] 
    #                 if g==m.proj_gen_tech[pr])/1000000.0))      
    
    if mod.options.export_capacities:
        n_elements = mod.GENERATION_TECHNOLOGIES.__len__()
        index = 'gentech'
        
        table_name = "cummulative_capacity_by_tech_periods"
        print table_name+" ..."
        table = export.write_table(
            mod, mod.GENERATION_TECHNOLOGIES,
            output_file=os.path.join(summaries_dir, table_name+".csv"),
            headings=(index, 'legacy') + tuple(p 
                for p in mod.PERIODS),
            values=lambda m, gt: (gt, sum(m.BuildGen[g, bldyr] 
                for (g, bldyr) in m.GEN_BLD_YRS
                if m.gen_tech[g] == gt and bldyr not in m.PERIODS)) + 
            tuple( sum(m.GenCapacity[g, p] for g in m.GENERATION_PROJECTS 
                if m.gen_tech[g] == gt) for p in m.PERIODS))
        plot_inv_decision(table_name, table, n_elements, index, True)
        
        table_name = "capacity_installed_by_tech_periods"
        print table_name+" ..."
        table = export.write_table(
            mod, mod.GENERATION_TECHNOLOGIES,
            output_file=os.path.join(summaries_dir, table_name+".csv"),
            headings=(index, 'legacy') + tuple(p 
                for p in mod.PERIODS),
            values=lambda m, gt: (gt, sum(m.BuildGen[g, bldyr] 
                for (g, bldyr) in m.GEN_BLD_YRS
                if m.gen_tech[g] == gt and bldyr not in m.PERIODS)) + 
            tuple( sum(m.BuildGen[g, p] for g in m.GENERATION_PROJECTS 
                if m.gen_tech[g] == gt) for p in m.PERIODS))
        plot_inv_decision(table_name, table, n_elements, index, False)
    
    if mod.options.export_transmission:
        n_elements = mod.TRANSMISSION_LINES.__len__()
        index = 'path'
        
        table_name = "cummulative_transmission_by_path_periods"
        print table_name+" ..."
        table = export.write_table(
            mod, True, mod.TRANSMISSION_LINES,
            output_file=os.path.join(summaries_dir, table_name+".csv"),
            headings=(index, 'legacy') + tuple(p for p in mod.PERIODS),
            values=lambda m, tx: (tx, m.existing_trans_cap[tx]) + 
                tuple(m.TransCapacity[tx, p] for p in m.PERIODS))
        #plot_inv_decision(table_name, table, n_elements, index, True)
        
        table_name = "transmission_installation_by_path_periods"
        print table_name+" ..."
        table = export.write_table(
            mod, True, mod.TRANSMISSION_LINES,
            output_file=os.path.join(summaries_dir, table_name+".csv"),
            headings=(index, 'legacy') + tuple(p for p in mod.PERIODS),
            values=lambda m, tx: (tx, m.existing_trans_cap[tx]) + 
                tuple(m.BuildTrans[tx, p] for p in m.PERIODS))        
        plot_inv_decision(table_name, table, n_elements, index, False)
    
    
    if mod.options.export_tech_dispatch:
        n_elements = mod.GENERATION_TECHNOLOGIES.__len__() 
        index = 'timepoints'
        
        gen_projects = {}
        for g in mod.GENERATION_TECHNOLOGIES:    
            gen_projects[g] = []
            for prj in mod.PROJECTS:
                if mod.proj_gen_tech[prj]==g:
                    gen_projects[g].append(prj) 
        def print_dis(m, tp):
            tup = (m.tp_timestamp[tp],)
            for g in m.GENERATION_TECHNOLOGIES:
                for s in m.SCENARIOS:
                    if s in m.PERIOD_SCENARIOS[m.tp_period[tp]]:
                        tup += (sum(m.DispatchProj[proj, tp, s] for proj in gen_projects[g] if (proj,tp,s) in m.PROJ_DISPATCH_POINTS),)
                    else:
                        tup += ('',)
            return tup

        table_name = "dispatch_proj_by_tech_tps"
        print table_name+" ..."
        table = export.write_table(
            mod, True, mod.TIMEPOINTS,
            output_file=os.path.join(summaries_dir, table_name+".csv"),
            headings=("timepoints",) + tuple(str(g)+"-"+str(mod.scenario_stamp[s]) for g in mod.GENERATION_TECHNOLOGIES for s in mod.SCENARIOS),
            values=print_dis)
        plot_dis_decision(table_name, table, n_elements, index)
    
    if mod.options.export_reservoirs:
        n_elements = mod.RESERVOIRS.__len__()
        index = 'timepoints'
        
        def print_res(m, tp):
            tup = (m.tp_timestamp[tp],)
            for r in m.RESERVOIRS:
                for s in m.SCENARIOS:
                    if s in m.PERIOD_SCENARIOS[m.tp_period[tp]]:
                        tup += (m.ReservoirVol[r, tp, s] - m.initial_res_vol[r],)
                    else:
                        tup += ('',)
            return tup
        
        table_name = "reservoir_final_vols_tp"
        print table_name+" ..."
        table = export.write_table(
            mod, True, mod.TIMEPOINTS,
            output_file=os.path.join(summaries_dir, table_name+".csv"),
            headings=("timepoints",) + tuple(str(r)+"-"+
                str(mod.scenario_stamp[s]) for r in mod.RESERVOIRS 
                for s in mod.SCENARIOS),
            values=print_res)
        plot_dis_decision(table_name, table, n_elements, index) 
        
        ##############################################################
        # The following is a custom export to get dispatch for certain
        # Chile load zones
        lzs_to_print = ['charrua','ancoa']

        lz_hprojs = {}
        for lz in lzs_to_print:
            lz_hprojs[lz]=[]
            for proj in mod.LZ_PROJECTS[lz]:
                if proj in mod.HYDRO_PROJECTS:
                    lz_hprojs[lz].append(proj)

        def print_hgen(m, tp):
            tup = (m.tp_timestamp[tp],)
            for lz in lzs_to_print:
                for s in m.SCENARIOS:
                    if s in m.PERIOD_SCENARIOS[m.tp_period[tp]]:
                        tup += (sum(m.DispatchProj[proj, tp, s] for proj in lz_hprojs[lz] if (proj,tp,s) in m.HYDRO_PROJ_DISPATCH_POINTS),)
                    else:
                        tup += ('',)
            return tup

        table_name = "hydro_dispatch_special_nodes_tp"
        print table_name+" ..."
        table = export.write_table(
            mod, True, mod.TIMEPOINTS,
            output_file=os.path.join(summaries_dir, table_name+".csv"),
            headings=("timepoints",) + tuple(str(lz)+"-"+str(
                mod.scenario_stamp[s]) for lz in lzs_to_print 
                for s in mod.SCENARIOS),
            values=print_hgen)
        #plot_dis_decision(table_name, table, n_elements, index)
        
    if mod.options.export_load_blocks:
        def print_res(m, ym):
            tup = (ym,)
            for r in m.RESERVOIRS:
                for s in m.SCENARIOS:
                    if s in m.PERIOD_SCENARIOS[m.tp_period[next(iter(m.ym_timepoints[ym]))]]:
                        tup += (m.ReservoirVol[r, ym, s] - m.initial_res_vol[r],)
                    else:
                        tup += ('',)
            return tup
        table_name = "reservoir_vols_load_block"
        print table_name+" ..."
        tab = export.write_table(
            mod, True, mod.YEARMONTHS,
            output_file=os.path.join(summaries_dir, table_name+".csv"),
            headings=("yearmonth",) + tuple(str(r)+"-"+
                str(mod.scenario_stamp[s]) for r in mod.RESERVOIRS 
                for s in mod.SCENARIOS),
            values=print_res)
        n_data = mod.RESERVOIRS.__len__()
        ind = 'yearmonth'
        plots = PdfPages(os.path.join(outdir,"Summaries",table_name)+'.pdf')

        df = pd.DataFrame(tab[1:], columns = tab[0])

        n_scen = mod.SCENARIOS.__len__()
        #num_col = int(n_data * n_scen)/8
        num_col = 6

        for p in ['all']+[p for p in mod.PERIODS]:
            fig = plt.figure(figsize=(17,8), dpi=100)
            dis_ax = fig.add_subplot(111)
            dis_ax.grid(b=False)
            # You have to play with the color map and the line style list to 
            # get enough combinations for your particular plot.
            # Set up different x axis labels if all periods are being plotted
            if p == 'all':
                dis_ax.set_xticks([i*5
                    for i in range(0,len(mod.YEARMONTHS)/5+1)])
                dis_ax.set_xticklabels([mod.YEARMONTHS[i*5+1]
                    for i in range(0,len(mod.YEARMONTHS)/5)])
                # Technologies have different linestyles and scenarios have 
                # different colors
                dis_ax.set_prop_cycle(cycler('color',
                    [color_map(i/float(n_data-1)) for i in range(n_data)]) * 
                    cycler('linestyle',[next(styles) for i in range(n_scen)]))
                df_to_plot = df.drop([ind], axis=1).replace('', nan)
            else:
                n_scen = mod.PERIOD_SCENARIOS[p].__len__()
                dis_ax.set_xticks([i*5 for i in range(0,24)])
                dis_ax.set_xticklabels([mod.YEARMONTHS[i] 
                    for i in range(1,25)])
                # Technologies have different colors and scenarios have 
                # different line styles                
                dis_ax.set_prop_cycle(cycler('color',
                    [color_map(i/float(n_data-1)) for i in range(n_data)]) * 
                    cycler('linestyle', [next(styles) for i in range(n_scen)]))
                # Before plotting, data must be filtered by period
                period_yms = [(p+y)*100+i for y in [0,1] for i in range(1,13)]
                df_to_plot = df.loc[df[ind].isin(period_yms)].drop([ind], 
                    axis=1).reset_index(drop=True).dropna(axis=1, how='all')
            # To locate the legend: "loc" is the point of the legend for which 
            # you will specify coordinates. These coords are specified in 
            # bbox_to_anchor (can be only 1 point or couple)        
            dis_plot = df_to_plot.plot(ax=dis_ax,
                linewidth=1.6).legend(loc='lower left', fontsize=8,
                bbox_to_anchor=(0., 1.015, 1., 1.015), ncol=num_col, 
                mode="expand")
            plt.xticks(rotation=90, fontsize=9)
            plots.savefig(bbox_extra_artists=(dis_plot,), bbox_inches='tight')
            plt.close()
        plots.close()
    ##############################################################
    
    def calc_tp_costs_in_period_one_scenario(m, p, s):
        return (sum(sum(
            # This are total costs in each tp for a scenario
            getattr(m, tp_cost)[t, s].expr() * m.tp_weight_in_year[t]
                    for tp_cost in m.cost_components_tp)
                    # Now, summation over timepoints 
                        for t in m.PERIOD_TPS[p]) *
            # Conversion to lump sum at beginning of period
            uniform_series_to_present_value(
                0, m.period_length_years[p]) *
            # Conversion to base year
            future_to_present_value(
                m.discount_rate, (m.period_start[p] - m.base_financial_year)))

    """
    Writing Objective Function value.
    """
    print "total_system_costs.txt..."
    with open(os.path.join(summaries_dir, "total_system_costs.txt"),'w+') as f:
        f.write("Total Expected System Costs: %.2f \n" % mod.SystemCost())
        f.write("Total Investment Costs: %.2f \n" % sum(
            mod.AnnualCostPerPeriod[p].expr() for p in mod.PERIODS))
        f.write("Total Expected Operations Costs: %.2f \n" % sum(
            mod.TpCostPerPeriod[p].expr() for p in mod.PERIODS))
        for p in mod.PERIODS:
            f.write("PERIOD %s\n" % p)
            f.write("  Investment Costs: %.2f \n" % mod.AnnualCostPerPeriod[p].expr())    
            f.write("  Expected Operations Costs: %.2f \n" % mod.TpCostPerPeriod[p].expr())
            for s in mod.PERIOD_SCENARIOS[p]:
                f.write("    Operational Costs of scenario %s with probability %s: %.2f\n" % (s, mod.scenario_probability[s], calc_tp_costs_in_period_one_scenario(mod, p, s)))
  
    
    print "\nTime taken writing summaries: %.2f s." % (time.time()-start)