Skip to content

TEMPERATURE_MODEL_PARAMETERS is undocumented #939

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mikofski opened this issue Mar 20, 2020 · 2 comments · Fixed by #1036
Closed

TEMPERATURE_MODEL_PARAMETERS is undocumented #939

mikofski opened this issue Mar 20, 2020 · 2 comments · Fixed by #1036
Labels
Milestone

Comments

@mikofski
Copy link
Member

mikofski commented Mar 20, 2020

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

@wholmgren wholmgren added the api label Mar 21, 2020
@wholmgren wholmgren added this to the 0.7.2 milestone Mar 21, 2020
@wholmgren
Copy link
Member

wholmgren commented Mar 21, 2020

Thanks @mikofski for the thorough suggestion. +1 for documenting the dict, -1 for the class.

autodata is new to me. Let's get it working with this dict and then think about other places it could be used.

@cwhanse cwhanse modified the milestones: 0.7.2, 0.7.3 Apr 16, 2020
@wholmgren wholmgren modified the milestones: 0.7.3, 0.8.0 Jul 17, 2020
@wholmgren
Copy link
Member

@mikofski can you make a PR with this for 0.8 (next few weeks)? If not maybe @kanderso-nrel ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants