Skip to content

Commit

Permalink
System module sphinx documentation (#146)
Browse files Browse the repository at this point in the history
* Added dummy files for the system module documentation.

* Added new examples for system tracking.

* updated the system tracking docs.

* adding docs

* updates to the routines for system module

* updated the routines for tracking module

* cleaned up doc strings + added example SERF East data.

* updated the whatsnew docs

* Updated the pvwatts routine to use PSM3 data

* added psm3 csv

* reduced size of the serf east fiel to 10k rows

* removed duplicate csv file

* added the system ID to OEDI documentation

* update the system ID for OEDI

* Update docs/examples/infer-orientation-daily-peak.py

Co-authored-by: Kevin Anderson <[email protected]>

* Update docs/examples/infer-orientation-fit-pvwatts.py

Co-authored-by: Kevin Anderson <[email protected]>

* changes to documentation based on @kandersonrel's review

* Update docs/examples/infer-orientation-fit-pvwatts.py

Co-authored-by: Kevin Anderson <[email protected]>

* updated the docstring to avoid pep8 errors>

* update the csv name

* removed the daily peak documentation.

* reformatting for release 0.1.3

* updated pvwatts model docstring

* added oedi reference to tracking system documentation

* removed redundant file directory definition

* Added readme for the system examples

* update the naming for pvwatts model

* Add visualizations for the documentation (plot first few days of time series)

* updated docstrings in final review

* fix flake8 issues

* added back missing text in whats new 0.1.2

* Update docs/examples/system/infer-orientation-fit-pvwatts.py

Co-authored-by: Cliff Hansen <[email protected]>

Co-authored-by: Perry <[email protected]>
Co-authored-by: Kevin Anderson <[email protected]>
Co-authored-by: Cliff Hansen <[email protected]>
  • Loading branch information
4 people authored Dec 12, 2022
1 parent 83500ac commit b212fff
Show file tree
Hide file tree
Showing 7 changed files with 19,590 additions and 1 deletion.
4 changes: 4 additions & 0 deletions docs/examples/system/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
System
------

This includes examples for system parameter estimation, including azimuth and tilt estimation, and determination if the system is fixed tilt or tracking.
90 changes: 90 additions & 0 deletions docs/examples/system/infer-orientation-fit-pvwatts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""
Infer Array Tilt/Azimuth - PVWatts Method
=========================================
Infer the azimuth and tilt of a system using PVWatts-based methods
"""

# %%
# Identifing and/or validating the azimuth and tilt information for a
# system is important, as these values must be correct for degradation
# and system yield analysis. This example shows how to use
# :py:func:`pvanalytics.system.infer_orientation_fit_pvwatts` to estimate
# a fixed-tilt system's azimuth and tilt, using the system's known
# latitude-longitude coordinates and an associated AC power time series.

import pvanalytics
import matplotlib.pyplot as plt
from pvanalytics import system
import pandas as pd
import pathlib
import pvlib

# %%
# First, we import an AC power data stream from the SERF East site located at
# NREL. This data set is publicly available via the PVDAQ database in the
# DOE Open Energy Data Initiative (OEDI)
# (https://data.openei.org/submissions/4568), under system ID 50.
# This data is timezone-localized.

pvanalytics_dir = pathlib.Path(pvanalytics.__file__).parent
ac_power_file = pvanalytics_dir / 'data' / 'serf_east_15min_ac_power.csv'
data = pd.read_csv(ac_power_file, index_col=0, parse_dates=True)
data = data.sort_index()
time_series = data['ac_power']
time_series = time_series.asfreq('15T')

# Plot the first few days of the time series to visualize it
time_series[:pd.to_datetime("2016-07-06 00:00:00-07:00")].plot()
plt.show()

# Outline the ground truth metadata associated with the system
latitude = 39.742
longitude = -105.1727
actual_azimuth = 158
actual_tilt = 45

# %%
# Next, we import the PSM3 data generated via the
# :py:func:`pvlib.iotools.get_psm3` function, using
# site latitude-longitude coordinates. To generate the
# PSM3 data, you must first register for NREL's NSDRB API at the
# following link: https://developer.nrel.gov/signup/.
# PSM3 data can then be retrieved using :py:func:`pvlib.iotools.get_psm3`.
# The PSM3 data has been resampled to 15 minute intervals, to match the AC
# power data.

psm3_file = pvanalytics_dir / 'data' / 'serf_east_psm3_data.csv'
psm3 = pd.read_csv(psm3_file, index_col=0, parse_dates=True)

# %%
# Filter the PSM3 data to only include clearsky periods
is_clear = (psm3.ghi_clear == psm3.ghi)
is_daytime = (psm3.ghi > 0)
time_series_clearsky = time_series[is_clear & is_daytime]
time_series_clearsky = time_series_clearsky.dropna()
psm3_clearsky = psm3.loc[time_series_clearsky.index]

# Get solar azimuth and zenith from pvlib, based on
# lat-long coords
solpos_clearsky = pvlib.solarposition.get_solarposition(
time_series_clearsky.index, latitude, longitude)

# %%
# Run the pvlib data and the sensor-based time series data through
# the :py:func:`pvanalytics.system.infer_orientation_fit_pvwatts` function.
best_tilt, best_azimuth, r2 = system.infer_orientation_fit_pvwatts(
time_series_clearsky,
psm3_clearsky.ghi_clear,
psm3_clearsky.dhi_clear,
psm3_clearsky.dni_clear,
solpos_clearsky.zenith,
solpos_clearsky.azimuth,
temperature=psm3_clearsky.temp_air,
)

# Compare actual system azimuth and tilt to predicted azimuth and tilt
print("Actual Azimuth: " + str(actual_azimuth))
print("Predicted Azimuth: " + str(best_azimuth))
print("Actual Tilt: " + str(actual_tilt))
print("Predicted Tilt: " + str(best_tilt))
65 changes: 65 additions & 0 deletions docs/examples/system/system-tracking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"""
Detect if a System is Tracking
==============================
Identifying if a system is tracking or fixed tilt
"""

# %%
# It is valuable to identify if a system is fixed tilt or tracking for
# future analysis. This example shows how to use
# :py:func:`pvanalytics.system.is_tracking_envelope` to determine if a
# system is tracking or not by fitting data to a maximum power or
# irradiance envelope, and fitting this envelope to quadratic and
# quartic curves. The r^2 output from these fits is used to determine
# if the system fits a tracking or fixed-tilt profile.

import pvanalytics
from pvanalytics.system import is_tracking_envelope
from pvanalytics.features.clipping import geometric
from pvanalytics.features.daytime import power_or_irradiance
import pandas as pd
import pathlib
import matplotlib.pyplot as plt

# %%
# First, we import an AC power data stream from the SERF East site located at
# NREL. This data set is publicly available via the PVDAQ database in the
# DOE Open Energy Data Initiative (OEDI)
# (https://data.openei.org/submissions/4568), under system ID 50.
# This data is timezone-localized. This particular data stream is associated
# with a fixed-tilt system.

pvanalytics_dir = pathlib.Path(pvanalytics.__file__).parent
ac_power_file = pvanalytics_dir / 'data' / \
'serf_east_15min_ac_power.csv'
data = pd.read_csv(ac_power_file, index_col=0, parse_dates=True)
data = data.sort_index()
time_series = data['ac_power']
time_series = time_series.asfreq('15T')

# Plot the first few days of the time series to visualize it
time_series[:pd.to_datetime("2016-07-06 00:00:00-07:00")].plot()
plt.show()

# %%
# Run the clipping and the daytime filters on the time series.
# Both of these masks will be used as inputs to the
# :py:func:`pvanalytics.system.is_tracking_envelope` function.

# Generate the daylight mask for the AC power time series
daytime_mask = power_or_irradiance(time_series)

# Generate the clipping mask for the time series
clipping_mask = geometric(time_series)

# %%
# Now, we use :py:func:`pvanalytics.system.is_tracking_envelope` to
# identify if the data stream is associated with a tracking or fixed-tilt
# system.

predicted_mounting_config = is_tracking_envelope(time_series,
daytime_mask,
clipping_mask)

print("Estimated mounting configuration: " + predicted_mounting_config.name)
1 change: 0 additions & 1 deletion docs/whatsnew/0.1.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ Other
* Removed empty modules ``pvanalytics.filtering`` and ``pvanalytics.fitting``
until the relevant functionality is added to the package. (:pull:`145`)


Contributors
~~~~~~~~~~~~

Expand Down
5 changes: 5 additions & 0 deletions docs/whatsnew/0.1.3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ Added new gallery example pages:
* :py:func:`~pvanalytics.quality.weather.relative_humidity_limits`
* :py:func:`~pvanalytics.quality.weather.wind_limits`
* :py:func:`~pvanalytics.quality.weather.module_temperature_check`

* ``pvanalytics.system`` (:issue:`133`, :pull:`146`):

* :py:func:`~pvanalytics.system.infer_orientation_fit_pvwatts`
* :py:func:`~pvanalytics.system.is_tracking_envelope`

* ``pvanalytics.quality.irradiance.calculate_component_sum_series``(:issue:`157`, :pull:`163`)
Expand Down
Loading

0 comments on commit b212fff

Please sign in to comment.