|
3 | 3 | """
|
4 | 4 |
|
5 | 5 | import pvlib
|
| 6 | +from pvlib.tools import normalize_max2one |
6 | 7 | import numpy as np
|
7 | 8 | import pandas as pd
|
8 |
| -from scipy.interpolate import interp1d |
| 9 | +import scipy.constants |
9 | 10 | from scipy.integrate import trapezoid
|
| 11 | +from scipy.interpolate import interp1d |
10 | 12 | import os
|
11 | 13 |
|
12 | 14 | from warnings import warn
|
13 | 15 |
|
14 | 16 |
|
| 17 | +_PLANCK_BY_LIGHT_SPEED_OVER_ELEMENTAL_CHARGE_BY_BILLION = ( |
| 18 | + scipy.constants.speed_of_light |
| 19 | + * scipy.constants.Planck |
| 20 | + / scipy.constants.elementary_charge |
| 21 | + * 1e9 |
| 22 | +) |
| 23 | + |
| 24 | + |
15 | 25 | def get_example_spectral_response(wavelength=None):
|
16 | 26 | '''
|
17 | 27 | Generate a generic smooth spectral response (SR) for tests and experiments.
|
@@ -154,7 +164,7 @@ def calc_spectral_mismatch_field(sr, e_sun, e_ref=None):
|
154 | 164 |
|
155 | 165 | e_sun: pandas.DataFrame or pandas.Series
|
156 | 166 | One or more measured solar irradiance spectra in a pandas.DataFrame
|
157 |
| - having wavelength in nm as column index. A single spectrum may be |
| 167 | + having wavelength in nm as column index. A single spectrum may be |
158 | 168 | be given as a pandas.Series having wavelength in nm as index.
|
159 | 169 | [(W/m^2)/nm]
|
160 | 170 |
|
@@ -571,3 +581,201 @@ def spectral_factor_caballero(precipitable_water, airmass_absolute, aod500,
|
571 | 581 | )
|
572 | 582 | modifier = f_AM + f_AOD + f_PW # Eq 5
|
573 | 583 | return modifier
|
| 584 | + |
| 585 | + |
| 586 | +def sr_to_qe(sr, wavelength=None, normalize=False): |
| 587 | + """ |
| 588 | + Convert spectral responsivities to quantum efficiencies. |
| 589 | + If ``wavelength`` is not provided, the spectral responsivity ``sr`` must be |
| 590 | + a :py:class:`pandas.Series` or :py:class:`pandas.DataFrame`, with the |
| 591 | + wavelengths in the index. |
| 592 | +
|
| 593 | + Provide wavelengths in nanometers, [nm]. |
| 594 | +
|
| 595 | + Conversion is described in [1]_. |
| 596 | +
|
| 597 | + .. versionadded:: 0.11.0 |
| 598 | +
|
| 599 | + Parameters |
| 600 | + ---------- |
| 601 | + sr : numeric, pandas.Series or pandas.DataFrame |
| 602 | + Spectral response, [A/W]. |
| 603 | + Index must be the wavelength in nanometers, [nm]. |
| 604 | +
|
| 605 | + wavelength : numeric, optional |
| 606 | + Points where spectral response is measured, in nanometers, [nm]. |
| 607 | +
|
| 608 | + normalize : bool, default False |
| 609 | + If True, the quantum efficiency is normalized so that the maximum value |
| 610 | + is 1. |
| 611 | + For ``pandas.DataFrame``, normalization is done for each column. |
| 612 | + For 2D arrays, normalization is done for each sub-array. |
| 613 | +
|
| 614 | + Returns |
| 615 | + ------- |
| 616 | + quantum_efficiency : numeric, same type as ``sr`` |
| 617 | + Quantum efficiency, in the interval [0, 1]. |
| 618 | +
|
| 619 | + Notes |
| 620 | + ----- |
| 621 | + - If ``sr`` is of type ``pandas.Series`` or ``pandas.DataFrame``, |
| 622 | + column names will remain unchanged in the returned object. |
| 623 | + - If ``wavelength`` is provided it will be used independently of the |
| 624 | + datatype of ``sr``. |
| 625 | +
|
| 626 | + Examples |
| 627 | + -------- |
| 628 | + >>> import numpy as np |
| 629 | + >>> import pandas as pd |
| 630 | + >>> from pvlib import spectrum |
| 631 | + >>> wavelengths = np.array([350, 550, 750]) |
| 632 | + >>> spectral_response = np.array([0.25, 0.40, 0.57]) |
| 633 | + >>> quantum_efficiency = spectrum.sr_to_qe(spectral_response, wavelengths) |
| 634 | + >>> print(quantum_efficiency) |
| 635 | + array([0.88560142, 0.90170326, 0.94227991]) |
| 636 | +
|
| 637 | + >>> spectral_response_series = pd.Series(spectral_response, index=wavelengths, name="dataset") |
| 638 | + >>> qe = spectrum.sr_to_qe(spectral_response_series) |
| 639 | + >>> print(qe) |
| 640 | + 350 0.885601 |
| 641 | + 550 0.901703 |
| 642 | + 750 0.942280 |
| 643 | + Name: dataset, dtype: float64 |
| 644 | +
|
| 645 | + >>> qe = spectrum.sr_to_qe(spectral_response_series, normalize=True) |
| 646 | + >>> print(qe) |
| 647 | + 350 0.939850 |
| 648 | + 550 0.956938 |
| 649 | + 750 1.000000 |
| 650 | + Name: dataset, dtype: float64 |
| 651 | +
|
| 652 | + References |
| 653 | + ---------- |
| 654 | + .. [1] “Spectral Response,” PV Performance Modeling Collaborative (PVPMC). |
| 655 | + https://pvpmc.sandia.gov/modeling-guide/2-dc-module-iv/effective-irradiance/spectral-response/ |
| 656 | + .. [2] “Spectral Response | PVEducation,” www.pveducation.org. |
| 657 | + https://www.pveducation.org/pvcdrom/solar-cell-operation/spectral-response |
| 658 | +
|
| 659 | + See Also |
| 660 | + -------- |
| 661 | + pvlib.spectrum.qe_to_sr |
| 662 | + """ # noqa: E501 |
| 663 | + if wavelength is None: |
| 664 | + if hasattr(sr, "index"): # true for pandas objects |
| 665 | + # use reference to index values instead of index alone so |
| 666 | + # sr / wavelength returns a series with the same name |
| 667 | + wavelength = sr.index.array |
| 668 | + else: |
| 669 | + raise TypeError( |
| 670 | + "'sr' must have an '.index' attribute" |
| 671 | + + " or 'wavelength' must be provided" |
| 672 | + ) |
| 673 | + quantum_efficiency = ( |
| 674 | + sr |
| 675 | + / wavelength |
| 676 | + * _PLANCK_BY_LIGHT_SPEED_OVER_ELEMENTAL_CHARGE_BY_BILLION |
| 677 | + ) |
| 678 | + |
| 679 | + if normalize: |
| 680 | + quantum_efficiency = normalize_max2one(quantum_efficiency) |
| 681 | + |
| 682 | + return quantum_efficiency |
| 683 | + |
| 684 | + |
| 685 | +def qe_to_sr(qe, wavelength=None, normalize=False): |
| 686 | + """ |
| 687 | + Convert quantum efficiencies to spectral responsivities. |
| 688 | + If ``wavelength`` is not provided, the quantum efficiency ``qe`` must be |
| 689 | + a :py:class:`pandas.Series` or :py:class:`pandas.DataFrame`, with the |
| 690 | + wavelengths in the index. |
| 691 | +
|
| 692 | + Provide wavelengths in nanometers, [nm]. |
| 693 | +
|
| 694 | + Conversion is described in [1]_. |
| 695 | +
|
| 696 | + .. versionadded:: 0.11.0 |
| 697 | +
|
| 698 | + Parameters |
| 699 | + ---------- |
| 700 | + qe : numeric, pandas.Series or pandas.DataFrame |
| 701 | + Quantum efficiency. |
| 702 | + If pandas subtype, index must be the wavelength in nanometers, [nm]. |
| 703 | +
|
| 704 | + wavelength : numeric, optional |
| 705 | + Points where quantum efficiency is measured, in nanometers, [nm]. |
| 706 | +
|
| 707 | + normalize : bool, default False |
| 708 | + If True, the spectral response is normalized so that the maximum value |
| 709 | + is 1. |
| 710 | + For ``pandas.DataFrame``, normalization is done for each column. |
| 711 | + For 2D arrays, normalization is done for each sub-array. |
| 712 | +
|
| 713 | + Returns |
| 714 | + ------- |
| 715 | + spectral_response : numeric, same type as ``qe`` |
| 716 | + Spectral response, [A/W]. |
| 717 | +
|
| 718 | + Notes |
| 719 | + ----- |
| 720 | + - If ``qe`` is of type ``pandas.Series`` or ``pandas.DataFrame``, |
| 721 | + column names will remain unchanged in the returned object. |
| 722 | + - If ``wavelength`` is provided it will be used independently of the |
| 723 | + datatype of ``qe``. |
| 724 | +
|
| 725 | + Examples |
| 726 | + -------- |
| 727 | + >>> import numpy as np |
| 728 | + >>> import pandas as pd |
| 729 | + >>> from pvlib import spectrum |
| 730 | + >>> wavelengths = np.array([350, 550, 750]) |
| 731 | + >>> quantum_efficiency = np.array([0.86, 0.90, 0.94]) |
| 732 | + >>> spectral_response = spectrum.qe_to_sr(quantum_efficiency, wavelengths) |
| 733 | + >>> print(spectral_response) |
| 734 | + array([0.24277287, 0.39924442, 0.56862085]) |
| 735 | +
|
| 736 | + >>> quantum_efficiency_series = pd.Series(quantum_efficiency, index=wavelengths, name="dataset") |
| 737 | + >>> sr = spectrum.qe_to_sr(quantum_efficiency_series) |
| 738 | + >>> print(sr) |
| 739 | + 350 0.242773 |
| 740 | + 550 0.399244 |
| 741 | + 750 0.568621 |
| 742 | + Name: dataset, dtype: float64 |
| 743 | +
|
| 744 | + >>> sr = spectrum.qe_to_sr(quantum_efficiency_series, normalize=True) |
| 745 | + >>> print(sr) |
| 746 | + 350 0.426950 |
| 747 | + 550 0.702128 |
| 748 | + 750 1.000000 |
| 749 | + Name: dataset, dtype: float64 |
| 750 | +
|
| 751 | + References |
| 752 | + ---------- |
| 753 | + .. [1] “Spectral Response,” PV Performance Modeling Collaborative (PVPMC). |
| 754 | + https://pvpmc.sandia.gov/modeling-guide/2-dc-module-iv/effective-irradiance/spectral-response/ |
| 755 | + .. [2] “Spectral Response | PVEducation,” www.pveducation.org. |
| 756 | + https://www.pveducation.org/pvcdrom/solar-cell-operation/spectral-response |
| 757 | +
|
| 758 | + See Also |
| 759 | + -------- |
| 760 | + pvlib.spectrum.sr_to_qe |
| 761 | + """ # noqa: E501 |
| 762 | + if wavelength is None: |
| 763 | + if hasattr(qe, "index"): # true for pandas objects |
| 764 | + # use reference to index values instead of index alone so |
| 765 | + # sr / wavelength returns a series with the same name |
| 766 | + wavelength = qe.index.array |
| 767 | + else: |
| 768 | + raise TypeError( |
| 769 | + "'qe' must have an '.index' attribute" |
| 770 | + + " or 'wavelength' must be provided" |
| 771 | + ) |
| 772 | + spectral_responsivity = ( |
| 773 | + qe |
| 774 | + * wavelength |
| 775 | + / _PLANCK_BY_LIGHT_SPEED_OVER_ELEMENTAL_CHARGE_BY_BILLION |
| 776 | + ) |
| 777 | + |
| 778 | + if normalize: |
| 779 | + spectral_responsivity = normalize_max2one(spectral_responsivity) |
| 780 | + |
| 781 | + return spectral_responsivity |
0 commit comments