diff --git a/docs/sphinx/source/comparison_pvlib_matlab.rst b/docs/sphinx/source/comparison_pvlib_matlab.rst index 01bdb20ad2..fac6d4e1e3 100644 --- a/docs/sphinx/source/comparison_pvlib_matlab.rst +++ b/docs/sphinx/source/comparison_pvlib_matlab.rst @@ -1,66 +1,80 @@ .. _comparison_pvlib_matlab: **************************** -Comparison with PVLIB_MATLAB +Comparison with PVLIB MATLAB **************************** -This document is under construction. -Please see our -`PVSC 2014 paper `_ -and -`PVSC 2015 abstract `_ -for more information. +PVLIB was originally developed as a library for MATLAB at Sandia +National Lab, and Sandia remains the official maintainer of the MATLAB +library. Sandia supported the initial Python port and +then released further project maintenance and development to the +`pvlib-python maintainers `_. -The pvlib-python license is BSD 3-clause, -the PVLIB\_MATLAB license is ??. +The pvlib-python maintainers collaborate with the PVLIB MATLAB +maintainers but operate independently. We'd all like to keep the core +functionality of the Python and MATLAB projects synchronized, but this +will require the efforts of the larger pvlib-python community, not just +the maintainers. Therefore, do not expect feature parity between the +libaries, only similarity. -We want to keep developing the core functionality and algorithms -of the Python and MATLAB projects roughly in parallel, -but we're not making any promises at this point. -The PVLIB\_MATLAB and pvlib-python projects are currently developed -by different teams that do not regularly work together. -We hope to grow this collaboration in the future. -Do not expect feature parity between the libaries, only similarity. +Major differences +~~~~~~~~~~~~~~~~~ -Here are some of the major differences between the latest pvlib-python build -and the original Sandia PVLIB\_Python project, but many of these -comments apply to the difference between pvlib-python and PVLIB\_MATLAB. +* pvlib-python uses git version control to track all changes + to the code. A summary of changes is included in the whatsnew file + for each release. PVLIB MATLAB documents changes in Changelog.docx +* pvlib-python has a comprehensive test suite, whereas PVLIB MATLAB does + not have a test suite at all. Specifically, pvlib-python + * Uses TravisCI for automated testing on Linux. + * Uses Appveyor for automated testing on Windows. + * Uses Coveralls to measure test coverage. -Library wide changes -~~~~~~~~~~~~~~~~~~~~ +* Using readthedocs for automated documentation building and hosting. +* Removed ``pvl_`` from module/function names. +* Consolidated similar functions into topical modules. + For example, functions from ``pvl_clearsky_ineichen.m`` and + ``pvl_clearsky_haurwitz.m`` have been consolidated into ``clearsky.py``. +* PVLIB MATLAB uses ``location`` structs as the input to some functions. + pvlib-python just uses the lat, lon, etc. as inputs to the functions. + Furthermore, pvlib-python replaces the structs with classes, and these classes + have methods, such as :py:func:`~pvlib.location.Location.get_solarposition`, + that automatically reference the appropriate data. + See :ref:`modeling-paradigms` for more information. +* pvlib-python implements a handful of class designed to simplify the + PV modeling process. These include :py:class:`~pvlib.location.Location`, + :py:class:`~pvlib.pvsystem.PVSystem`, + :py:class:`~pvlib.pvsystem.LocalizedPVSystem`, + :py:class:`~pvlib.tracking.SingleAxisTracker`, + and + :py:class:`~pvlib.modelchain.ModelChain`. -* Remove ``pvl_`` from module names. -* Consolidation of similar modules. For example, functions from ``pvl_clearsky_ineichen.py`` and ``pvl_clearsky_haurwitz.py`` have been consolidated into ``clearsky.py``. -* Removed ``Vars=Locals(); Expect...; var=pvl\_tools.Parse(Vars,Expect);`` pattern. Very few tests of input validitity remain. Garbage in, garbage or ``nan`` out. -* Removing unnecssary and sometimes undesired behavior such as setting maximum zenith=90 or airmass=0. Instead, we make extensive use of ``nan`` values. -* Changing function and module names so that they do not conflict. -* Added ``/pvlib/data`` for lookup tables, test, and tutorial data. +Other differences +~~~~~~~~~~~~~~~~~ - -More specific changes -~~~~~~~~~~~~~~~~~~~~~ - -* Add PyEphem option to solar position calculations. -* ``irradiance.py`` has more AOI, projection, and irradiance sum and calculation functions -* Locations are now ``pvlib.location.Location`` objects, not structs. -* Specify time zones using a string from the standard IANA Time Zone Database naming conventions or using a pytz.timezone instead of an integer GMT offset. We may add dateutils support in the future. -* ``clearsky.ineichen`` supports interpolating monthly Linke Turbidities to daily resolution. +* Very few tests of input validitity exist in the Python code. + We believe that the vast majority of these tests were not necessary. + We also make use of Python's robust support for raising and catching + exceptions. +* Removed unnecessary and sometimes undesired behavior such as setting + maximum zenith=90 or airmass=0. Instead, we make extensive use of + ``nan`` values in returned arrays. +* Implemented the NREL solar position calculation algorithm. + Also added a PyEphem option to solar position calculations. +* Specify time zones using a string from the standard IANA Time Zone + Database naming conventions or using a pytz.timezone instead of an + integer GMT offset. +* ``clearsky.ineichen`` supports interpolating monthly + Linke Turbidities to daily resolution. * Instead of requiring effective irradiance as an input, ``pvsystem.sapm`` calculates and returns it based on input POA irradiance, AM, and AOI. +* pvlib-python does not come with as much example data. +* pvlib-python does not currently implement as many algorithms as + PVLIB MATLAB. Documentation ~~~~~~~~~~~~~ -* Using readthedocs for documentation hosting. -* Many typos and formatting errors corrected. -* Documentation source code and tutorials live in ``/`` rather than ``/pvlib/docs``. -* Additional tutorials in ``/docs/tutorials``. - -Testing -~~~~~~~ - -* Tests are cleaner and more thorough. They are still no where near complete. -* Using Coveralls to measure test coverage. -* Using TravisCI for automated testing. -* Using ``nosetests`` for more concise test code. +* Using Sphinx to build the documentation, + including dynamically created inline examples. +* Additional Jupyter tutorials in ``/docs/tutorials``. diff --git a/docs/sphinx/source/conf.py b/docs/sphinx/source/conf.py index a74ea4675d..432ec82845 100644 --- a/docs/sphinx/source/conf.py +++ b/docs/sphinx/source/conf.py @@ -50,6 +50,7 @@ def __getattr__(cls, name): 'sphinx.ext.autodoc', 'sphinx.ext.mathjax', 'sphinx.ext.viewcode', + 'sphinx.ext.intersphinx', 'sphinx.ext.extlinks', 'numpydoc', 'sphinx.ext.autosummary', @@ -77,7 +78,7 @@ def __getattr__(cls, name): # |version| and |release|, also used in various other places throughout the # built documents. # Get the version from the version file -version_file = os.path.join(os.path.dirname(__file__), +version_file = os.path.join(os.path.dirname(__file__), '../../../pvlib/version.py') with open(version_file, 'r') as f: exec(f.read()) @@ -301,3 +302,11 @@ def __getattr__(cls, name): # If true, do not generate a @detailmenu in the "Top" node's menu. #texinfo_no_detailmenu = False + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = { + 'python': ('https://docs.python.org/3.5/', None), + 'pandas': ('http://pandas.pydata.org/pandas-docs/stable/', None), + 'numpy': ('http://docs.scipy.org/doc/numpy/', None), +} + diff --git a/docs/sphinx/source/contributing.rst b/docs/sphinx/source/contributing.rst new file mode 100644 index 0000000000..5087f68e39 --- /dev/null +++ b/docs/sphinx/source/contributing.rst @@ -0,0 +1,89 @@ +.. _contributing: + +Contributing +============ + +Encouraging more people to help develop pvlib-python is essential to our +success. Therefore, we want to make it easy and rewarding for you to +contribute. + + +Easy ways to contribute +----------------------- + +Here are a few ideas for you can contribute, even if you are new to +pvlib-python, git, or Python: + +* Make `GitHub issues `_ + and contribute to the conversation about how to resolve them. +* Read issues and pull requests that other people created and + contribute to the conversation about how to resolve them. +* Improve the documentation and the unit tests. +* Improve the IPython/Jupyter Notebook tutorials or write new ones that + demonstrate how to use pvlib-python in your area of expertise. +* If you have MATLAB experience, you can help us keep pvlib-python + up to date with PVLIB_MATLAB or help us develop common unit tests. + For more, see `Issue #2 `_ + and `Issue #3 `_. +* Tell your friends and colleagues about pvlib-python. +* Add your project to our + `Projects and publications that use pvlib-python wiki + `_. + + +How to contribute new code +-------------------------- + +Contributors to pvlib-python use GitHub's pull requests to add/modify +its source code. The GitHub pull request process can be intimidating for +new users, but you'll find that it becomes straightforward once you use +it a few times. Please let us know if you get stuck at any point in the +process. Here's an outline of the process: + +#. Create a GitHub issue and get initial feedback from users and + maintainers. If the issue is a bug report, please include the + code needed to reproduce the problem. +#. Obtain the latest version of pvlib-python: Fork the pvlib-python + project to your GitHub account, ``git clone`` your fork to your computer. +#. Make some or all of your changes/additions and ``git commit`` them to + your local repository. +#. Share your changes with us via a pull request: ``git push`` your + local changes to your GitHub fork, then go to GitHub make a pull + request. + +The Pandas project maintains an excellent `contributing page +`_ that goes into +detail on each of these steps. Also see GitHub's `Set Up Git +`_ and `Using Pull +Requests `_. + +Note that you do not need to make all of your changes before creating a +pull request. Your pull requests will automatically be updated when you +commit new changes and push them to GitHub. This gives everybody an easy +way to comment on the code and can make the process more efficient. + +We strongly recommend using virtual environments for development. +Virtual environments make it trivial to switch between different +versions of software. This `astropy guide +`_ is a good reference for virtual environments. If +this is your first pull request, don't worry about using a virtual +environment. + +You must include documentation and unit tests for any new or improved +code. We can provide help and advice on this after you start the pull +request. + +The maintainers will follow same procedures, rather than making direct +commits to the main repo. Exceptions may be made for extremely minor +changes, such as fixing documentation typos. + + +This documentation +------------------ +If this documentation is unclear, help us improve it! Consider looking +at `IPython `_, +`pandas `_, and +`Sandia-Labs/PVLIB_Python#33 `_ for inspiration. diff --git a/docs/sphinx/source/index.rst b/docs/sphinx/source/index.rst index dae85e27b8..519609c32b 100644 --- a/docs/sphinx/source/index.rst +++ b/docs/sphinx/source/index.rst @@ -1,56 +1,65 @@ -Welcome to pvlib-python's documentation! +pvlib-python ======================================== -pvlib-python provides a set of documented functions for simulating -the performance of photovoltaic energy systems. -The toolbox was originally developed in MATLAB at -Sandia National Laboratories and it implements many of the -models and methods developed at the Labs. -More information on Sandia Labs PV performance modeling programs -can be found at https://pvpmc.sandia.gov/. - -The source code for pvlib-python is hosted on -`github `_. - -The github page also contains a valuable -`wiki `_ -with information on how you can contribute to pvlib-python development! - -Please see the links above for details on the status of the pvlib-python -project. We are at an early stage in the development of this project, -so expect to see significant API changes in the next few releases. - -This documentation focuses on providing a reference for all of -the modules and functions available in pvlib-python. -For examples of how to use pvlib-python, please see the -`tutorials `_. -Some of the tutorials were written with older -versions of pvlib-python and we would greatly appreciate your -help updating them! - -.. note:: - - This documentation assumes general familiarity with - Python, NumPy, and Pandas. Google searches will yield many - excellent tutorials for these packages. - -Please see our -`PVSC 2014 paper `_ -and -`PVSC 2015 paper `_ -(and the `notebook to reproduce the figures `_) for more information. - -The GitHub wiki also has a page on `Projects and publications that use pvlib python `_ for inspiration and listing of your application. - -There is a :ref:`variable naming convention ` to ensure consistency throughout the library. - -Installation -============ - -1. Follow Pandas' - `instructions `_ - for installing the scientific python stack, including ``pip``. -#. ``pip install pvlib-python`` +pvlib-python provides a set of documented functions for simulating the +performance of photovoltaic energy systems. The toolbox was originally +developed in MATLAB at Sandia National Laboratories and it implements +many of the models and methods developed at the Labs. More information +on Sandia Labs PV performance modeling programs can be found at +https://pvpmc.sandia.gov/. + +The source code for pvlib-python is hosted on `github +`_. + +Please see the :ref:`installation` page for installation help. + +For examples of how to use pvlib-python, please see +:ref:`package_overview` and our `Jupyter Notebook tutorials +`_. The documentation assumes general familiarity with +Python, NumPy, and Pandas. Google searches will yield many +excellent tutorials for these packages. + +The pvlib-python GitHub wiki has a `Projects and publications that use +pvlib python +`_ page for inspiration and listing of your +application. + +There is a :ref:`variable naming convention ` to +ensure consistency throughout the library. + +Citing pvlib-python +=================== + +Many of the contributors to pvlib-python work in institutions where +citation metrics are used in performance or career evaluations. If you +use pvlib-python in a published work, please cite the most appropriate +of: + +* J. S. Stein, “The photovoltaic performance modeling + collaborative (PVPMC),” in Photovoltaic Specialists Conference, 2012. +* R.W. Andrews, J.S. Stein, C. Hansen, and D. Riley, “Introduction + to the open source pvlib for python photovoltaic system + modelling package,” in 40th IEEE Photovoltaic Specialist + Conference, 2014. + (`paper + `_) +* W.F. Holmgren, R.W. Andrews, A.T. Lorenzo, and J.S. Stein, + “PVLIB Python 2015,” in 42nd Photovoltaic Specialists Conference, 2015. + (`paper + `_ and + the `notebook to reproduce the figures + `_) +* J.S. Stein, W.F. Holmgren, J. Forbess, and C.W. Hansen, + "PVLIB: Open Source Photovoltaic Performance Modeling Functions + for Matlab and Python," in 43rd Photovoltaic Specialists Conference, 2016. +* W.F. Holmgren and D.G. Groenendyk, + "An Open Source Solar Power Forecasting Tool Using PVLIB-Python," + in 43rd Photovoltaic Specialists Conference, 2016. + +Specific released versions of pvlib-python can be cited using their +`Zenodo DOI `_. Contents @@ -58,10 +67,12 @@ Contents .. toctree:: :maxdepth: 2 - - self + package_overview whatsnew + installation + contributing + timetimezones modules classes comparison_pvlib_matlab @@ -72,6 +83,4 @@ Indices and tables ================== * :ref:`genindex` -* :ref:`modindex` * :ref:`search` - diff --git a/docs/sphinx/source/installation.rst b/docs/sphinx/source/installation.rst new file mode 100644 index 0000000000..9a8af0b792 --- /dev/null +++ b/docs/sphinx/source/installation.rst @@ -0,0 +1,82 @@ +.. _installation: + +Installation +============ + +Installing pvlib-python is similar to installing most other scientific +python packages. The instructions below describe how to install +pvlib-python under a few different conditions. Most of the information +on the `Pandas installation page +`_ is also +applicable to pvlib-python. + +If you have Python +------------------ + +To obtain the most recent stable release of pvlib-python, use +`conda `_ or `pip `_:: + + conda install -c pvlib pvlib + + pip install pvlib + +If your system complains that you don't have access privileges or asks +for a password then you're probably trying to install pvlib into your +system's Python distribution. This is usually a bad idea and you should +instead follow the :ref:`nopython` instructions below. + +.. _nopython: + +If you don't have Python +------------------------ + +There are many ways to install Python on your system, but the Anaconda +Scientific Python distribution provides by far the easiest way for new +users to get started. Anaconda includes all of the popular libraries +that you'll need for pvlib, including Pandas, NumPy, and SciPy. +"Anaconda installs cleanly into a single directory, does not require +Administrator or root privileges, does not affect other Python installs +on your system, or interfere with OSX Frameworks." -Anaconda +Documentation. + +#. Install the full Anaconda Scientific Python distribution available + `here `_ +#. Install pvlib: ``conda install -c pvlib pvlib`` + +If you have trouble, see the `Anaconda +FAQ `_, Google your error +messages, or make a new issue on our `Issues +page `_. + + +Working at the bleeding edge +---------------------------- + +We strongly recommend working in a `virtual environment +`_ if you're going to use the development versions +of the code. There are many ways to use virtual environments in Python, +but Anaconda again provides the easiest solution: + +#. Create a new conda environment for pvlib and pre-install a + handful of packages into the environment: + ``conda create --name pvlibdev python pandas scipy`` +#. Activate the new environment: ``source activate pvlibdev`` +#. Install the latest development version of pvlib: + + #. If you don't plan to modify the source-code: + ``pip install git+https://github.com/pvlib/pvlib-python.git`` + #. If you do plan to modify the source code: + Use the GitHub GUI application or git command-line tool to + clone this repository to your computer, then navigate your + command-line to the top-level pvlib-python directory, + then ``pip install -e .`` + +#. You may also consider installing additional packages into your + development environment: + ``conda install jupyter ipython seaborn nose flake8`` + +The `conda documentation +`_ has more information +on how to use virtual environments. You can also add ``-h`` to most +conda commands to get help (e.g. ``conda -h`` or ``conda env -h``) diff --git a/docs/sphinx/source/package_overview.rst b/docs/sphinx/source/package_overview.rst index 5e5d6eacbe..a2c333a92f 100644 --- a/docs/sphinx/source/package_overview.rst +++ b/docs/sphinx/source/package_overview.rst @@ -14,6 +14,8 @@ there are modelers of PV systems, so pvlib-python provides several modeling paradigms. +.. _modeling-paradigms: + Modeling paradigms ------------------ diff --git a/docs/sphinx/source/timetimezones.rst b/docs/sphinx/source/timetimezones.rst new file mode 100644 index 0000000000..a7d0f20084 --- /dev/null +++ b/docs/sphinx/source/timetimezones.rst @@ -0,0 +1,383 @@ +.. _timetimezones: + +Time and time zones +=================== + +Dealing with time and time zones can be a frustrating experience in any +programming language and for any application. pvlib-python relies on +:py:mod:`pandas` and `pytz `_ to handle +time and time zones. Therefore, the vast majority of the information in +this document applies to any time series analysis using pandas and is +not specific to pvlib-python. + +General functionality +--------------------- + +pvlib makes extensive use of pandas due to its excellent time series +functionality. Take the time to become familiar with pandas' `Time +Series / Date functionality page +`_. +It is also worthwhile to become familiar with pure Python's +:py:mod:`python:datetime` module, although we usually recommend +using the corresponding pandas functionality where possible. + +First, we'll import the libraries that we'll use to explore the basic +time and time zone functionality in python and pvlib. + +.. ipython:: python + + import datetime + import pandas as pd + import pytz + +Finding a time zone +******************* + +pytz is based on the Olson time zone database. You can obtain a list of +all valid time zone strings with ``pytz.all_timezones``. It's a long +list, so we only print every 20th time zone. + +.. ipython:: python + + len(pytz.all_timezones) + pytz.all_timezones[::20] + +Wikipedia's `List of tz database time zones +`_ is also +good reference. + +The ``pytz.country_timezones`` function is useful, too. + +.. ipython:: python + + pytz.country_timezones('US') + +And don't forget about Python's :py:func:`python:filter` function. + +.. ipython:: python + + list(filter(lambda x: 'GMT' in x, pytz.all_timezones)) + +Note that while pytz has ``'EST'`` and ``'MST'``, it does not have +``'PST'``. Use ``'Etc/GMT+8'`` instead, or see :ref:`fixedoffsets`. + +Timestamps +********** + +:py:class:`pandas.Timestamp` and :py:class:`pandas.DatetimeIndex` +can be created in many ways. Here we focus on the time zone issues +surrounding them; see the pandas documentation for more information. + +First, create a time zone naive pandas.Timestamp. + +.. ipython:: python + + pd.Timestamp('2015-1-1 00:00') + +You can specify the time zone using the ``tz`` keyword argument or the +``tz_localize`` method of Timestamp and DatetimeIndex objects. + +.. ipython:: python + + pd.Timestamp('2015-1-1 00:00', tz='America/Denver') + pd.Timestamp('2015-1-1 00:00').tz_localize('America/Denver') + +Localized Timestamps can be converted from one time zone to another. + +.. ipython:: python + + midnight_mst = pd.Timestamp('2015-1-1 00:00', tz='America/Denver') + corresponding_utc = midnight_mst.tz_convert('UTC') # returns a new Timestamp + corresponding_utc + +It does not make sense to convert a time stamp that has not been +localized, and pandas will raise an exception if you try to do so. + +.. ipython:: python + :okexcept: + + midnight = pd.Timestamp('2015-1-1 00:00') + midnight.tz_convert('UTC') + +The difference between ``tz_localize`` and ``tz_convert`` is a common +source of confusion for new users. Just remember: localize first, +convert later. + +Daylight savings time +********************* + +Some time zones are aware of daylight savings time and some are not. For +example the winter time results are the same for US/Mountain and MST, +but the summer time results are not. + +Note the UTC offset in winter... + +.. ipython:: python + + pd.Timestamp('2015-1-1 00:00').tz_localize('US/Mountain') + pd.Timestamp('2015-1-1 00:00').tz_localize('Etc/GMT+7') + +vs. the UTC offset in summer... + +.. ipython:: python + + pd.Timestamp('2015-6-1 00:00').tz_localize('US/Mountain') + pd.Timestamp('2015-6-1 00:00').tz_localize('Etc/GMT+7') + +pandas and pytz make this time zone handling possible because pandas +stores all times as integer nanoseconds since January 1, 1970. +Here is the pandas time representation of the integers 1 and 1e9. + +.. ipython:: python + + pd.Timestamp(1) + pd.Timestamp(1e9) + +So if we specify times consistent with the specified time zone, pandas +will use the same integer to represent them. + +.. ipython:: python + + # US/Mountain + pd.Timestamp('2015-6-1 01:00', tz='US/Mountain').value + + # MST + pd.Timestamp('2015-6-1 00:00', tz='Etc/GMT+7').value + + # Europe/Berlin + pd.Timestamp('2015-6-1 09:00', tz='Europe/Berlin').value + + # UTC + pd.Timestamp('2015-6-1 07:00', tz='UTC').value + + # UTC + pd.Timestamp('2015-6-1 07:00').value + +It's ultimately these integers that are used when calculating quantities +in pvlib such as solar position. + +As stated above, pandas will assume UTC if you do not specify a time +zone. This is dangerous, and we recommend using localized timeseries, +even if it is UTC. + + +.. _fixedoffsets: + +Fixed offsets +************* + +The ``'Etc/GMT*'`` time zones mentioned above provide fixed offset +specifications, but watch out for the counter-intuitive sign convention. + +.. ipython:: python + + pd.Timestamp('2015-1-1 00:00', tz='Etc/GMT-2') + +Fixed offset time zones can also be specified as offset minutes +from UTC using ``pytz.FixedOffset``. + +.. ipython:: python + + pd.Timestamp('2015-1-1 00:00', tz=pytz.FixedOffset(120)) + +You can also specify the fixed offset directly in the ``tz_localize`` +method, however, be aware that this is not documented and that the +offset must be in seconds, not minutes. + +.. ipython:: python + + pd.Timestamp('2015-1-1 00:00', tz=7200) + +Yet another way to specify a time zone with a fixed offset is by using +the string formulation. + +.. ipython:: python + + pd.Timestamp('2015-1-1 00:00+0200') + + +Native Python objects +********************* + +Sometimes it's convenient to use native Python +:py:class:`python:datetime.date` and +:py:class:`python:datetime.datetime` objects, so we demonstrate their +use next. pandas Timestamp objects can also be created from time zone +aware or naive +:py:class:`python:datetime.datetime` objects. The behavior is as +expected. + +.. ipython:: python + + # tz naive python datetime.datetime object + naive_python_dt = datetime.datetime(2015, 6, 1, 0) + + # tz naive pandas Timestamp object + pd.Timestamp(naive_python_dt) + + # tz aware python datetime.datetime object + aware_python_dt = pytz.timezone('US/Mountain').localize(naive_python_dt) + + # tz aware pandas Timestamp object + pd.Timestamp(aware_python_dt) + +One thing to watch out for is that python +:py:class:`python:datetime.date` objects gain time information when +passed to ``Timestamp``. + +.. ipython:: python + + # tz naive python datetime.date object (no time info) + naive_python_date = datetime.date(2015, 6, 1) + + # tz naive pandas Timestamp object (time=midnight) + pd.Timestamp(naive_python_date) + +You cannot localize a native Python date object. + +.. ipython:: python + :okexcept: + + # fail + pytz.timezone('US/Mountain').localize(naive_python_date) + + +pvlib-specific functionality +---------------------------- + +.. note:: + + This section applies to pvlib >= 0.3. Version 0.2 of pvlib used a + ``Location`` object's ``tz`` attribute to auto-magically correct for + some time zone issues. This behavior was counter-intuitive to many + users and was removed in version 0.3. + +How does this general functionality interact with pvlib? Perhaps the two +most common places to get tripped up with time and time zone issues in +solar power analysis occur during data import and solar position +calculations. + +Data import +*********** + +Let's first examine how pvlib handles time when it imports a TMY3 file. + +.. ipython:: python + + import os + import inspect + import pvlib + + # some gymnastics to find the example file + pvlib_abspath = os.path.dirname(os.path.abspath(inspect.getfile(pvlib))) + file_abspath = os.path.join(pvlib_abspath, 'data', '703165TY.csv') + tmy3_data, tmy3_metadata = pvlib.tmy.readtmy3(file_abspath) + + tmy3_metadata + +The metadata has a ``'TZ'`` key with a value of ``-9.0``. This is the +UTC offset in hours in which the data has been recorded. The +:py:func:`~pvlib.tmy.readtmy3` function read the data in the file, +created a :py:class:`~pandas.DataFrame` with that data, and then +localized the DataFrame's index to have this fixed offset. Here, we +print just a few of the rows and columns of the large dataframe. + +.. ipython:: python + + tmy3_data.index.tz + + tmy3_data.ix[0:3, ['GHI', 'DNI', 'AOD']] + +The :py:func:`~pvlib.tmy.readtmy2` function also returns a DataFrame +with a localized DatetimeIndex. + +Solar position +************** + +The correct solar position can be immediately calculated from the +DataFrame's index since the index has been localized. + +.. ipython:: python + :suppress: + + import seaborn as sns + sns.set_color_codes() + +.. ipython:: python + + solar_position = pvlib.solarposition.get_solarposition(tmy3_data.index, + tmy3_metadata['latitude'], + tmy3_metadata['longitude']) + + ax = solar_position.ix[0:24, ['apparent_zenith', 'apparent_elevation', 'azimuth']].plot() + + ax.legend(loc=1); + ax.axhline(0, color='darkgray'); # add 0 deg line for sunrise/sunset + ax.axhline(180, color='darkgray'); # add 180 deg line for azimuth at solar noon + ax.set_ylim(-60, 200); # zoom in, but cuts off full azimuth range + ax.set_xlabel('Local time ({})'.format(solar_position.index.tz)); + @savefig solar-position.png width=6in + ax.set_ylabel('(degrees)'); + +`According to the US Navy +`_, +on January 1, 1997 at Sand Point, Alaska, sunrise was at 10:09 am, solar +noon was at 1:46 pm, and sunset was at 5:23 pm. This is consistent with +the data plotted above (and depressing). + +Solar position (assumed UTC) +**************************** + +What if we had a DatetimeIndex that was not localized, such as the one +below? The solar position calculator will assume UTC time. + +.. ipython:: python + + index = pd.DatetimeIndex(start='1997-01-01 01:00', freq='1h', periods=24) + index + + solar_position_notz = pvlib.solarposition.get_solarposition(index, + tmy3_metadata['latitude'], + tmy3_metadata['longitude']) + + ax = solar_position_notz.ix[0:24, ['apparent_zenith', 'apparent_elevation', 'azimuth']].plot() + + ax.legend(loc=1); + ax.axhline(0, color='darkgray'); # add 0 deg line for sunrise/sunset + ax.axhline(180, color='darkgray'); # add 180 deg line for azimuth at solar noon + ax.set_ylim(-60, 200); # zoom in, but cuts off full azimuth range + ax.set_xlabel('Time (UTC)'); + @savefig solar-position-nolocal.png width=6in + ax.set_ylabel('(degrees)'); + +This looks like the plot above, but shifted by 9 hours. + +Solar position (calculate and convert) +************************************** + +In principle, one could localize the tz-naive solar position data to +UTC, and then convert it to the desired time zone. + +.. ipython:: python + + fixed_tz = pytz.FixedOffset(tmy3_metadata['TZ'] * 60) + solar_position_hack = solar_position_notz.tz_localize('UTC').tz_convert(fixed_tz) + + solar_position_hack.index + + ax = solar_position_hack.ix[0:24, ['apparent_zenith', 'apparent_elevation', 'azimuth']].plot() + + ax.legend(loc=1); + ax.axhline(0, color='darkgray'); # add 0 deg line for sunrise/sunset + ax.axhline(180, color='darkgray'); # add 180 deg line for azimuth at solar noon + ax.set_ylim(-60, 200); # zoom in, but cuts off full azimuth range + ax.set_xlabel('Local time ({})'.format(solar_position_hack.index.tz)); + @savefig solar-position-hack.png width=6in + ax.set_ylabel('(degrees)'); + +Note that the time has been correctly localized and converted, however, +the calculation bounds still correspond to the original assumed-UTC range. + +For this and other reasons, we recommend that users supply time zone +information at the beginning of a calculation rather than localizing and +converting the results at the end of a calculation. diff --git a/docs/sphinx/source/whatsnew/v0.3.0.txt b/docs/sphinx/source/whatsnew/v0.3.0.txt index 22c09c0c09..1afb25cdf2 100644 --- a/docs/sphinx/source/whatsnew/v0.3.0.txt +++ b/docs/sphinx/source/whatsnew/v0.3.0.txt @@ -44,6 +44,9 @@ Enhancements * Added new sections to the documentation: * :ref:`package_overview` (:issue:`93`) + * :ref:`installation` (:issue:`135`) + * :ref:`contributing` (:issue:`46`) + * :ref:`timetimezones` (:issue:`47`) * :ref:`variables_style_rules` (:issue:`102`) * :ref:`classes` (:issue:`93`) @@ -65,6 +68,8 @@ Enhancements e.g. ``Location.get_airmass``. * Modify ``sapm`` documentation to clarify that it does not work with the CEC database. (:issue:`122`) +* Adds citation information to the documentation. (:issue:`73`) +* Updates the :ref:`comparison_pvlib_matlab` documentation. (:issue:`116`) Bug fixes @@ -87,3 +92,6 @@ Contributors * pyElena21 * DaCoEx * Uwe Krien + +Will Holmgren, Jessica Forbess, bmu, Cliff Hansen, Tony Lorenzo, +Uwe Krien, and bt- contributed to the object model discussion.