Skip to content

Commit e670800

Browse files
committed
remove infer_spectral_model
1 parent 75a2f00 commit e670800

File tree

3 files changed

+9
-116
lines changed

3 files changed

+9
-116
lines changed

docs/sphinx/source/whatsnew/v0.11.3.rst

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@
44
v0.11.3 (Anticipated March, 2025)
55
---------------------------------
66

7+
Breaking Changes
8+
~~~~~~~~~~~~~~~~
9+
* The pvlib.location.Location.pytz attribute is now read only. The
10+
pytz attribute is now set internally to be consistent with the
11+
pvlib.location.Location.tz attribute. (:issue:`2340`, :pull:`2341`)
12+
* Users must now provide ModelChain.spectral_model, or the 'no_loss' spectral
13+
model is assumed. pvlib.modelchain.ModelChain no longer attempts to infer
14+
the spectral from PVSystem attributes. (:issue:`2017`, :pull:`2253`)
15+
716
Bug fixes
817
~~~~~~~~~
918
* Fix a bug in :py:func:`pvlib.bifacial.get_irradiance_poa` which may have yielded non-zero
@@ -62,11 +71,6 @@ Maintenance
6271
* asv 0.4.2 upgraded to asv 0.6.4 to fix CI failure due to pinned older conda.
6372
(:pull:`2352`)
6473

65-
Breaking Changes
66-
~~~~~~~~~~~~~~~~
67-
* The pvlib.location.Location.pytz attribute is now read only. The
68-
pytz attribute is now set internally to be consistent with the
69-
pvlib.location.Location.tz attribute. (:issue:`2340`, :pull:`2341`)
7074

7175
Contributors
7276
~~~~~~~~~~~~

pvlib/modelchain.py

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -340,9 +340,6 @@ class ModelChain:
340340
The ModelChain instance will be passed as the first argument to
341341
a user-defined function.
342342
343-
See :py:func:`~pvlib.modelchain.ModelChain.infer_spectral_model` to
344-
get a list of available spectral models for the current system.
345-
346343
temperature_model : str or function, optional
347344
Valid strings are: 'sapm', 'pvsyst', 'faiman', 'fuentes', 'noct_sam'.
348345
The ModelChain instance will be passed as the first argument to a
@@ -876,72 +873,6 @@ def spectral_model(self, model):
876873
else: # assume model is callable with 1st argument = the MC instance
877874
self._spectral_model = partial(model, self)
878875

879-
def infer_spectral_model(self, weather=None):
880-
"""
881-
Return a spectral model key or a list of possible spectral models based
882-
on the system attributes and weather data. If the weather data is not
883-
provided, the spectral model will be inferred from the system
884-
attributes only.
885-
886-
Parameters
887-
----------
888-
weather : pd.DataFrame or collection of str, optional
889-
An object with columns of available input data to help infer
890-
the spectral model. If ``None``, the spectral model will be
891-
inferred from the system attributes only.
892-
893-
Returns
894-
-------
895-
Inferred spectral correction model : string key or list of string keys
896-
If no spectral model is inferred, 'no_loss' is returned.
897-
If only one spectral model is inferred, a string key is returned.
898-
If multiple spectral models are inferred, a list of string keys is
899-
returned.
900-
901-
The following spectral models keys may be returned:
902-
903-
- ``'sapm'`` for
904-
:py:func:`~pvlib.spectrum.spectral_factor_sapm`
905-
- ``'first_solar'`` for
906-
:py:func:`~pvlib.spectrum.spectral_factor_first_solar`.
907-
Requires ``'precipitable_water'`` in the weather dataframe.
908-
909-
If no spectral model is inferred, 'no_loss' is returned.
910-
911-
Examples
912-
--------
913-
>>> mc = ModelChain(system, location)
914-
>>> mc.spectral_model = mc.infer_spectral_model(weather=weather)
915-
"""
916-
possible_models_result = [] # list of possible spectral models
917-
module_parameters = tuple(
918-
array.module_parameters for array in self.system.arrays
919-
)
920-
params = _common_keys(module_parameters)
921-
922-
# infer all the possible spectral models and append them to the list
923-
if {"A4", "A3", "A2", "A1", "A0"} <= params:
924-
possible_models_result.append("sapm")
925-
if weather is not None: # models that depend on weather data
926-
if "precipitable_water" in weather:
927-
if "first_solar_spectral_coefficients" in params:
928-
# user explicitly sets first solar spectral coefficients
929-
possible_models_result.append("first_solar")
930-
# cell type is known or can be inferred
931-
if ("Technology" in params or "Material" in params) and (
932-
self.system._infer_cell_type() is not None
933-
):
934-
possible_models_result.append("first_solar")
935-
936-
# result resolution based on the number of inferred spectral models
937-
if (result_len := len(possible_models_result)) == 0:
938-
# if no spectral model is inferred, return no_loss
939-
return "no_loss"
940-
elif result_len == 1:
941-
# when only one spectral model is inferred, return it
942-
return possible_models_result[0]
943-
else: # multiple spectral models are inferred (avoiding duplicates)
944-
return list(set(possible_models_result))
945876

946877
def first_solar_spectral_loss(self):
947878
self.results.spectral_modifier = self.system.first_solar_spectral_loss(

tests/test_modelchain.py

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,48 +1280,6 @@ def test_singlediode_dc_arrays(location, dc_model,
12801280
assert isinstance(dc, (pd.Series, pd.DataFrame))
12811281

12821282

1283-
@pytest.mark.parametrize('dc_model', ['sapm', 'cec', 'cec_native'])
1284-
def test_infer_spectral_model(location, sapm_dc_snl_ac_system,
1285-
cec_dc_snl_ac_system,
1286-
cec_dc_native_snl_ac_system, dc_model):
1287-
dc_systems = {'sapm': sapm_dc_snl_ac_system,
1288-
'cec': cec_dc_snl_ac_system,
1289-
'cec_native': cec_dc_native_snl_ac_system}
1290-
system = dc_systems[dc_model]
1291-
mc = ModelChain(system, location, aoi_model='physical')
1292-
assert isinstance(mc, ModelChain)
1293-
1294-
1295-
def test_infer_spectral_model_with_weather(location, sapm_dc_snl_ac_system,
1296-
cec_dc_snl_ac_system, weather):
1297-
# instantiate example ModelChain to get the default spectral model
1298-
# default should resolve to no loss
1299-
mc = ModelChain(sapm_dc_snl_ac_system, location, aoi_model='physical')
1300-
assert mc.spectral_model == mc.no_spectral_loss
1301-
# - inference should resolve to sapm
1302-
mc.spectral_model = mc.infer_spectral_model(weather=weather)
1303-
assert mc.spectral_model == mc.sapm_spectral_loss
1304-
# - next inference should resolve to no loss
1305-
mc = ModelChain(
1306-
cec_dc_snl_ac_system,
1307-
location,
1308-
aoi_model="physical",
1309-
spectral_model=None,
1310-
)
1311-
mc.spectral_model = mc.infer_spectral_model(weather=weather)
1312-
assert mc.spectral_model == mc.no_spectral_loss
1313-
1314-
# infer spectral model from weather
1315-
# - without precipitable water in it, should resolve to no loss
1316-
mc.spectral_model = mc.infer_spectral_model(weather=weather)
1317-
assert mc.spectral_model == mc.no_spectral_loss
1318-
# - with precipitable water in it, should resolve to first solar
1319-
weather['precipitable_water'] = 1.42
1320-
mc.spectral_model = mc.infer_spectral_model(weather=weather)
1321-
assert mc.spectral_model == mc.first_solar_spectral_loss
1322-
assert isinstance(mc, ModelChain)
1323-
1324-
13251283
@pytest.mark.parametrize('temp_model', [
13261284
'sapm_temp', 'faiman_temp', 'pvsyst_temp', 'fuentes_temp',
13271285
'noct_sam_temp'])

0 commit comments

Comments
 (0)