Repository: pvlib/pvlib-python

Issue:
ModelChainResult.cell_temperature is not always a pandas.Series 
For a `ModelChain` configured as below, the `cell_temperature` when running the model chain with a list of data like `ModelChain.run_model([data])` is a tuple with a single number instead of the expected Series

**To Reproduce**
```python
import pandas as pd                                                                                                                                                                                                                                           
from pvlib.location import Location                                                                                                                                                                                                                           
from pvlib.pvsystem import PVSystem, Array                                                                                                                                                                                                                    
from pvlib.modelchain import ModelChain                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                              
data = pd.DataFrame(                                                                                                                                                                                                                                          
    {                                                                                                                                                                                                                                                         
        "ghi": [1100.0, 1101.0],                                                                                                                                                                                                                              
        "dni": [1000.0, 1001],                                                                                                                                                                                                                                
        "dhi": [100.0, 100],                                                                                                                                                                                                                                  
        "temp_air": [25.0, 25],                                                                                                                                                                                                                               
        "wind_speed": [10.0, 10],                                                                                                                                                                                                                             
    },                                                                                                                                                                                                                                                        
    index=pd.DatetimeIndex(                                                                                                                                                                                                                                   
        [pd.Timestamp("2021-01-20T12:00-05:00"), pd.Timestamp("2021-01-20T12:05-05:00")]                                                                                                                                                                      
    ),                                                                                                                                                                                                                                                        
)                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                              
array_params = {                                                                                                                                                                                                                                              
    "name": None,                                                                                                                                                                                                                                             
    "surface_tilt": 20.0,                                                                                                                                                                                                                                     
    "surface_azimuth": 180.0,                                                                                                                                                                                                                                 
    "module": "Canadian_Solar_Inc__CS5P_220M",                                                                                                                                                                                                                
    "albedo": 0.2,                                                                                                                                                                                                                                            
    "temperature_model_parameters": {                                                                                                                                                                                                                         
        "u_c": 29.0,                                                                                                                                                                                                                                          
        "u_v": 0.0,                                                                                                                                                                                                                                           
        "eta_m": 0.1,                                                                                                                                                                                                                                         
        "alpha_absorption": 0.9,                                                                                                                                                                                                                              
    },                                                                                                                                                                                                                                                        
    "strings": 5,                                                                                                                                                                                                                                             
    "modules_per_string": 7,                                                                                                                                                                                                                                  
    "module_parameters": {                                                                                                                                                                                                                                    
        "alpha_sc": 0.004539,                                                                                                                                                                                                                                 
        "gamma_ref": 1.2,                                                                                                                                                                                                                                     
        "mu_gamma": -0.003,                                                                                                                                                                                                                                   
        "I_L_ref": 5.11426,                                                                                                                                                                                                                                   
        "I_o_ref": 8.10251e-10,                                                                                                                                                                                                                               
        "R_sh_ref": 381.254,                                                                                                                                                                                                                                  
        "R_sh_0": 400.0,                                                                                                                                                                                                                                      
        "R_s": 1.06602,                                                                                                                                                                                                                                       
        "cells_in_series": 96,                                                                                                                                                                                                                                
        "R_sh_exp": 5.5,                                                                                                                                                                                                                                      
        "EgRef": 1.121,                                                                                                                                                                                                                                       
    },                                                                                                                                                                                                                                                        
}
inverter_parameters = {                                                                                                                                                                                                                                       
    "Paco": 250.0,                                                                                                                                                                                                                                            
    "Pdco": 259.589,                                                                                                                                                                                                                                          
    "Vdco": 40.0,                                                                                                                                                                                                                                             
    "Pso": 2.08961,                                                                                                                                                                                                                                           
    "C0": -4.1e-05,                                                                                                                                                                                                                                           
    "C1": -9.1e-05,                                                                                                                                                                                                                                           
    "C2": 0.000494,                                                                                                                                                                                                                                           
    "C3": -0.013171,                                                                                                                                                                                                                                          
    "Pnt": 0.075,                                                                                                                                                                                                                                             
}                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                              
location = Location(latitude=33.98, longitude=-115.323, altitude=2300)                                                                                                                                                                                        
                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                              
array_sys = PVSystem(                                                                                                                                                                                                                                         
    arrays=[Array(**array_params)], inverter_parameters=inverter_parameters                                                                                                                                                                                   
)                                                                                                                                                                                                                                                             
assert isinstance(                                                                                                                                                                                                                                            
    ModelChain(array_sys, location, aoi_model="no_loss", spectral_model="no_loss")                                                                                                                                                                            
    .run_model(data)                                                                                                                                                                                                                                          
    .results.cell_temperature,                                                                                                                                                                                                                                
    pd.Series,                                                                                                                                                                                                                                                
)                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                              
array_run = ModelChain(                                                                                                                                                                                                                                       
    array_sys, location, aoi_model="no_loss", spectral_model="no_loss"                                                                                                                                                                                        
).run_model([data])                                                                                                                                                                                                                                           
assert array_run.results.cell_temperature == array_run.cell_temperature                                                                                                                                                                                       
print(array_run.results.cell_temperature)  # (45.329789874660285,)                                                                                                                                                                                            
                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                              
array_params["strings_per_inverter"] = array_params.pop("strings")                                                                                                                                                                                            
standard_sys = PVSystem(**array_params, inverter_parameters=inverter_parameters)                                                                                                                                                                              
assert isinstance(                                                                                                                                                                                                                                            
    ModelChain(standard_sys, location, aoi_model="no_loss", spectral_model="no_loss")                                                                                                                                                                         
    .run_model(data)                                                                                                                                                                                                                                          
    .results.cell_temperature,                                                                                                                                                                                                                                
    pd.Series,                                                                                                                                                                                                                                                
)                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                              
standard_run = ModelChain(                                                                                                                                                                                                                                    
    standard_sys, location, aoi_model="no_loss", spectral_model="no_loss"                                                                                                                                                                                     
).run_model([data])                                                                                                                                                                                                                                           
assert standard_run.results.cell_temperature == standard_run.cell_temperature                                                                                                                                                                                 
print(standard_run.results.cell_temperature)  # (45.329789874660285,)                                                                                                                                                                                         
assert not isinstance(standard_run.results.cell_temperature, pd.Series)                                                                                                                                                                                       
                                                                                
```

**Expected behavior**
`type(ModelChain.run_model([data]).results.cell_temperature) == pd.Series`
__

**Versions:**
 - ``pvlib.__version__``:  0.8.1+4.gba4a199
 - ``pandas.__version__``:  1.1.4
 - python: 3.8.5



Discussion:
Confirmed. This is a bug in `pvlib.modelchain.ModelChain._prepare_temperature` not all inputs are tuples and aren't being converted. @wfvining fyi and lmk if you want to fix it.
Definitely a bug, but I think the correct behavior is slightly different than you expect. Because you pass a list to `ModelChain.run_model()` the output should be a tuple with a single `pd.Series` element.
I agree that passing data as a tuple/list should result in all results being tuples of Series/DataFrames. So perhaps this is a separate bug, but ``array_run.results.total_irrad`` (and other results properties) is a singular `pd.DataFrame` instead of `Tuple[pd.DataFrame]`. 
Yes, that's the problem. We should make those match the type of `ModelChain.weather`. Not sure about this, but we might be able to pass ~`unwrap=isinstance(self.weather, tuple)`~ `unwrap=not isinstance(self.weather, tuple)` to the `PVSystem` methods to accomplish this. Probably won't be that easy though, since `ModelChain` interacts heavily with `PVSystem` attributes like `temperature_model_params` which can't accept that kwarg.
Perhaps a related error is raised when running 
```python
poa_data = pd.DataFrame(
    {
        "poa_global": [1100.0, 1101.0],
        "poa_direct": [1000.0, 1001],
        "poa_diffuse": [100.0, 100],
        "module_temperature": [25.0, 25],
    },
    index=pd.DatetimeIndex(
        [pd.Timestamp("2021-01-20T12:00-05:00"), pd.Timestamp("2021-01-20T12:05-05:00")]
    ),
)

ModelChain(
    array_sys, location, aoi_model="no_loss", spectral_model="no_loss",
).run_model_from_poa([poa_data]) 
```
raises a TypeError here https://github.com/pvlib/pvlib-python/blob/6b92d218653633e366241c31e8836c0072739ece/pvlib/modelchain.py#L1102-L1106
because `self.results.aoi_modifier = 1.0` and `self.results.spectral_modifier = 1.0` 
https://github.com/pvlib/pvlib-python/blob/6b92d218653633e366241c31e8836c0072739ece/pvlib/modelchain.py#L904-L909
Yup, that's the *first* place this error creeps in. That needs to change, as well as the methods that apply loss models from `PVSystem`.  `ModelChain._prep_inputs_fixed()` also needs updating, as well as `_prepate_temperature` itself. I suspect there are one or two other places as well.

I'm kicking myself a bit for not considering this corner case initially. Very glad you found it early on.
One simple solution might be to add some indirection when assigning to `ModelChain.results`. Instead of assigning directly, assignments go through an `_assign_result(field, value)` method that ensures the type of `value` matches `ModelChain.weather`. This might not be the *best* option, but it would not be too difficult to implement.

Patch:
diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py
--- a/pvlib/modelchain.py
+++ b/pvlib/modelchain.py
@@ -268,22 +268,47 @@ class ModelChainResult:
     _T = TypeVar('T')
     PerArray = Union[_T, Tuple[_T, ...]]
     """Type for fields that vary between arrays"""
+
+    # these attributes are used in __setattr__ to determine the correct type.
+    _singleton_tuples: bool = field(default=False)
+    _per_array_fields = {'total_irrad', 'aoi', 'aoi_modifier',
+                         'spectral_modifier', 'cell_temperature',
+                         'effective_irradiance', 'dc', 'diode_params'}
+
     # system-level information
     solar_position: Optional[pd.DataFrame] = field(default=None)
     airmass: Optional[pd.DataFrame] = field(default=None)
     ac: Optional[pd.Series] = field(default=None)
-    # per DC array information
     tracking: Optional[pd.DataFrame] = field(default=None)
+
+    # per DC array information
     total_irrad: Optional[PerArray[pd.DataFrame]] = field(default=None)
     aoi: Optional[PerArray[pd.Series]] = field(default=None)
-    aoi_modifier: Optional[PerArray[pd.Series]] = field(default=None)
-    spectral_modifier: Optional[PerArray[pd.Series]] = field(default=None)
+    aoi_modifier: Optional[PerArray[Union[pd.Series, float]]] = \
+        field(default=None)
+    spectral_modifier: Optional[PerArray[Union[pd.Series, float]]] = \
+        field(default=None)
     cell_temperature: Optional[PerArray[pd.Series]] = field(default=None)
     effective_irradiance: Optional[PerArray[pd.Series]] = field(default=None)
     dc: Optional[PerArray[Union[pd.Series, pd.DataFrame]]] = \
         field(default=None)
     diode_params: Optional[PerArray[pd.DataFrame]] = field(default=None)
 
+    def _result_type(self, value):
+        """Coerce `value` to the correct type according to
+        ``self._singleton_tuples``."""
+        # Allow None to pass through without being wrapped in a tuple
+        if (self._singleton_tuples
+                and not isinstance(value, tuple)
+                and value is not None):
+            return (value,)
+        return value
+
+    def __setattr__(self, key, value):
+        if key in ModelChainResult._per_array_fields:
+            value = self._result_type(value)
+        super().__setattr__(key, value)
+
 
 class ModelChain:
     """
@@ -684,12 +709,9 @@ def infer_dc_model(self):
                              'set the model with the dc_model kwarg.')
 
     def sapm(self):
-        self.results.dc = self.system.sapm(self.results.effective_irradiance,
-                                           self.results.cell_temperature)
-
-        self.results.dc = self.system.scale_voltage_current_power(
-            self.results.dc)
-
+        dc = self.system.sapm(self.results.effective_irradiance,
+                              self.results.cell_temperature)
+        self.results.dc = self.system.scale_voltage_current_power(dc)
         return self
 
     def _singlediode(self, calcparams_model_function):
@@ -745,18 +767,14 @@ def pvwatts_dc(self):
         pvlib.pvsystem.PVSystem.pvwatts_dc
         pvlib.pvsystem.PVSystem.scale_voltage_current_power
         """
-        self.results.dc = self.system.pvwatts_dc(
-            self.results.effective_irradiance, self.results.cell_temperature)
-        if isinstance(self.results.dc, tuple):
-            temp = tuple(
-                pd.DataFrame(s, columns=['p_mp']) for s in self.results.dc)
-        else:
-            temp = pd.DataFrame(self.results.dc, columns=['p_mp'])
-        scaled = self.system.scale_voltage_current_power(temp)
-        if isinstance(scaled, tuple):
-            self.results.dc = tuple(s['p_mp'] for s in scaled)
-        else:
-            self.results.dc = scaled['p_mp']
+        dc = self.system.pvwatts_dc(
+            self.results.effective_irradiance,
+            self.results.cell_temperature,
+            unwrap=False
+        )
+        p_mp = tuple(pd.DataFrame(s, columns=['p_mp']) for s in dc)
+        scaled = self.system.scale_voltage_current_power(p_mp)
+        self.results.dc = _tuple_from_dfs(scaled, "p_mp")
         return self
 
     @property
@@ -866,23 +884,29 @@ def infer_aoi_model(self):
 
     def ashrae_aoi_loss(self):
         self.results.aoi_modifier = self.system.get_iam(
-            self.results.aoi, iam_model='ashrae')
+            self.results.aoi,
+            iam_model='ashrae'
+        )
         return self
 
     def physical_aoi_loss(self):
-        self.results.aoi_modifier = self.system.get_iam(self.results.aoi,
-                                                        iam_model='physical')
+        self.results.aoi_modifier = self.system.get_iam(
+            self.results.aoi,
+            iam_model='physical'
+        )
         return self
 
     def sapm_aoi_loss(self):
-        self.results.aoi_modifier = self.system.get_iam(self.results.aoi,
-                                                        iam_model='sapm')
+        self.results.aoi_modifier = self.system.get_iam(
+            self.results.aoi,
+            iam_model='sapm'
+        )
         return self
 
     def martin_ruiz_aoi_loss(self):
         self.results.aoi_modifier = self.system.get_iam(
-            self.results.aoi,
-            iam_model='martin_ruiz')
+            self.results.aoi, iam_model='martin_ruiz'
+        )
         return self
 
     def no_aoi_loss(self):
@@ -934,13 +958,15 @@ def infer_spectral_model(self):
 
     def first_solar_spectral_loss(self):
         self.results.spectral_modifier = self.system.first_solar_spectral_loss(
-            self.weather['precipitable_water'],
-            self.results.airmass['airmass_absolute'])
+            _tuple_from_dfs(self.weather, 'precipitable_water'),
+            self.results.airmass['airmass_absolute']
+        )
         return self
 
     def sapm_spectral_loss(self):
         self.results.spectral_modifier = self.system.sapm_spectral_loss(
-            self.results.airmass['airmass_absolute'])
+            self.results.airmass['airmass_absolute']
+        )
         return self
 
     def no_spectral_loss(self):
@@ -1066,7 +1092,7 @@ def infer_losses_model(self):
 
     def pvwatts_losses(self):
         self.losses = (100 - self.system.pvwatts_losses()) / 100.
-        if self.system.num_arrays > 1:
+        if isinstance(self.results.dc, tuple):
             for dc in self.results.dc:
                 dc *= self.losses
         else:
@@ -1271,6 +1297,17 @@ def _verify(data, index=None):
             for (i, array_data) in enumerate(data):
                 _verify(array_data, i)
 
+    def _configure_results(self):
+        """Configure the type used for per-array fields in ModelChainResult.
+
+        Must be called after ``self.weather`` has been assigned. If
+        ``self.weather`` is a tuple and the number of arrays in the system
+        is 1, then per-array results are stored as length-1 tuples.
+        """
+        self.results._singleton_tuples = (
+            self.system.num_arrays == 1 and isinstance(self.weather, tuple)
+        )
+
     def _assign_weather(self, data):
         def _build_weather(data):
             key_list = [k for k in WEATHER_KEYS if k in data]
@@ -1286,6 +1323,7 @@ def _build_weather(data):
             self.weather = tuple(
                 _build_weather(weather) for weather in data
             )
+        self._configure_results()
         return self
 
     def _assign_total_irrad(self, data):
@@ -1383,7 +1421,8 @@ def prepare_inputs(self, weather):
             _tuple_from_dfs(self.weather, 'ghi'),
             _tuple_from_dfs(self.weather, 'dhi'),
             airmass=self.results.airmass['airmass_relative'],
-            model=self.transposition_model)
+            model=self.transposition_model
+        )
 
         return self
 
diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py
--- a/pvlib/pvsystem.py
+++ b/pvlib/pvsystem.py
@@ -6,6 +6,7 @@
 from collections import OrderedDict
 import functools
 import io
+import itertools
 import os
 from urllib.request import urlopen
 import numpy as np
@@ -811,8 +812,9 @@ def first_solar_spectral_loss(self, pw, airmass_absolute):
             effective irradiance, i.e., the irradiance that is converted to
             electrical current.
         """
+        pw = self._validate_per_array(pw, system_wide=True)
 
-        def _spectral_correction(array):
+        def _spectral_correction(array, pw):
             if 'first_solar_spectral_coefficients' in \
                     array.module_parameters.keys():
                 coefficients = \
@@ -828,7 +830,9 @@ def _spectral_correction(array):
                 pw, airmass_absolute,
                 module_type, coefficients
             )
-        return tuple(_spectral_correction(array) for array in self.arrays)
+        return tuple(
+            itertools.starmap(_spectral_correction, zip(self.arrays, pw))
+        )
 
     def singlediode(self, photocurrent, saturation_current,
                     resistance_series, resistance_shunt, nNsVth,
@@ -891,29 +895,31 @@ def get_ac(self, model, p_dc, v_dc=None):
         model = model.lower()
         multiple_arrays = self.num_arrays > 1
         if model == 'sandia':
+            p_dc = self._validate_per_array(p_dc)
+            v_dc = self._validate_per_array(v_dc)
             if multiple_arrays:
-                p_dc = self._validate_per_array(p_dc)
-                v_dc = self._validate_per_array(v_dc)
-                inv_fun = inverter.sandia_multi
-            else:
-                inv_fun = inverter.sandia
-            return inv_fun(v_dc, p_dc, self.inverter_parameters)
+                return inverter.sandia_multi(
+                    v_dc, p_dc, self.inverter_parameters)
+            return inverter.sandia(v_dc[0], p_dc[0], self.inverter_parameters)
         elif model == 'pvwatts':
             kwargs = _build_kwargs(['eta_inv_nom', 'eta_inv_ref'],
                                    self.inverter_parameters)
+            p_dc = self._validate_per_array(p_dc)
             if multiple_arrays:
-                p_dc = self._validate_per_array(p_dc)
-                inv_fun = inverter.pvwatts_multi
-            else:
-                inv_fun = inverter.pvwatts
-            return inv_fun(p_dc, self.inverter_parameters['pdc0'], **kwargs)
+                return inverter.pvwatts_multi(
+                    p_dc, self.inverter_parameters['pdc0'], **kwargs)
+            return inverter.pvwatts(
+                p_dc[0], self.inverter_parameters['pdc0'], **kwargs)
         elif model == 'adr':
             if multiple_arrays:
                 raise ValueError(
                     'The adr inverter function cannot be used for an inverter',
                     ' with multiple MPPT inputs')
-            else:
-                return inverter.adr(v_dc, p_dc, self.inverter_parameters)
+            # While this is only used for single-array systems, calling
+            # _validate_per_arry lets us pass in singleton tuples.
+            p_dc = self._validate_per_array(p_dc)
+            v_dc = self._validate_per_array(v_dc)
+            return inverter.adr(v_dc[0], p_dc[0], self.inverter_parameters)
         else:
             raise ValueError(
                 model + ' is not a valid AC power model.',


Test patch:
diff --git a/pvlib/tests/test_modelchain.py b/pvlib/tests/test_modelchain.py
--- a/pvlib/tests/test_modelchain.py
+++ b/pvlib/tests/test_modelchain.py
@@ -1080,6 +1080,54 @@ def test_run_model_from_effective_irradiance_missing_poa(
             (data_complete, data_incomplete))
 
 
+def test_run_model_singleton_weather_single_array(cec_dc_snl_ac_system,
+                                                  location, weather):
+    mc = ModelChain(cec_dc_snl_ac_system, location,
+                    aoi_model="no_loss", spectral_model="no_loss")
+    mc.run_model([weather])
+    assert isinstance(mc.results.total_irrad, tuple)
+    assert isinstance(mc.results.aoi, tuple)
+    assert isinstance(mc.results.aoi_modifier, tuple)
+    assert isinstance(mc.results.spectral_modifier, tuple)
+    assert isinstance(mc.results.effective_irradiance, tuple)
+    assert isinstance(mc.results.dc, tuple)
+    assert isinstance(mc.results.cell_temperature, tuple)
+    assert len(mc.results.cell_temperature) == 1
+    assert isinstance(mc.results.cell_temperature[0], pd.Series)
+
+
+def test_run_model_from_poa_singleton_weather_single_array(
+        sapm_dc_snl_ac_system, location, total_irrad):
+    mc = ModelChain(sapm_dc_snl_ac_system, location,
+                    aoi_model='no_loss', spectral_model='no_loss')
+    ac = mc.run_model_from_poa([total_irrad]).results.ac
+    expected = pd.Series(np.array([149.280238, 96.678385]),
+                         index=total_irrad.index)
+    assert isinstance(mc.results.cell_temperature, tuple)
+    assert len(mc.results.cell_temperature) == 1
+    assert isinstance(mc.results.cell_temperature[0], pd.Series)
+    assert_series_equal(ac, expected)
+
+
+def test_run_model_from_effective_irradiance_weather_single_array(
+        sapm_dc_snl_ac_system, location, weather, total_irrad):
+    data = weather.copy()
+    data[['poa_global', 'poa_diffuse', 'poa_direct']] = total_irrad
+    data['effective_irradiance'] = data['poa_global']
+    mc = ModelChain(sapm_dc_snl_ac_system, location, aoi_model='no_loss',
+                    spectral_model='no_loss')
+    ac = mc.run_model_from_effective_irradiance([data]).results.ac
+    expected = pd.Series(np.array([149.280238, 96.678385]),
+                         index=data.index)
+    assert isinstance(mc.results.cell_temperature, tuple)
+    assert len(mc.results.cell_temperature) == 1
+    assert isinstance(mc.results.cell_temperature[0], pd.Series)
+    assert isinstance(mc.results.dc, tuple)
+    assert len(mc.results.dc) == 1
+    assert isinstance(mc.results.dc[0], pd.DataFrame)
+    assert_series_equal(ac, expected)
+
+
 def poadc(mc):
     mc.results.dc = mc.results.total_irrad['poa_global'] * 0.2
     mc.results.dc.name = None  # assert_series_equal will fail without this
@@ -1324,6 +1372,22 @@ def test_aoi_models(sapm_dc_snl_ac_system, location, aoi_model,
     assert mc.results.ac[1] < 1
 
 
+@pytest.mark.parametrize('aoi_model', [
+    'sapm', 'ashrae', 'physical', 'martin_ruiz'
+])
+def test_aoi_models_singleon_weather_single_array(
+        sapm_dc_snl_ac_system, location, aoi_model, weather):
+    mc = ModelChain(sapm_dc_snl_ac_system, location, dc_model='sapm',
+                    aoi_model=aoi_model, spectral_model='no_loss')
+    mc.run_model(weather=[weather])
+    assert isinstance(mc.results.aoi_modifier, tuple)
+    assert len(mc.results.aoi_modifier) == 1
+    assert isinstance(mc.results.ac, pd.Series)
+    assert not mc.results.ac.empty
+    assert mc.results.ac[0] > 150 and mc.results.ac[0] < 200
+    assert mc.results.ac[1] < 1
+
+
 def test_aoi_model_no_loss(sapm_dc_snl_ac_system, location, weather):
     mc = ModelChain(sapm_dc_snl_ac_system, location, dc_model='sapm',
                     aoi_model='no_loss', spectral_model='no_loss')
@@ -1382,6 +1446,21 @@ def test_spectral_models(sapm_dc_snl_ac_system, location, spectral_model,
     assert isinstance(spectral_modifier, (pd.Series, float, int))
 
 
+@pytest.mark.parametrize('spectral_model', [
+    'sapm', 'first_solar', 'no_loss', constant_spectral_loss
+])
+def test_spectral_models_singleton_weather_single_array(
+        sapm_dc_snl_ac_system, location, spectral_model, weather):
+    # add pw to weather dataframe
+    weather['precipitable_water'] = [0.3, 0.5]
+    mc = ModelChain(sapm_dc_snl_ac_system, location, dc_model='sapm',
+                    aoi_model='no_loss', spectral_model=spectral_model)
+    spectral_modifier = mc.run_model([weather]).results.spectral_modifier
+    assert isinstance(spectral_modifier, tuple)
+    assert len(spectral_modifier) == 1
+    assert isinstance(spectral_modifier[0], (pd.Series, float, int))
+
+
 def constant_losses(mc):
     mc.losses = 0.9
     mc.results.dc *= mc.losses
diff --git a/pvlib/tests/test_pvsystem.py b/pvlib/tests/test_pvsystem.py
--- a/pvlib/tests/test_pvsystem.py
+++ b/pvlib/tests/test_pvsystem.py
@@ -1472,6 +1472,40 @@ def test_PVSystem_get_ac_pvwatts_multi(
         system.get_ac('pvwatts', (pdcs, pdcs, pdcs))
 
 
+@pytest.mark.parametrize('model', ['sandia', 'adr', 'pvwatts'])
+def test_PVSystem_get_ac_single_array_tuple_input(
+        model,
+        pvwatts_system_defaults,
+        cec_inverter_parameters,
+        adr_inverter_parameters):
+    vdcs = {
+        'sandia': pd.Series(np.linspace(0, 50, 3)),
+        'pvwatts': None,
+        'adr': pd.Series([135, 154, 390, 420, 551])
+    }
+    pdcs = {'adr': pd.Series([135, 1232, 1170, 420, 551]),
+            'sandia': pd.Series(np.linspace(0, 11, 3)) * vdcs['sandia'],
+            'pvwatts': 50}
+    inverter_parameters = {
+        'sandia': cec_inverter_parameters,
+        'adr': adr_inverter_parameters,
+        'pvwatts': pvwatts_system_defaults.inverter_parameters
+    }
+    expected = {
+        'adr': pd.Series([np.nan, 1161.5745, 1116.4459, 382.6679, np.nan]),
+        'sandia': pd.Series([-0.020000, 132.004308, 250.000000])
+    }
+    system = pvsystem.PVSystem(
+        arrays=[pvsystem.Array()],
+        inverter_parameters=inverter_parameters[model]
+    )
+    ac = system.get_ac(p_dc=(pdcs[model],), v_dc=(vdcs[model],), model=model)
+    if model == 'pvwatts':
+        assert ac < pdcs['pvwatts']
+    else:
+        assert_series_equal(ac, expected[model])
+
+
 def test_PVSystem_get_ac_adr(adr_inverter_parameters, mocker):
     mocker.spy(inverter, 'adr')
     system = pvsystem.PVSystem(