Skip to content

TEMPERATURE_MODEL_PARAMETERS is undocumented #939

Closed
@mikofski

Description

@mikofski

Is your feature request related to a problem? Please describe.
TEMPERATURE_MODEL_PARAMETERS is mentioned several times in the docs, but it isn't published in the api

Describe the solution you'd like
add a docstring after the constant definition in temperature.py like this (exact wording tbd):

TEMPERATURE_MODEL_PARAMETERS = {
    'sapm': {
        'open_rack_glass_glass': {'a': -3.47, 'b': -.0594, 'deltaT': 3},
        'close_mount_glass_glass': {'a': -2.98, 'b': -.0471, 'deltaT': 1},
        'open_rack_glass_polymer': {'a': -3.56, 'b': -.0750, 'deltaT': 3},
        'insulated_back_glass_polymer': {'a': -2.81, 'b': -.0455, 'deltaT': 0},
    },
    'pvsyst': {'freestanding': {'u_c': 29.0, 'u_v': 0},
               'insulated': {'u_c': 15.0, 'u_v': 0}}
}
"""Dictionary of temperature parameters organized by model.

There are keys for each model at the top level. Currently there are two models,
``sapm`` for the Sandia Array Performance Model, and ``pvsyst``. Each model has
a dictionary of configurations with a dictionary of the model parameters
associated with it. Retrieve a parameters by indexing the model and
configuration by name.

Example
-------
Retrieve the open rack glass-polymer configuration for SAPM::

    from pvlib.temperature import TEMPERATURE_MODEL_PARAMS
    temp_params = TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_polymer']
"""

Then somewhere in the docs add an autodata directive to publish the constant data to the api, like this:

Temperature Model Parameters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. currentmodule:: pvlib.temperature
.. autodata:: TEMPERATURE_MODEL_PARAMETERS
   :annotation:

note: remove :annotation: to show the value of the dictionary

depending on where it goes, you might have to return the module namespace to whatever it was before this entry using something like this:

.. currentmodule:: pvlib

to return it to pvlib for example if this was in api.rst

renders like this:
image

And now it's in the index
image

and can be referenced everywhere in the docs using:

:data:`~pvlib.temperature.TEMPERATURE_MODEL_PARAMETERS`

Ideas for where to put it?

  • in api.rst in the subsection called "PV Temperature Models" part of "PV Modeling"
  • in pvsystem.rst at the end after SAT, in a new section called "temperature"
  • huh?

Describe alternatives you've considered

  • instead of using a dictionary, use a constant class and then add it to the temperature section of api.rst after the Faiman model, here's an example:
class _IndexAttrMeta(type):
    """private meta class to index class attributes like a dictionary"""
    def __getitem__(self, item):
        # retrieve items by index like a dictionary
        return getattr(self, str(item).lower())


class TEMPERATURE_MODEL_PARAMETERS(metaclass=_IndexAttrMeta):
    """Dictionary of temperature parameters organized by model.

    There are keys for each model at the top level. Currently there are two models,
    ``sapm`` for the Sandia Array Performance Model, and ``pvsyst``. Each model has
    a dictionary of configurations with a dictionary of the model parameters
    associated with it. Retrieve a parameters by indexing the model and
    configuration by name.

    Example
    -------
    Retrieve the open rack glass-polymer configuration for SAPM::

        from pvlib.temperature import TEMPERATURE_MODEL_PARAMS
        temp_params = TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_polymer']
    """
    # NOTE: only Python-2 uses __metaclass__,
    # Python-3 passes this to the class as an argument,
    # see: https://docs.python.org/3/library/2to3.html#2to3fixer-metaclass
    # __metaclass__ = _IndexAttrMeta

    #: Sandia Array Performance Model
    sapm = {
        'open_rack_glass_glass': {'a': -3.47, 'b': -.0594, 'deltaT': 3},
        'close_mount_glass_glass': {'a': -2.98, 'b': -.0471, 'deltaT': 1},
        'open_rack_glass_polymer': {'a': -3.56, 'b': -.0750, 'deltaT': 3},
        'insulated_back_glass_polymer': {'a': -2.81, 'b': -.0455, 'deltaT': 0}}
    #: PVSyst model
    pvsyst = {'freestanding': {'u_c': 29.0, 'u_v': 0},
              'insulated': {'u_c': 15.0, 'u_v': 0}}

So this works just like it did before:

In [1]: from pvlib.temperature import TEMPERATURE_MODEL_PARAMETERS

In [2]: TEMPERATURE_MODEL_PARAMETERS['sapm']
Out[2]:
{'open_rack_glass_glass': {'a': -3.47, 'b': -0.0594, 'deltaT': 3},
 'close_mount_glass_glass': {'a': -2.98, 'b': -0.0471, 'deltaT': 1},
 'open_rack_glass_polymer': {'a': -3.56, 'b': -0.075, 'deltaT': 3},
 'insulated_back_glass_polymer': {'a': -2.81, 'b': -0.0455, 'deltaT': 0}}

In [3]: TEMPERATURE_MODEL_PARAMETERS['pvsyst']
Out[3]: {'freestanding': {'u_c': 29.0, 'u_v': 0}, 'insulated': {'u_c': 15.0, 'u_v': 0}}

and all of the tests pass

$ pytest pvlib/tests/test_temperature.py
================================================= test session starts =================================================
platform win32 -- Python 3.6.8, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: C:\Users\mikm\Projects, inifile: pytest.ini
plugins: cov-2.8.1, mock-2.0.0, remotedata-0.3.2, rerunfailures-8.0, timeout-1.3.4
collected 14 items

pvlib\tests\test_temperature.py ..............                                                                   [100%]

================================================== warnings summary ===================================================
pvlib\tests\test_temperature.py:5
  C:\Users\mikm\Projects\pvlib-python\pvlib\tests\test_temperature.py:5: FutureWarning: pandas.util.testing is deprecated. Use the functions in the public API at pandas.testing instead.
    from pandas.util.testing import assert_series_equal

-- Docs: https://docs.pytest.org/en/latest/warnings.html
============================================ 14 passed, 1 warning in 0.07s ============================================

Now just add it to api.rst

PV temperature models
---------------------

.. autosummary::
   :toctree: generated/

   temperature.sapm_cell
   temperature.sapm_module
   temperature.pvsyst_cell
   temperature.faiman
   temperature.TEMPERATURE_MODEL_PARAMETERS

and it will be documented on it's own generated page like other functions
image
image

currently, I can't figure out how to remove the __init__ method which is not supposed to be documented, but this isn't my first choice anyway, so if this alternate is the way to go, perhaps someone else can figure out how to remove it?

  • another option would be to just make it a class, but this would require changing TEMPERATURE_MODEL_PARAMETERS usage everywhere to use attributes instead of items, like TEMPERATURE_MODEL_PARAMETERS.sapm. This option is probably the easiest technically, and safest for readability, but requires some grunt work to find all useage and replace indexing with dot notation.
class TEMPERATURE_MODEL_PARAMETERS:
    """Dictionary of temperature parameters organized by model.

    There are keys for each model at the top level. Currently there are two models,
    ``sapm`` for the Sandia Array Performance Model, and ``pvsyst``. Each model has
    a dictionary of configurations with a dictionary of the model parameters
    associated with it. Retrieve a parameters by indexing the model and
    configuration by name.

    Example
    -------
    Retrieve the open rack glass-polymer configuration for SAPM::

        from pvlib.temperature import TEMPERATURE_MODEL_PARAMS
        temp_params = TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_polymer']
    """
    #: Sandia Array Performance Model
    sapm = {
        'open_rack_glass_glass': {'a': -3.47, 'b': -.0594, 'deltaT': 3},
        'close_mount_glass_glass': {'a': -2.98, 'b': -.0471, 'deltaT': 1},
        'open_rack_glass_polymer': {'a': -3.56, 'b': -.0750, 'deltaT': 3},
        'insulated_back_glass_polymer': {'a': -2.81, 'b': -.0455, 'deltaT': 0}}
    #: PVSyst model
    pvsyst = {'freestanding': {'u_c': 29.0, 'u_v': 0},
              'insulated': {'u_c': 15.0, 'u_v': 0}}
  • even a more complicated option would be to figure out how use properties to make the models immutable, but just like __getitem__, the property decorator only acts on instances so you would have to figure out how to add it to a metaclass, which is really going too far now:
class Meta(type):
    @staticmethod
    def bind_geta(a):
        # bind `a` so it doesn't change in the loop
        def geta(self):
            return getattr(self, a)
        # return the bound function `geta`
        return geta
        
    def __getitem__(self, arg):
        return getattr(self, arg)

    def __new__(cls, name, bases, attrs):
        for a in attrs:
            if a.startswith('__'):
                continue
            if not a.startswith('_'):
                # create the property as an attribute of Meta
                setattr(cls, a[1:], property(Meta.bind_geta(a)))
        return super().__new__(cls, name, bases, attrs)


class TEMPERATURE_MODEL_PARAMETERS(metaclass=Meta):
    """Dictionary of temperature parameters organized by model.

    There are keys for each model at the top level. Currently there are two models,
    ``sapm`` for the Sandia Array Performance Model, and ``pvsyst``. Each model has
    a dictionary of configurations with a dictionary of the model parameters
    associated with it. Retrieve a parameters by indexing the model and
    configuration by name.

    Example
    -------
    Retrieve the open rack glass-polymer configuration for SAPM::

        from pvlib.temperature import TEMPERATURE_MODEL_PARAMS
        temp_params = TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_polymer']
    """
    _sapm = {
        'open_rack_glass_glass': {'a': -3.47, 'b': -.0594, 'deltaT': 3},
        'close_mount_glass_glass': {'a': -2.98, 'b': -.0471, 'deltaT': 1},
        'open_rack_glass_polymer': {'a': -3.56, 'b': -.0750, 'deltaT': 3},
        'insulated_back_glass_polymer': {'a': -2.81, 'b': -.0455, 'deltaT': 0}}
    _pvsyst = {'freestanding': {'u_c': 29.0, 'u_v': 0},
              'insulated': {'u_c': 15.0, 'u_v': 0}}

Additional context
see #938

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions