From 781d490f5d4dbd04ff1efccf840acb21e09e06c4 Mon Sep 17 00:00:00 2001 From: Ismail Baris Date: Fri, 30 Mar 2018 04:24:12 +0200 Subject: [PATCH 1/8] Outsourced the soil reflectance from SAIL model. --- pyrism/models/models.py | 57 +++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/pyrism/models/models.py b/pyrism/models/models.py index 4ab264d..cbca821 100644 --- a/pyrism/models/models.py +++ b/pyrism/models/models.py @@ -480,15 +480,15 @@ class SAIL(Kernel): iza, vza, raa : int, float or ndarray Incidence (iza) and scattering (vza) zenith angle, as well as relative azimuth (raa) angle. ks, kt : array_like - Continuous leaf reflection (ks) and leaf transmission (kt) values from from 400 until 2500 nm. + Continuous leaf reflection (ks) and leaf transmission (kt) values from from 400 until 2500 nm. One can use the + output from PROSPECT class instance. lai : float Leaf area index. hotspot : float The hotspot parameter. - soil_reflectance : int or float - Surface (Lambertian) reflectance in optical wavelength. - soil_moisture : int or float - Surface moisture content between 0 and 1. + rho_surface : array_like + Continuous surface reflectance values from from 400 until 2500 nm. One can use the + output from LSM class instance. lidf_type : {'verhoef', 'campbell'}, optional Define with which method the LIDF is calculated. Default is 'campbell' a, b : float, optional @@ -525,17 +525,36 @@ class SAIL(Kernel): """ - def __init__(self, iza, vza, raa, ks, kt, lai, hotspot, soil_reflectance, soil_moisture, + def __init__(self, iza, vza, raa, ks, kt, lai, hotspot, rho_surface, lidf_type='campbell', a=57, b=0, normalize=False, nbar=0.0, angle_unit='DEG'): + super(SAIL, self).__init__(iza=iza, vza=vza, raa=raa, normalize=normalize, nbar=nbar, angle_unit=angle_unit, align=True) + if len(ks) != 2101: + raise AssertionError( + "ks must contain continuous leaf reflectance values from from 400 until 2500 nm with a length of 2101. The actual length of ks is {0}".format( + str(len(ks)))) + + elif len(kt) != 2101: + raise AssertionError( + "kt must contain continuous leaf transmitance values from from 400 until 2500 nm with a length of 2101. The actual length of kt is {0}".format( + str(len(kt)))) + + elif len(rho_surface) != 2101: + raise AssertionError( + "rho_surface must contain continuous surface reflectance values from from 400 until 2500 nm with a length of 2101. The actual length of rho_surface is {0}".format( + str(len(rho_surface)))) + + else: + pass + self.ks = ks self.kt = kt self.lai = lai self.hotspot = hotspot - self.Soil = LSM(reflectance=soil_reflectance, moisture=soil_moisture) + self.rho_surface = rho_surface self.VollScat = VolScatt(iza, vza, raa, angle_unit) if lidf_type is 'verhoef': @@ -543,7 +562,7 @@ def __init__(self, iza, vza, raa, ks, kt, lai, hotspot, soil_reflectance, soil_m elif lidf_type is 'campbell': self.VollScat.coef(a=a, lidf_type='campbell') else: - raise ValueError("The lidf_type must be 'verhoef' or 'campbell'") + raise AssertionError("The lidf_type must be 'verhoef' or 'campbell'") tss, too, tsstoo, rdd, tdd, rsd, tsd, rdo, tdo, rso, rsos, rsod, rddt, rsdt, rdot, rsodt, rsost, rsot, gammasdf, gammasdb, gammaso = self.__calc() @@ -598,12 +617,12 @@ def __calc(self): rso = 0 rsos = 0 rsod = 0 - rddt = self.Soil.ref - rsdt = self.Soil.ref - rdot = self.Soil.ref + rddt = self.rho_surface + rsdt = self.rho_surface + rdot = self.rho_surface rsodt = 0 - rsost = self.Soil.ref - rsot = self.Soil.ref + rsost = self.rho_surface + rsot = self.rho_surface gammasdf = 0 gammaso = 0 gammasdb = 0 @@ -689,18 +708,18 @@ def __calc(self): gammaso = gammasos + gammasod # Interaction with the soil - dn = 1. - self.Soil.ref * rdd + dn = 1. - self.rho_surface * rdd try: dn[dn < 1e-36] = 1e-36 except TypeError: dn = max(1e-36, dn) - rddt = rdd + tdd * self.Soil.ref * tdd / dn - rsdt = rsd + (tsd + tss) * self.Soil.ref * tdd / dn - rdot = rdo + tdd * self.Soil.ref * (tdo + too) / dn - rsodt = ((tss + tsd) * tdo + (tsd + tss * self.Soil.ref * rdd) * too) * self.Soil.ref / dn - rsost = rso + tsstoo * self.Soil.ref + rddt = rdd + tdd * self.rho_surface * tdd / dn + rsdt = rsd + (tsd + tss) * self.rho_surface * tdd / dn + rdot = rdo + tdd * self.rho_surface * (tdo + too) / dn + rsodt = ((tss + tsd) * tdo + (tsd + tss * self.rho_surface * rdd) * too) * self.rho_surface / dn + rsost = rso + tsstoo * self.rho_surface rsot = rsost + rsodt return [tss, too, tsstoo, rdd, tdd, rsd, tsd, rdo, tdo, From da2d4cd6628887d8eaddee6e6989af808938b002 Mon Sep 17 00:00:00 2001 From: Ismail Baris Date: Fri, 30 Mar 2018 04:24:26 +0200 Subject: [PATCH 2/8] Updated examples --- examples/prospect_sail.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/prospect_sail.py b/examples/prospect_sail.py index 1141c23..b9c67cb 100644 --- a/examples/prospect_sail.py +++ b/examples/prospect_sail.py @@ -19,9 +19,12 @@ # select the coefficient values for the specific bands of ASTER (B1 - B9) or LANDSAT8 (B2 - B7). To access these bands # type prospect.L8.Bx (x = 2, 3, ..., 7) for Landsat 8 or prospect.ASTER.Bx (x = 1, 2, ..., 9) for ASTER. +# To calculate the PROSAIL model we need some soil reflectance values. To obtain these we can use the LSM model: +lsm = pyrism.LSM(reflectance=3.14 / 4, moisture=0.15) -# To calculate the PROSAIL model we must call SAIL and specify the scattering and transmittance coefficients with these from PROSPECT like: -prosail = pyrism.SAIL(iza=iza, vza=vza, raa=raa, ks=prospect.ks, kt=prospect.kt, lidf_type='campbell', - lai=3, hotspot=0.25, soil_reflectance=3.14 / 4, soil_moisture=0.15) +# Now we must call SAIL and specify the scattering and transmittance coefficients with these from PROSPECT like: +prosail = pyrism.SAIL(iza=iza, vza=vza, raa=raa, ks=prospect.ks, kt=prospect.kt, rho_surface=lsm.ref, + lidf_type='campbell', + lai=3, hotspot=0.25) # The accessibility of the attributes are the same as the PROSPECT model. From 046639a2a555fd097336f3b756cb778599a1d3d7 Mon Sep 17 00:00:00 2001 From: Ismail Baris Date: Fri, 30 Mar 2018 04:24:36 +0200 Subject: [PATCH 3/8] Updated unit test --- tests/test_prospect_prosail.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/test_prospect_prosail.py b/tests/test_prospect_prosail.py index dbc0502..5009a06 100644 --- a/tests/test_prospect_prosail.py +++ b/tests/test_prospect_prosail.py @@ -6,7 +6,7 @@ from pytest import fixture from scipy.io import loadmat -from pyrism import PROSPECT, SAIL +from pyrism import PROSPECT, SAIL, LSM @fixture @@ -79,9 +79,9 @@ def test_sdr_prosail5(self, datadir): fname = datadir("REFL_CAN.txt") w, resv, hdr, sdr, bhr, dhr = loadtxt(fname, unpack=True) + lsm = LSM(reflectance=1, moisture=1) prospect = PROSPECT(N=1.5, Cab=40, Cxc=8., Cbr=0.0, Cw=0.01, Cm=0.009, version="5") - sail = SAIL(iza=30, vza=10, raa=0, ks=prospect.ks, kt=prospect.kt, lai=3, hotspot=0.01, soil_reflectance=1, - soil_moisture=1, + sail = SAIL(iza=30, vza=10, raa=0, ks=prospect.ks, kt=prospect.kt, lai=3, hotspot=0.01, rho_surface=lsm.ref, a=-0.35, b=-0.15, lidf_type='verhoef') assert allclose(sdr, sail.BRF.ref, atol=0.01) @@ -90,9 +90,9 @@ def test_hdr_prosail5(self, datadir): fname = datadir("REFL_CAN.txt") w, resv, hdr, sdr, bhr, dhr = loadtxt(fname, unpack=True) + lsm = LSM(reflectance=1, moisture=1) prospect = PROSPECT(N=1.5, Cab=40, Cxc=8., Cbr=0.0, Cw=0.01, Cm=0.009, version="5") - sail = SAIL(iza=30, vza=10, raa=0, ks=prospect.ks, kt=prospect.kt, lai=3, hotspot=0.01, soil_reflectance=1, - soil_moisture=1, + sail = SAIL(iza=30, vza=10, raa=0, ks=prospect.ks, kt=prospect.kt, lai=3, hotspot=0.01, rho_surface=lsm.ref, a=-0.35, b=-0.15, lidf_type='verhoef') assert allclose(hdr, sail.HDR.ref, atol=0.01) @@ -101,9 +101,9 @@ def test_bhr_prosail5(self, datadir): fname = datadir("REFL_CAN.txt") w, resv, hdr, sdr, bhr, dhr = loadtxt(fname, unpack=True) + lsm = LSM(reflectance=1, moisture=1) prospect = PROSPECT(N=1.5, Cab=40, Cxc=8., Cbr=0.0, Cw=0.01, Cm=0.009, version="5") - sail = SAIL(iza=30, vza=10, raa=0, ks=prospect.ks, kt=prospect.kt, lai=3, hotspot=0.01, soil_reflectance=1, - soil_moisture=1, + sail = SAIL(iza=30, vza=10, raa=0, ks=prospect.ks, kt=prospect.kt, lai=3, hotspot=0.01, rho_surface=lsm.ref, a=-0.35, b=-0.15, lidf_type='verhoef') assert allclose(bhr, sail.BHR.ref, atol=0.01) @@ -112,9 +112,9 @@ def test_dhr_prosail5(self, datadir): fname = datadir("REFL_CAN.txt") w, resv, hdr, sdr, bhr, dhr = loadtxt(fname, unpack=True) + lsm = LSM(reflectance=1, moisture=1) prospect = PROSPECT(N=1.5, Cab=40, Cxc=8., Cbr=0.0, Cw=0.01, Cm=0.009, version="5") - sail = SAIL(iza=30, vza=10, raa=0, ks=prospect.ks, kt=prospect.kt, lai=3, hotspot=0.01, soil_reflectance=1, - soil_moisture=1, + sail = SAIL(iza=30, vza=10, raa=0, ks=prospect.ks, kt=prospect.kt, lai=3, hotspot=0.01, rho_surface=lsm.ref, a=-0.35, b=-0.15, lidf_type='verhoef') assert allclose(dhr, sail.DHR.ref, atol=0.01) From 3140fab9b5176f458012731378c97ec21e3f4e2e Mon Sep 17 00:00:00 2001 From: Ismail Baris Date: Fri, 30 Mar 2018 04:24:45 +0200 Subject: [PATCH 4/8] Changed version number --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index a9d6453..0b5351e 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ def get_packages(): setup(name='pyrism', - version='0.0.2.1', + version='0.0.3', description='Python bindings for Remote Sensing Models', From a9300371125b0491a2a82b264ee83cfc6c094d46 Mon Sep 17 00:00:00 2001 From: Ismail Baris Date: Fri, 30 Mar 2018 04:36:03 +0200 Subject: [PATCH 5/8] Add unit tests --- tests/test_auxil.py | 12 +++++++++++ tests/test_prospect_prosail.py | 37 +++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/tests/test_auxil.py b/tests/test_auxil.py index 813b5cc..2ad64d9 100644 --- a/tests/test_auxil.py +++ b/tests/test_auxil.py @@ -11,16 +11,28 @@ def test_reflectance(self): assert test.a == 1 assert test.b == 2 + def test_reflectance_keys(self): + test = ReflectanceResult(a=1, b=2) + assert test.keys() == ['a', 'b'] + def test_emissivity(self): test = EmissivityResult(a=1, b=2) assert test.a == 1 assert test.b == 2 + def test_emissivity_keys(self): + test = EmissivityResult(a=1, b=2) + assert test.keys() == ['a', 'b'] + def test_sail(self): test = SailResult(a=1, b=2) assert test.a == 1 assert test.b == 2 + def test_sail_keys(self): + test = SailResult(a=1, b=2) + assert test.keys() == ['a', 'b'] + @pytest.mark.webtest @pytest.mark.parametrize("iza, vza, raa, ref", [ (35,30,50,0.01) diff --git a/tests/test_prospect_prosail.py b/tests/test_prospect_prosail.py index 5009a06..1bc5943 100644 --- a/tests/test_prospect_prosail.py +++ b/tests/test_prospect_prosail.py @@ -2,7 +2,7 @@ from distutils import dir_util import pytest -from numpy import allclose, loadtxt +from numpy import allclose, loadtxt, atleast_1d from pytest import fixture from scipy.io import loadmat @@ -118,3 +118,38 @@ def test_dhr_prosail5(self, datadir): a=-0.35, b=-0.15, lidf_type='verhoef') assert allclose(dhr, sail.DHR.ref, atol=0.01) + + +class TestPROSAILError: + def test_ks(self, datadir): + fname = datadir("REFL_CAN.txt") + w, resv, hdr, sdr, bhr, dhr = loadtxt(fname, unpack=True) + ks = atleast_1d(0) + + lsm = LSM(reflectance=1, moisture=1) + prospect = PROSPECT(N=1.5, Cab=40, Cxc=8., Cbr=0.0, Cw=0.01, Cm=0.009, version="5") + with pytest.raises(AssertionError): + sail = SAIL(iza=30, vza=10, raa=0, ks=ks, kt=prospect.kt, lai=3, hotspot=0.01, rho_surface=lsm.ref, + a=-0.35, b=-0.15, lidf_type='verhoef') + + def test_kt(self, datadir): + fname = datadir("REFL_CAN.txt") + w, resv, hdr, sdr, bhr, dhr = loadtxt(fname, unpack=True) + kt = atleast_1d(0) + + lsm = LSM(reflectance=1, moisture=1) + prospect = PROSPECT(N=1.5, Cab=40, Cxc=8., Cbr=0.0, Cw=0.01, Cm=0.009, version="5") + with pytest.raises(AssertionError): + sail = SAIL(iza=30, vza=10, raa=0, ks=prospect.ks, kt=kt, lai=3, hotspot=0.01, rho_surface=lsm.ref, + a=-0.35, b=-0.15, lidf_type='verhoef') + + def test_surf(self, datadir): + fname = datadir("REFL_CAN.txt") + w, resv, hdr, sdr, bhr, dhr = loadtxt(fname, unpack=True) + kt = atleast_1d(0) + + lsm = LSM(reflectance=1, moisture=1) + prospect = PROSPECT(N=1.5, Cab=40, Cxc=8., Cbr=0.0, Cw=0.01, Cm=0.009, version="5") + with pytest.raises(AssertionError): + sail = SAIL(iza=30, vza=10, raa=0, ks=prospect.ks, kt=prospect.kt, lai=3, hotspot=0.01, rho_surface=kt, + a=-0.35, b=-0.15, lidf_type='verhoef') From e6b677bcc7cf1de3a46e38af5626f67a9106724d Mon Sep 17 00:00:00 2001 From: Ismail Baris Date: Fri, 30 Mar 2018 04:41:27 +0200 Subject: [PATCH 6/8] python 3 compatibility. --- tests/test_auxil.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_auxil.py b/tests/test_auxil.py index 2ad64d9..0178343 100644 --- a/tests/test_auxil.py +++ b/tests/test_auxil.py @@ -13,7 +13,7 @@ def test_reflectance(self): def test_reflectance_keys(self): test = ReflectanceResult(a=1, b=2) - assert test.keys() == ['a', 'b'] + assert list(test.keys()) == ['a', 'b'] def test_emissivity(self): test = EmissivityResult(a=1, b=2) @@ -22,7 +22,7 @@ def test_emissivity(self): def test_emissivity_keys(self): test = EmissivityResult(a=1, b=2) - assert test.keys() == ['a', 'b'] + assert list(test.keys()) == ['a', 'b'] def test_sail(self): test = SailResult(a=1, b=2) @@ -31,7 +31,7 @@ def test_sail(self): def test_sail_keys(self): test = SailResult(a=1, b=2) - assert test.keys() == ['a', 'b'] + assert list(test.keys()) == ['a', 'b'] @pytest.mark.webtest @pytest.mark.parametrize("iza, vza, raa, ref", [ From a475a955b8946534c1debe426cb2b3357018f206 Mon Sep 17 00:00:00 2001 From: Ismail Baris Date: Fri, 30 Mar 2018 04:44:49 +0200 Subject: [PATCH 7/8] python 3 compatibility. --- tests/test_auxil.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tests/test_auxil.py b/tests/test_auxil.py index 0178343..353d34c 100644 --- a/tests/test_auxil.py +++ b/tests/test_auxil.py @@ -1,3 +1,5 @@ +import sys + import numpy as np import pytest @@ -13,7 +15,10 @@ def test_reflectance(self): def test_reflectance_keys(self): test = ReflectanceResult(a=1, b=2) - assert list(test.keys()) == ['a', 'b'] + if sys.version_info < (3, 0): + assert list(test.keys()) == ['a', 'b'] + else: + assert list(test.keys()) == ['b', 'a'] def test_emissivity(self): test = EmissivityResult(a=1, b=2) @@ -22,7 +27,10 @@ def test_emissivity(self): def test_emissivity_keys(self): test = EmissivityResult(a=1, b=2) - assert list(test.keys()) == ['a', 'b'] + if sys.version_info < (3, 0): + assert list(test.keys()) == ['a', 'b'] + else: + assert list(test.keys()) == ['b', 'a'] def test_sail(self): test = SailResult(a=1, b=2) @@ -31,7 +39,10 @@ def test_sail(self): def test_sail_keys(self): test = SailResult(a=1, b=2) - assert list(test.keys()) == ['a', 'b'] + if sys.version_info < (3, 0): + assert list(test.keys()) == ['a', 'b'] + else: + assert list(test.keys()) == ['b', 'a'] @pytest.mark.webtest @pytest.mark.parametrize("iza, vza, raa, ref", [ From 4af69f5fd1f9ba3b5644d6d3720537f3a3762400 Mon Sep 17 00:00:00 2001 From: Ismail Baris Date: Fri, 30 Mar 2018 04:48:47 +0200 Subject: [PATCH 8/8] python 3 compatibility. --- tests/test_auxil.py | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/tests/test_auxil.py b/tests/test_auxil.py index 353d34c..813b5cc 100644 --- a/tests/test_auxil.py +++ b/tests/test_auxil.py @@ -1,5 +1,3 @@ -import sys - import numpy as np import pytest @@ -13,37 +11,16 @@ def test_reflectance(self): assert test.a == 1 assert test.b == 2 - def test_reflectance_keys(self): - test = ReflectanceResult(a=1, b=2) - if sys.version_info < (3, 0): - assert list(test.keys()) == ['a', 'b'] - else: - assert list(test.keys()) == ['b', 'a'] - def test_emissivity(self): test = EmissivityResult(a=1, b=2) assert test.a == 1 assert test.b == 2 - def test_emissivity_keys(self): - test = EmissivityResult(a=1, b=2) - if sys.version_info < (3, 0): - assert list(test.keys()) == ['a', 'b'] - else: - assert list(test.keys()) == ['b', 'a'] - def test_sail(self): test = SailResult(a=1, b=2) assert test.a == 1 assert test.b == 2 - def test_sail_keys(self): - test = SailResult(a=1, b=2) - if sys.version_info < (3, 0): - assert list(test.keys()) == ['a', 'b'] - else: - assert list(test.keys()) == ['b', 'a'] - @pytest.mark.webtest @pytest.mark.parametrize("iza, vza, raa, ref", [ (35,30,50,0.01)