This package provides tools for New York City residents and Consolidated Edison customers to log their electricity consumption and estimate their emissions contribution. The package currently provides the means to query:
- ConEd for personal usage data
- The New York Independent System Operator for fuel mix data
The package currently supports writing of data to an InfluxDB time-series database.
This package comprises two main super classes: a Reader for accessing data from external sources and formatting into measurements (Measurement class), and a Writer for writing measurements to a database. In addition, the package contains utilities for derivative calculations.
Each Reader class holds measurements accessible by a key, containing the data returned by the last query (query()
method).
Class | Key | Measurement Description |
---|---|---|
ConEdReader | ['usage'] |
ConEd 15-minute usage data in kWh |
NYISOReader | ['fuel_mix'] |
NYISO 5-minute fuel mix data in MW |
['emissions'] |
Estimated 5-minute average carbon intensity in kg/MWh CO2 equivalent |
The Writer class contains the write_measurement
method, which accepts a measurement and writes it to the destination.
The handling of the different properties of the Measurement class is described in the following table.
Measurement Property | Description | InfluxDBWriter Handling |
---|---|---|
name | String containing the name of the measurement | Written as InfluxDB Measurement name |
unit | String containing the unit of measurement | Written as a tag named 'unit' |
tags | A dictionary containing any additional user-defined tags | Written as tags named for the dict keys |
database | A string containing the name of the destination database | Writes to matching InfluxDB database |
df | A Pandas DataFrame containing the time-series data with timestamp in UTC | Each column is written as an InfluxDB |
series |
The co2_utils.py
module contains the co2_calc
function to convert fuel mix data to estimated carbon intensity data.
The conversion uses carbon intensity curves for each fuel type stored as a pickle file. The generate_curves
function
can be used to generate new curves from the annual eGRID datafiles published by the U.S. Environmental Protection
Agency.
See Notes on CO2 Intensity Calculation.
Input:
from home_energy_nyc.connections import ConEdReader, NYISOReader, InfluxDBWriter
import configparser
CONFIG_FILEPATH = r'home_energy_nyc.conf'
conf = configparser.ConfigParser()
conf.read(CONFIG_FILEPATH)
readers = (
NYISOReader.from_config(conf),
ConEdReader.from_config(conf)
)
writer = InfluxDBWriter.from_config(conf)
for r in readers:
r.query()
for msr in r.measurements():
writer.write_measurement(msr)
The above example uses the from_config
class method as an alternative constructor, enabling initialization arguments
(e.g. usernames, passwords) to be read from a configuration file. The configuration file section headers must match
the class names, and all arguments for the __init__
method of the corresponding class must be present (in any order).
Example: Extract of the configuration file:
[InfluxDBWriter]
host = localhost
port = 8086
username = usr
password = pwd
Input:
from home_energy_nyc import generate_curves
generate_curves(2019, r'references/egrid2019_data_metric.xlsx')
Output:
CO2 curves written for 2019. Average CO2 intensity estimated at 92.1% of EPA reported value.
The curve generator will construct, from the EPA eGRID dataset, a curve of CO2 intensity vs. cumulative dispatched capacity per fuel type and write the complete set of curves to the 'database' folder. It will then download historical NYISO fuel mix data for the stated year, apply the curves and compare the calculated annual emissions with those reported for the NYISO Balancing Authrotiy in the EPA eGRID dataset (field code BAC2ERTA). The function will return the accuracy measured as the calculated value divided by the historical value.
- All plants of a given fuel type are imported and ordered by descending Capacity Factor (C.F.). The C.F. operates as a proxy for the the likelihood of dispatch, with lower C.F. plant being dispatched later in the stack. Any plant that was not dispatched in the year (zero C.F.) is discarded.
- Hourly CO2 rate in kg/h for each plant is generated by multiplying Nameplate Capacity in MW by plant equivalent CO2 emissions in kg/MWh from the EPA dataset.
- Cumulative capacity is calculated across the stack.
- Cumulative CO2 rate in kg/h is calculated and converted back to kg/MWh by dividing by cumulative capacity.
- The cumulative capacity is normalized such that the full cumulative capacity of the stack is equal to the maximum quantity of capacity of the given fuel type that was dispatched in the year. This step is necessary because there is much more capacity that the maximum dispatch and no plant dispatches with 100% CF. We are aiming to construct a general curve representing efficient plant being dispatched first and more polluting plant being call upon as resources are stretched. We calibrate the lowest C.F. plant to peak dispatch.
Example: Calculation steps before normalization.
Plant | Capacity (MW) | C.F. | CO2 eq. (kg/h) | Cum. Capacity (MW) | Cum. CO2 eq. (kg/MWh) |
---|---|---|---|---|---|
1 | 300 | 0.8 | 90,000 | 300 | 300 |
2 | 175 | 0.6 | 61,250 | 475 | 318 |
3 | 50 | 0.05 | 20,000 | 525 | 326 |
4 | 50 | 0.01 | 20,000 | 575 | 333 |
Example: Final curve normalized to a peak dispatch of 100 MW.
Normalized Capacity (MW) | Cum. CO2 eq. (kg/MWh) |
---|---|
52 | 300 |
83 | 318 |
91 | 326 |
100 | 333 |
Historical data from 2018 and 2019 indicates an accuracy of -8% to -12% in total annual emissions. One possible reason for the underestimate is the assumption that dual fuel plant is running exclusively on gas, a more efficient fuel than oil. However, oil fired hours are relatively few and there are likely other factors at play. As a general indicator of the most polluting hours, this method is adequate but may be improved upon.
The methodology is only capable of taking a state-wide view. Due to transmission constraints on importing clean power from upstate into New York City, more gas is dispatched in the City. Therefore a kWh consumed in the City is in a given hour is likely to be associated with higher carbon emissions. Furthermore, this method only accounts for plant generating in the NYISO system and will not account for any distribution-level generation. More granular realtime data would be required to improve accuracy.
As offshore wind is deployed off Long Island, New York City residents can expect their carbon footprint to significantly improve.