Repository: pvlib/pvlib-python
Pull request #208 (2016-07-07 22:29:42)

updated first_solar_spectral_correction within atmosphere.py
I updated first_solar_spectral_correction within atmosphere.py to account for changes in model that are reflected in the IEEE PVSC 43 publication. I also added data flags/filters in order to make sure that the function doesn't "blow up" when given extraordinary inputs.

Minimum precipitable water floor is set to 0.1cm. This presents the function from going toward -Inf as precipitable water goes to toward zero.

An absolute airmass ceiling is placed at AM = 10. This prevents function from destabilizing at very high AM. AM > 10 occur very close to sunset/sunrise when irradiance levels are very low.

Warning flags are now printed if Pwat is really high (above 8 cm), or if absolute air mass is very low (below .58)

wholmgren: Thanks, @MLEEFS. Looks good, just a few simple things...

It's best to replace the print statements with [warnings.warn](https://docs.python.org/3.5/library/warnings.html#warnings.warn). This way, users can silence the warnings if they want to. I am ambivalent about input warnings for pvlib python, but if you want to use them, that's the way to do it.

You should also replace the limit setting with the [np.maximum](http://docs.scipy.org/doc/numpy/reference/generated/numpy.maximum.html) and np.minimum functions. For example:

```
pw = np.maximum(pw, 0.1)
```

These numpy functions should be much faster than the list comprehensions and I think they're more readable.

I'm a little surprised to see that the tests still passed without any modification, so your changes to the coefficients must amount to pretty small changes in output over the tested range (1-5 cm and 1-5 airmasses). 
MLEEFS: Hi @wholmgren ,

I made the changes you requested. Can you confirm that they have been made? I am still getting used to the mechanics of GIT.
MLEEFS: the "bonus" lines of code should be removed

Patch:
diff --git a/docs/environment.yml b/docs/environment.yml
index 2fd1519..ed7c402 100644
--- a/docs/environment.yml
+++ b/docs/environment.yml
@@ -1,6 +1,7 @@
-name: pvlib
+name: pvlibdocs
 dependencies:
     - python=2.7
+    - mock  # needed for local python 2.7 builds
     - numpy
     - scipy
     - pandas
@@ -8,7 +9,10 @@ dependencies:
     - ephem
     - numba
     - ipython=4.0.1
-    - sphinx
+    - ipywidgets
     - numpydoc
     - matplotlib
-    - seaborn
\ No newline at end of file
+    - seaborn
+    - sphinx=1.3.5  # same versions as rtd
+    - sphinx_rtd_theme=0.1.7
+    - docutils=0.12
diff --git a/docs/sphinx/source/classes.rst b/docs/sphinx/source/classes.rst
index f1fc154..ccda434 100644
--- a/docs/sphinx/source/classes.rst
+++ b/docs/sphinx/source/classes.rst
@@ -17,6 +17,7 @@ Location
     :members:
     :undoc-members:
     :show-inheritance:
+    :noindex:
 
 PVSystem
 --------
@@ -24,6 +25,7 @@ PVSystem
     :members:
     :undoc-members:
     :show-inheritance:
+    :noindex:
 
 ModelChain
 ----------
@@ -31,6 +33,7 @@ ModelChain
     :members:
     :undoc-members:
     :show-inheritance:
+    :noindex:
 
 LocalizedPVSystem
 -----------------
@@ -38,6 +41,7 @@ LocalizedPVSystem
     :members:
     :undoc-members:
     :show-inheritance:
+    :noindex:
 
 SingleAxisTracker
 -----------------
@@ -45,6 +49,7 @@ SingleAxisTracker
     :members:
     :undoc-members:
     :show-inheritance:
+    :noindex:
 
 LocalizedSingleAxisTracker
 --------------------------
@@ -52,4 +57,5 @@ LocalizedSingleAxisTracker
     :members:
     :undoc-members:
     :show-inheritance:
+    :noindex:
 
diff --git a/docs/sphinx/source/index.rst b/docs/sphinx/source/index.rst
index caa171f..11af074 100644
--- a/docs/sphinx/source/index.rst
+++ b/docs/sphinx/source/index.rst
@@ -46,11 +46,11 @@ of:
   modelling package,” in 40th IEEE Photovoltaic Specialist
   Conference, 2014.
   (`paper
-  <http://energy.sandia.gov/wp/wp-content/gallery/uploads/PV_LIB_Python_final_SAND2014-18444C.pdf>`_)
+  <http://energy.sandia.gov/wp/wp-content/gallery/uploads/PV_LIB_Python_final_SAND2014-18444C.pdf>`__)
 * W.F. Holmgren, R.W. Andrews, A.T. Lorenzo, and J.S. Stein,
   “PVLIB Python 2015,” in 42nd Photovoltaic Specialists Conference, 2015.
   (`paper
-  <https://github.com/pvlib/pvsc2015/blob/master/pvlib_pvsc_42.pdf>`_ and
+  <https://github.com/pvlib/pvsc2015/blob/master/pvlib_pvsc_42.pdf>`__ and
   the `notebook to reproduce the figures
   <http://nbviewer.ipython.org/github/pvlib/pvsc2015/blob/master/paper.ipynb>`_)
 * J.S. Stein, W.F. Holmgren, J. Forbess, and C.W. Hansen,
diff --git a/docs/sphinx/source/whatsnew/v0.4.0.txt b/docs/sphinx/source/whatsnew/v0.4.0.txt
index 719c314..d5adb58 100644
--- a/docs/sphinx/source/whatsnew/v0.4.0.txt
+++ b/docs/sphinx/source/whatsnew/v0.4.0.txt
@@ -27,12 +27,15 @@ Enhancements
 Bug fixes
 ~~~~~~~~~
 
+* dirint function yielded the wrong results for non-sea-level pressures.
+  Fixed. (:issue:`212`)
 
 
 Documentation
 ~~~~~~~~~~~~~
 
 * Added new terms to the variables documentation. (:issue:`195`)
+* Fix documentation build warnings. (:issue:`210`)
 
 
 Other
diff --git a/pvlib/atmosphere.py b/pvlib/atmosphere.py
index b56730d..494e0dc 100644
--- a/pvlib/atmosphere.py
+++ b/pvlib/atmosphere.py
@@ -6,6 +6,7 @@ absolute airmass and to determine pressure from altitude or vice versa.
 from __future__ import division
 
 import numpy as np
+from warnings import warn
 
 APPARENT_ZENITH_MODELS = ('simple', 'kasten1966', 'kastenyoung1989',
                           'gueymard1993', 'pickering2002')
@@ -339,7 +340,7 @@ def first_solar_spectral_correction(pw, airmass_absolute, module_type=None,
     .. math::
 
         M = c_1 + c_2*AMa  + c_3*Pwat  + c_4*AMa^.5
-            + c_5*Pwat^.5 + c_6*AMa/Pwat
+            + c_5*Pwat^.5 + c_6*AMa/Pwat^.5
 
     Default coefficients are determined for several cell types with
     known quantum efficiency curves, by using the Simple Model of the
@@ -348,7 +349,7 @@ def first_solar_spectral_correction(pw, airmass_absolute, module_type=None,
     Pwat where:
 
        * 0.5 cm <= Pwat <= 5 cm
-       * 0.8 <= AMa <= 4.75 (Pressure of 800 mbar and 1.01 <= AM <= 6)
+       * 1.0 <= AMa <= 5.0 
        * Spectral range is limited to that of CMP11 (280 nm to 2800 nm)
        * spectrum simulated on a plane normal to the sun
        * All other parameters fixed at G173 standard
@@ -358,14 +359,14 @@ def first_solar_spectral_correction(pw, airmass_absolute, module_type=None,
     applied to fit Eq. 1 to determine the coefficients for each module.
 
     Based on the PVLIB Matlab function ``pvl_FSspeccorr`` by Mitchell
-    Lee and Alex Panchula, at First Solar, 2015.
+    Lee and Alex Panchula, at First Solar, 2016 [2]_.
 
     Parameters
     ----------
     pw : array-like
         atmospheric precipitable water (cm).
 
-    airmass_absolute :
+    airmass_absolute : array-like
         absolute (pressure corrected) airmass.
 
     module_type : None or string
@@ -380,7 +381,7 @@ def first_solar_spectral_correction(pw, airmass_absolute, module_type=None,
 
         The module used to calculate the spectral correction
         coefficients corresponds to the Mult-crystalline silicon
-        Manufacturer 2 Model C from [2]_.
+        Manufacturer 2 Model C from [3]_.
 
     coefficients : array-like
         allows for entry of user defined spectral correction
@@ -406,20 +407,55 @@ def first_solar_spectral_correction(pw, airmass_absolute, module_type=None,
     .. [1] Gueymard, Christian. SMARTS2: a simple model of the atmospheric
        radiative transfer of sunshine: algorithms and performance
        assessment. Cocoa, FL: Florida Solar Energy Center, 1995.
-
-    .. [2] Marion, William F., et al. User's Manual for Data for Validating
+    .. [2] Lee, Mitchell, and Panchula, Alex. "Spectral Correction for
+       Photovoltaic Module Performance Based on Air Mass and Precipitable 
+       Water." IEEE Photovoltaic Specialists Conference, Portland, 2016 
+    .. [3] Marion, William F., et al. User's Manual for Data for Validating
        Models for PV Module Performance. National Renewable Energy
        Laboratory, 2014. http://www.nrel.gov/docs/fy14osti/61610.pdf
     """
 
+    # --- Screen Input Data ---
+
+    # *** Pwat ***
+    # Replace Pwat Values below 0.1 cm with 0.1 cm to prevent model from
+    # diverging"
+
+    if np.min(pw) < 0.1:
+        pw = np.maximum(pw, 0.1)
+        warn('Exceptionally low Pwat values replaced with 0.1 cm to prevent'+
+        ' model divergence')
+
+
+    # Warn user about Pwat data that is exceptionally high
+    if np.max(pw) > 8:
+        warn('Exceptionally high Pwat values. Check input data:' +
+        ' model may diverge in this range')
+
+
+    # *** AMa ***
+    # Replace Extremely High AM with AM 10 to prevent model divergence
+    # AM > 10 will only occur very close to sunset
+    if np.max(airmass_absolute) > 10: 
+      airmass_absolute = np.minimum(airmass_absolute,10)
+    
+    # Warn user about AMa data that is exceptionally low
+    if np.min(airmass_absolute) < 0.58:
+       warn('Exceptionally low air mass: ' +
+           'model not intended for extra-terrestrial use')
+       # pvl_absoluteairmass(1,pvl_alt2pres(4340)) = 0.58
+       # Elevation of Mina Pirquita, Argentian = 4340 m. Highest elevation city
+       # with population over 50,000.
+    
+
     _coefficients = {}
     _coefficients['cdte'] = (
-        0.87102, -0.040543, -0.00929202, 0.10052, 0.073062, -0.0034187)
+       0.86273, -0.038948, -0.012506, 0.098871, 0.084658, -0.0042948)
     _coefficients['monosi'] = (
-        0.86588, -0.021637, -0.0030218, 0.12081, 0.017514, -0.0012610)
+        0.85914, -0.020880, -0.0058853, 0.12029, 0.026814, -0.0017810)
     _coefficients['xsi'] = _coefficients['monosi']
     _coefficients['polysi'] = (
-        0.84674, -0.028568, -0.0051832, 0.13669, 0.029234, -0.0014207)
+        0.84090, -0.027539, -0.0079224, 0.13570, 0.038024, -0.0021218)
     _coefficients['multisi'] = _coefficients['polysi']
 
     if module_type is not None and coefficients is None:
@@ -435,6 +471,6 @@ def first_solar_spectral_correction(pw, airmass_absolute, module_type=None,
     AMa = airmass_absolute
     modifier = (
         coeff[0] + coeff[1]*AMa  + coeff[2]*pw  + coeff[3]*np.sqrt(AMa) +
-        + coeff[4]*np.sqrt(pw) + coeff[5]*AMa/pw)
+        + coeff[4]*np.sqrt(pw) + coeff[5]*AMa/np.sqrt(pw))
 
     return modifier
diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py
index 44ebfe2..fd4cf3e 100644
--- a/pvlib/irradiance.py
+++ b/pvlib/irradiance.py
@@ -313,14 +313,13 @@ def beam_component(surface_tilt, surface_azimuth,
     return beam
 
 
-# ToDo: how to best structure this function? wholmgren 2014-11-03
 def total_irrad(surface_tilt, surface_azimuth,
                 apparent_zenith, azimuth,
                 dni, ghi, dhi, dni_extra=None, airmass=None,
                 albedo=.25, surface_type=None,
                 model='isotropic',
                 model_perez='allsitescomposite1990', **kwargs):
-    '''
+    r"""
     Determine diffuse irradiance from the sky on a
     tilted surface.
 
@@ -328,6 +327,8 @@ def total_irrad(surface_tilt, surface_azimuth,
 
        I_{tot} = I_{beam} + I_{sky} + I_{ground}
 
+    See the transposition function documentation for details.
+
     Parameters
     ----------
     surface_tilt : float or Series.
@@ -359,15 +360,10 @@ def total_irrad(surface_tilt, surface_azimuth,
 
     Returns
     -------
-    DataFrame with columns ``'poa_global', 'poa_direct',
-    'poa_sky_diffuse', 'poa_ground_diffuse'``.
-
-    References
-    ----------
-    [1] Loutzenhiser P.G. et. al. "Empirical validation of models to compute
-    solar irradiance on inclined surfaces for building energy simulation"
-    2007, Solar Energy vol. 81. pp. 254-267
-    '''
+    irradiance: DataFrame
+        Contains columns ``'poa_global', 'poa_direct',
+        'poa_sky_diffuse', 'poa_ground_diffuse'``.
+    """
 
     pvl_logger.debug('planeofarray.total_irrad()')
 
@@ -415,7 +411,7 @@ def total_irrad(surface_tilt, surface_azimuth,
 
 # ToDo: keep this or not? wholmgren, 2014-11-03
 def globalinplane(aoi, dni, poa_sky_diffuse, poa_ground_diffuse):
-    '''
+    r'''
     Determine the three components on in-plane irradiance
 
     Combines in-plane irradaince compoents from the chosen diffuse translation,
@@ -1474,7 +1470,7 @@ def dirint(ghi, zenith, times, pressure=101325, use_delta_kt_prime=True,
 
     pvl_logger.debug('clearsky.dirint')
 
-    disc_out = disc(ghi, zenith, times)
+    disc_out = disc(ghi, zenith, times, pressure=pressure)
     kt = disc_out['kt']
 
     # Absolute Airmass, per the DISC model


Test patch:
diff --git a/pvlib/test/test_irradiance.py b/pvlib/test/test_irradiance.py
index 23d5d7f..67d3c24 100644
--- a/pvlib/test/test_irradiance.py
+++ b/pvlib/test/test_irradiance.py
@@ -208,7 +208,7 @@ def test_dirint_value():
     pressure = 93193.
     dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure)
     assert_almost_equal(dirint_data.values,
-                        np.array([928.85, 688.26]), 1)
+                        np.array([ 888. ,  683.7]), 1)
 
 
 def test_dirint_nans():
@@ -220,7 +220,7 @@ def test_dirint_nans():
     dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure,
                                     temp_dew=temp_dew)
     assert_almost_equal(dirint_data.values,
-                        np.array([np.nan, np.nan, np.nan, np.nan, 934.2]), 1)
+                        np.array([np.nan, np.nan, np.nan, np.nan, 893.1]), 1)
 
 
 def test_dirint_tdew():
@@ -231,7 +231,7 @@ def test_dirint_tdew():
     dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure,
                                     temp_dew=10)
     assert_almost_equal(dirint_data.values,
-                        np.array([934.06, 640.67]), 1)
+                        np.array([892.9,  636.5]), 1)
 
 def test_dirint_no_delta_kt():
     times = pd.DatetimeIndex(['2014-06-24T12-0700','2014-06-24T18-0700'])
@@ -241,7 +241,7 @@ def test_dirint_no_delta_kt():
     dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure,
                                     use_delta_kt_prime=False)
     assert_almost_equal(dirint_data.values,
-                        np.array([901.56, 674.87]), 1)
+                        np.array([861.9,  670.4]), 1)
 
 def test_dirint_coeffs():
     coeffs = irradiance._get_dirint_coeffs()