Example #1
0
    def test_calc(self):
        # just try to get it running simply without further testing
        RT = RT1(self.I0,
                 self.t_0,
                 self.t_ex,
                 self.p_0,
                 self.p_ex,
                 V=self.V,
                 SRF=self.S)
        Itot, Isurf, Ivol, Iint = RT.calc()
        self.assertTrue(np.allclose(Itot, Isurf + Ivol + Iint))

        V = Rayleigh(tau=0., omega=0.)
        RT = RT1(self.I0,
                 self.t_0,
                 self.t_ex,
                 self.p_0,
                 self.p_ex,
                 V=V,
                 SRF=self.S)
        Itot, Isurf, Ivol, Iint = RT.calc()
        self.assertEqual(Ivol, 0.)
        self.assertEqual(Iint, 0.)  # todo gives nan
        self.assertEqual(Itot, Isurf)
        self.assertTrue(Isurf > 0.)
Example #2
0
def Rad(theta, phi, thetainc, phiinc):
    '''
    thetainc : float
               azimuth incidence angle
    phiinc : float
             polar incidence angle
    theta : numpy array
            azimuth exit angles
    phi : numpy array
          polar exit angles
    '''
    # pre-evaluation of fn-coefficients

    print('start of 3d coefficient evaluation')
    tic = timeit.default_timer()
    Rfn = RT1(1.,
              np.deg2rad(thetainc),
              np.deg2rad(45),
              phiinc,
              np.pi,
              V=V,
              SRF=SRF,
              geometry='fvfv',
              lambda_backend='cse_seng_sp_newlambdify')

    _fnevals = Rfn._fnevals
    # store also fn-coefficients to avoid re-calculation
    # (alternatively one can provide any value but None to avoid calculation)
    fn = Rfn.fn

    toc = timeit.default_timer()
    print('evaluation of 3d coefficients took ' +
          str(round((toc - tic) / 60., 2)) + ' minutes')

    R3d = RT1(1.,
              tinc,
              theta,
              pinc,
              phi,
              V=V,
              SRF=SRF,
              fn_input=fn,
              _fnevals_input=_fnevals,
              geometry='fvfv')

    tic = timeit.default_timer()
    Itot, Isurf, Ivol, Iint = R3d.calc()

    Itot = 4. * np.pi * np.cos(theta) * Itot
    Isurf = 4. * np.pi * np.cos(theta) * Isurf
    Ivol = 4. * np.pi * np.cos(theta) * Ivol
    Iint = 4. * np.pi * np.cos(theta) * Iint

    toc = timeit.default_timer()
    print('evaluation of 3dplot print-values took ' +
          str(round((toc - tic) / 60., 2)) + ' minutes')

    return Itot, Isurf, Ivol, Iint
Example #3
0
 def test_volume(self):
     t_0 = np.deg2rad(60.)
     t_ex = np.deg2rad(60.)
     V = Rayleigh(tau=0., omega=0.0)
     RT = RT1(self.I0, t_0, t_ex, self.p_0, self.p_ex, V=V, SRF=self.S)
     Itot, Isurf, Ivol, Iint = RT.calc()
     self.assertEqual(Ivol, 0.)
Example #4
0
 def test_init(self):
     RT = RT1(self.I0,
              self.t_0,
              self.t_ex,
              self.p_0,
              self.p_ex,
              V=self.V,
              SRF=self.S)
     self.assertTrue(RT.t_0 == self.t_0)
Example #5
0
    def test_fn_coefficients_RayCosine(self):
        # test if calculation of fn coefficients is correct
        # for a cosine lobe with reduced number of coefficients
        # this is done by comparing the obtained coefficients
        # against the analytical solution using a Rayleigh volume
        # and isotropic surface scattering phase function
        S = CosineLobe(ncoefs=1, i=5)
        V = Rayleigh(tau=0.7, omega=0.3)
        # --> cosTHETA = 0.

        # tests are using full Volume phase function, but only
        # ncoef times the coefficients from the surface

        t_0 = np.pi / 2.
        t_ex = 0.234234
        p_0 = np.pi / 2.
        p_ex = 0.

        RT = RT1(self.I0, t_0, t_ex, p_0, p_ex, V=V, SRF=S, geometry='vvvv')
        res = RT._fnevals(t_0, p_0, t_ex, p_ex)

        # ncoefs = 1
        # analtytical solution for ncoefs = 1 --> n=0

        a0 = (3. / (16. * np.pi)) * (4. / 3.)
        a2 = (3. / (16. * np.pi)) * (2. / 3.)
        b0 = (15. * np.sqrt(np.pi)) / (16. * gamma(3.5) * gamma(4.))

        # print 'a0:', a0, V._get_legcoef(0)
        # print 'a2:', a2, V._get_legcoef(2)
        # print 'b0: ', b0, S._get_legcoef(0)

        ref0 = 1. / 4. * b0 * (8. * a0 - a2 - 3. * a2 * np.cos(2. * t_0))
        ref2 = 3. / 4. * a2 * b0 * (1. + 3. * np.cos(2. * t_0))

        self.assertTrue(np.allclose([ref0, ref2], [res[0], res[2]]))

        # ncoefs = 2
        # first and third coef should be the same as for ncoefs=1
        S = CosineLobe(ncoefs=2, i=5, NormBRDF=np.pi)
        RT = RT1(self.I0, t_0, t_ex, p_0, p_ex, V=V, SRF=S, geometry='ffff')
        res2 = RT._fnevals(t_0, p_0, t_ex, p_ex)

        self.assertTrue(np.allclose([ref0, ref2], [res2[0], res2[2]]))
Example #6
0
    def test_fn_coefficients_HGIso(self):
        # test if calculation of fn coefficients is correct
        # this is done by comparing the obtained coefficients
        # against the analytical solution using a Rayleigh volume
        # and isotropic surface scattering phase function
        S = Isotropic()

        t_0 = 0.
        t_ex = 0.
        p_0 = 0.
        p_ex = np.pi

        V = HenyeyGreenstein(omega=0.2, tau=1.7, t=0.7, ncoefs=1)
        RT = RT1(self.I0, t_0, t_ex, p_0, p_ex, V=V, SRF=S, geometry='ffff')
        r = RT._fnevals(t_0, p_0, t_ex, p_ex)

        self.assertTrue(np.allclose(r[0], 1. / (2. * np.pi)))
Example #7
0
    def test_example_2_int(self):
        print('Testing Example 2 ...')

        inc = self.inc2

        # ---- evaluation of second example
        V = HenyeyGreenstein(tau=0.7, omega=0.3, t=0.7, ncoefs=20)
        SRF = CosineLobe(ncoefs=10, i=5, NormBRDF=np.pi)

        R = RT1(1.,
                np.deg2rad(inc),
                np.deg2rad(inc),
                np.zeros_like(inc),
                np.full_like(inc, np.pi),
                V=V,
                SRF=SRF,
                geometry='mono')

        self.assertTrue(np.allclose(self.int_num_2, R.calc()[3], atol=1e-6))
Example #8
0
    def test_fn_coefficients_RayIso(self):
        # test if calculation of fn coefficients is correct
        # this is done by comparing the obtained coefficients
        # against the analytical solution using a Rayleigh volume
        # and isotropic surface scattering phase function
        S = Isotropic()
        V = Rayleigh(tau=0.7, omega=0.3)
        t_0 = np.deg2rad(60.)
        t_ex = np.deg2rad(60.)
        p_0 = 0.
        RT = RT1(self.I0, t_0, t_ex, p_0, self.p_ex, V=V, SRF=S)

        # the reference solutions should be (see rayleighisocoefficients.pdf)
        f0 = 3. / (16. * np.pi) * (3. - np.cos(t_0)**2.)
        f1 = 0.
        f2 = 3. / (16. * np.pi) * (3. * np.cos(t_0)**2. - 1.)
        # and all others are 0.

        self.assertTrue(
            np.allclose([f0, f1, f2], RT._fnevals(t_0, p_0, t_ex, self.p_ex)))
Example #9
0
    def test_example_1_int(self):
        print('Testing Example 1 ...')

        inc = self.inc1

        # ---- evaluation of first example
        V = Rayleigh(tau=np.array([0.7]), omega=np.array([0.3]))
        # 11 instead of 10 coefficients used to assure 7 digit precision
        SRF = CosineLobe(ncoefs=11, i=5, NormBRDF=np.array([np.pi]))

        R = RT1(1.,
                np.deg2rad(inc),
                np.deg2rad(inc),
                np.zeros_like(inc),
                np.full_like(inc, np.pi),
                V=V,
                SRF=SRF,
                geometry='mono')

        self.assertTrue(np.allclose(self.int_num_1, R.calc()[3]))
Example #10
0
    def test_example1_fn(self):
        S = CosineLobe(
            ncoefs=10, i=5, NormBRDF=np.pi
        )  # somehow this is only working for ncoefs=1 at the moment!
        V = Rayleigh(tau=0.7, omega=0.3)

        I0 = 1.
        phi_0 = 0.
        #~ phi_0 = np.pi/2.
        phi_ex = np.pi  # backscatter case
        fn = None
        for i in range(0, len(self.inc), self.step):

            #~ if self.n[i] % 2 == 1:
            #~ continue   # todo skipping odds at the moment

            t_0 = self.inc[i]
            t_ex = t_0 * 1.
            RT = RT1(I0, t_0, t_ex, phi_0, phi_ex, RV=V, SRF=S, fn=fn)
            self.assertAlmostEqual(self.inc[i], RT.theta_0)

            mysol = RT._get_fn(int(self.n[i]), RT.theta_0, phi_0)

            print('inc,n,fnref,mysol:', RT.t_0, self.n[i], self.fn[i], mysol)
            fn = RT.fn

            self.assertEqual(
                self.tau[i], V.tau
            )  # check that tau for reference is the same as used for Volume object
            if self.fn[i] == 0.:
                self.assertEqual(mysol, self.fn[i])
            else:
                #~ if np.abs(self.fn[i]) > 1.E-:
                #~ thres = 1.E-3 ## 1 promille threshold
                #~ else:
                thres = 1.E-8  # one percent threshold for very small numbers
                ratio = mysol / self.fn[i]
                self.assertTrue(np.abs(1. - ratio) < thres)
Example #11
0
    def test_example1_Fint(self):
        # backscatter case
        S = CosineLobe(ncoefs=10, i=5, NormBRDF=np.pi)
        V = Rayleigh(tau=0.7, omega=0.3)

        I0 = 1.
        phi_0 = 0.
        phi_ex = np.pi  # backscatter case
        for i in range(0, len(self.inc), self.step):
            print('i,n:', i, self.n[i])
            t_0 = self.inc[i]
            t_ex = t_0 * 1.

            RT = RT1(I0, t_0, t_ex, phi_0, phi_ex, RV=V, SRF=S)
            self.assertEqual(
                self.tau[i], V.tau
            )  # check that tau for reference is the same as used for Volume object

            Fint1 = RT._calc_Fint(t_0, t_ex, phi_0,
                                  phi_ex)  # todo clairfy usage of phi!!!
            Fint2 = RT._calc_Fint(t_ex, t_0, phi_ex, phi_0)

            self.assertEqual(Fint1, Fint2)
Example #12
0
    def performfit(
        self,
        sig0,
        dB,
        Nmeasurements,
        mininc,
        maxinc,
        minincnum,
        maxincnum,
        omin,
        omax,
        taumin,
        taumax,
        rmin,
        rmax,
        tmin,
        tmax,
    ):
        '''
        fucntion adapted from doc/examples/examples_fitting.py

        the values are generated using np.random.seed(0) for all
        calls of np.random...
        '''

        # ---------------------------------------------------------------------
        # ------------------------- DATA-GENERATION ---------------------------

        # generate N arrays of incidence-angles that contain maxincnum
        # values between mininc and maxinc
        inc = np.array([np.deg2rad(np.linspace(mininc, maxinc, maxincnum))] *
                       Nmeasurements)

        np.random.seed(0)  # reset seed to have a reproducible test
        # generate random samples of parameters
        omegadata = np.random.uniform(low=omin,
                                      high=omax,
                                      size=(Nmeasurements, ))

        np.random.seed(0)  # reset seed to have a reproducible test
        taudata = np.random.uniform(low=taumin,
                                    high=taumax,
                                    size=(Nmeasurements, ))

        np.random.seed(0)  # reset seed to have a reproducible test
        rdata = np.random.uniform(low=rmin, high=rmax, size=(Nmeasurements, ))

        np.random.seed(0)  # reset seed to have a reproducible test
        tdata = np.random.uniform(low=tmin, high=tmax, size=(Nmeasurements, ))

        # set tau of Neq measurements to be equal and fit only a single param.
        # for tau to all datasets

        # choose a random number of equal datasets
        if Nmeasurements == 1:
            Neq = 0
            equal_tau_selects = [0]
        else:
            Neq = int(Nmeasurements / 5)

            np.random.seed(0)  # reset seed to have a reproducible test
            equal_tau_selects = np.random.choice(range(Nmeasurements),
                                                 size=Neq + 1,
                                                 replace=False)

        for i in equal_tau_selects:
            # for i in [1,3,5,7,9,11,14,16,17]:
            taudata[i] = taudata[equal_tau_selects[0]]

        # define model that is used to generate the data
        # the choices for tau, omega and NormBRDF have no effect on the
        # dataset since they will be changed to randomly generated values!

        V_data = Rayleigh(tau=0.1, omega=0.1)
        SRF_data = HGsurface(ncoefs=10, t=sp.var('t_data'), a=[1., 1., 1.])

        # setup rt1-object
        # (since the fn-coefficients must still be calculated, one must
        #  specify the arrays for the parameters afterwards)
        R_data = RT1(1.,
                     0.,
                     0.,
                     0.,
                     0.,
                     V=V_data,
                     SRF=SRF_data,
                     geometry='mono',
                     param_dict={'t_data': .5})

        # specify parameters and incidence-angles
        R_data.t_0 = inc
        R_data.p_0 = np.zeros_like(inc)

        R_data.V.omega = omegadata[:, np.newaxis]
        R_data.V.tau = taudata[:, np.newaxis]
        R_data.SRF.NormBRDF = rdata[:, np.newaxis]
        R_data.param_dict = {'t_data': tdata[:, np.newaxis]}
        # calculate the data and add some random noise
        data = R_data.calc()[0]

        np.random.seed(0)  # reset seed to have a reproducible test
        noise = np.random.uniform(low=-np.max(data) / 50.,
                                  high=np.max(data) / 50.,
                                  size=data.shape)
        data = data + noise

        if sig0 is True:
            # convert the calculated results do sigma0
            signorm = 4. * np.pi * np.cos(inc)
            data = signorm * data

        if dB is True:
            # convert the calculated results to dB
            data = 10. * np.log10(data)

        # define the mask for selecting non-rectangular arrays of data (this is
        # done to show that fitting also works for non-rectangular datasets)

        np.random.seed(0)  # reset seed to have a reproducible test
        inc_lengths = np.random.randint(minincnum, maxincnum, Nmeasurements)
        selects = []
        for i in range(Nmeasurements):
            np.random.seed(0)  # reset seed to have a reproducible test
            selects += [
                np.random.choice(range(maxincnum),
                                 inc_lengths[i],
                                 replace=False)
            ]

        # generate dataset of the shape [ [inc_0, data_0], [inc_1, data_1], ..]
        # with inc_i and data_i being arrays of varying length

        dfindex = [nsel for nsel, i in enumerate(selects) for j in i]
        dfinc = [j for i, inc_i in enumerate(inc) for j in inc_i[selects[i]]]
        dfsig = [
            j for i, data_i in enumerate(data) for j in data_i[selects[i]]
        ]

        dataset = pd.DataFrame({
            'inc': dfinc,
            'sig': dfsig
        },
                               index=pd.to_datetime(dfindex, unit='D'))

        # ---------------------------------------------------------------------
        # ------------------------------- FITTING -----------------------------

        def set_V_SRF(t1, N, tau, omega, **kwargs):
            V = Rayleigh(omega=omega, tau=tau)
            SRF = HGsurface(ncoefs=10, t=t1, NormBRDF=N, a=[1., 1., 1.])
            return V, SRF

        # specify additional arguments for scipy.least_squares
        lsq_kwargs = {
            'ftol': 1e-8,
            'gtol': 1e-8,
            'xtol': 1e-8,
            'max_nfev': 500,
            'method': 'trf',
            'tr_solver': 'lsmr',
            'x_scale': 'jac'
        }

        # select random numbers within the boundaries as sart-values
        np.random.seed(0)  # reset seed to have a reproducible test
        ostart = (omax - omin) * np.random.random() + omin
        np.random.seed(0)  # reset seed to have a reproducible test
        tstart = (tmax - tmin) * np.random.random() + tmin
        taustart = (taumax - taumin) * np.random.random() + taumin

        # fit only a single parameter to the datasets that have equal tau
        _, fittau_dyn = np.unique(dataset.index, return_inverse=True)
        fittau_dyn[np.isin(fittau_dyn, equal_tau_selects)] = \
            fittau_dyn[np.isin(fittau_dyn, equal_tau_selects)][0]
        # add manual parameter dynamics for tau
        dataset['tau_dyn'] = fittau_dyn

        # specify the treatment of the parameters in the retrieval procedure
        defdict = {
            't1': [True, tstart, 'D', ([tmin], [tmax])],
            'N': [False, 'auxiliary'],
            'tau': [True, taustart, 'manual', ([taumin], [taumax])],
            'omega': [True, ostart, None, ([omin], [omax])],
            'bsf': [False, 0.]
        }

        # append auxiliary datasets

        N_auxdata = pd.DataFrame({
            'N': rdata
        }, pd.unique(dataset.index)).loc[dataset.index]
        dataset['N'] = N_auxdata

        # initialize fit-class
        testfit = Fits(sig0=sig0,
                       dB=dB,
                       dataset=dataset,
                       defdict=defdict,
                       set_V_SRF=set_V_SRF,
                       lsq_kwargs=lsq_kwargs,
                       setindex='mean',
                       int_Q=True,
                       verbose=2)

        # print model definition
        testfit.model_definition

        # perform the fit
        testfit.performfit(print_progress=True)

        # check if _calc_slope_curv is working
        # TODO this only tests if a result is obtained, not if the result
        # is actually correct !!
        slops, curvs = testfit._calc_slope_curv()

        # provide true-values for comparison of fitted results
        truevals = {
            'tau': taudata,
            'omega': omegadata,
            't1': tdata,
        }

        # ----------- calculate R^2 values and errors of parameters -----------

        # sicne fit[0].fun gives the residuals weighted with respect to
        # weights, the model calculation can be gained via
        # estimates = fit[0].fun/weights + measurements

        # apply mask
        measures = testfit.data[~testfit.mask]
        estimates = testfit.fit_output.fun + measures

        # evaluate linear regression to get r-value etc.
        slope, intercept, r_value, p_value, std_err = linregress(
            estimates, measures)
        # calculate R^2 value
        r2 = r_value**2

        # check if r^2 between original and fitted data is > 0.95
        self.assertTrue(r2 > 0.95, msg=f'r^2 condition not  met , R={r2:4f}')

        # set mean-error values for the derived parameters
        if sig0 is True and dB is False:
            errdict = {'tau': 0.03, 'omega': 0.008, 't1': 0.05}

        if sig0 is False and dB is False:
            errdict = {'tau': 0.03, 'omega': 0.01, 't1': 0.08}

        if sig0 is True and dB is True:
            errdict = {'tau': 0.03, 'omega': 0.01, 't1': 0.09}

        if sig0 is False and dB is True:
            errdict = {'tau': 0.03, 'omega': 0.01, 't1': 0.09}

        fittedvals = testfit.res_df
        for key in truevals:
            err = abs(fittedvals[key] - truevals[key]).mean()
            self.assertTrue(err < errdict[key],
                            msg='derived error' + str(err) + 'too high for ' +
                            str(key))

        return truevals, r2
Example #13
0
    assert False, 'Choose an existing example or specify V and SRF explicitly'

#%%

# specification of measurement-geometry
t_0 = np.deg2rad(inc)
t_ex = t_0 * 1.
p_0 = np.ones_like(t_0) * 0.
p_ex = np.ones_like(t_0) * 0. + np.pi

tic = timeit.default_timer()
R = RT1(I0,
        t_0,
        t_ex,
        p_0,
        p_ex,
        V=V,
        SRF=SRF,
        geometry='mono',
        lambda_backend='cse_seng_sp_newlambdify')

fn = R.fn  # evaluate and store coefficients for faster iteration
_fnevals = R._fnevals  # evaluate and  store coefficients for faster iteration

Itot, Isurf, Ivol, Iint = R.calc()
toc = timeit.default_timer()
print('evaluating print-values took ' + str(toc - tic))

if len(Itot.shape) > 1:
    if Nres == 'all':
        for Nres in range(len(Itot)):
Example #14
0
# define model that is used to generate the data
# the choices for tau, omega and NormBRDF have no effect on the generated data
# since they will be changed to randomly generated values!

V_data = Rayleigh(tau=0.1, omega=0.1)
SRF_data = HGsurface(ncoefs=15, t=sp.var('t_data'), a=[1., 1., 1.])

# setup rt1-object
# (since the fn-coefficients must still be calculated, one must
#  specify the arrays for the parameters afterwards)
R_data = RT1(1.,
             t_0=inc,
             p_0=np.zeros_like(inc),
             t_ex=None,
             p_ex=None,
             V=V_data,
             SRF=SRF_data,
             geometry='mono',
             param_dict={'t_data': .5},
             lambda_backend='cse_seng_sp_newlambdify',
             verbosity=0)

R_data.V.omega = omegadata
R_data.V.tau = taudata
R_data.SRF.NormBRDF = rdata
R_data.param_dict = {'t_data': tdata[:, np.newaxis]}

# calculate the data and add some random noise
data = R_data.calc()[0]
noise = np.random.uniform(low=-np.max(data) / 50.,
                          high=np.max(data) / 50.,
Example #15
0
 def test_surface(self):
     V = Rayleigh(tau=0., omega=0.)
     t_0 = np.deg2rad(60.)
     RT = RT1(4., t_0, self.t_ex, self.p_0, self.p_ex, V=V, SRF=self.S)
     Itot, Isurf, Ivol, Iint = RT.calc()
     self.assertTrue(np.allclose(Isurf, 2. / np.pi, 15))
Example #16
0
    def performfit(
        self,
        sig0,
        dB,
        Nmeasurements,
        mininc,
        maxinc,
        minincnum,
        maxincnum,
        omin,
        omax,
        taumin,
        taumax,
        rmin,
        rmax,
        tmin,
        tmax,
    ):
        '''
        fucntion adapted from doc/examples/examples_fitting.py

        the values are generated using np.random.seed(0) for all
        calls of np.random...
        '''

        # ---------------------------------------------------------------------
        # ------------------------- DATA-GENERATION ---------------------------

        # generate N arrays of incidence-angles that contain maxincnum
        # values between mininc and maxinc
        inc = np.array([np.deg2rad(np.linspace(mininc, maxinc, maxincnum))] *
                       Nmeasurements)

        np.random.seed(0)  # reset seed to have a reproducible test
        # generate random samples of parameters
        omegadata = np.random.uniform(low=omin,
                                      high=omax,
                                      size=(Nmeasurements, ))

        np.random.seed(0)  # reset seed to have a reproducible test
        taudata = np.random.uniform(low=taumin,
                                    high=taumax,
                                    size=(Nmeasurements, ))

        np.random.seed(0)  # reset seed to have a reproducible test
        rdata = np.random.uniform(low=rmin, high=rmax, size=(Nmeasurements, ))

        np.random.seed(0)  # reset seed to have a reproducible test
        tdata = np.random.uniform(low=tmin, high=tmax, size=(Nmeasurements, ))

        # set tau of Neq measurements to be equal and fit only a single param.
        # for tau to all datasets

        # choose a random number of equal datasets
        if Nmeasurements == 1:
            Neq = 0
            equal_tau_selects = [0]
        else:
            Neq = int(Nmeasurements / 5)

            np.random.seed(0)  # reset seed to have a reproducible test
            equal_tau_selects = np.random.choice(range(Nmeasurements),
                                                 size=Neq + 1,
                                                 replace=False)

        for i in equal_tau_selects:
            # for i in [1,3,5,7,9,11,14,16,17]:
            taudata[i] = taudata[equal_tau_selects[0]]

        # define model that is used to generate the data
        # the choices for tau, omega and NormBRDF have no effect on the
        # dataset since they will be changed to randomly generated values!

        V_data = Rayleigh(tau=0.1, omega=0.1)
        SRF_data = HGsurface(ncoefs=10, t=sp.var('t_data'), a=[1., 1., 1.])

        # setup rt1-object
        # (since the fn-coefficients must still be calculated, one must
        #  specify the arrays for the parameters afterwards)
        R_data = RT1(1.,
                     0.,
                     0.,
                     0.,
                     0.,
                     V=V_data,
                     SRF=SRF_data,
                     geometry='mono',
                     param_dict={'t_data': .5})

        # specify parameters and incidence-angles
        R_data.t_0 = inc
        R_data.p_0 = np.zeros_like(inc)

        R_data.V.omega = omegadata
        R_data.V.tau = taudata
        R_data.SRF.NormBRDF = rdata
        R_data.param_dict = {'t_data': tdata[:, np.newaxis]}

        # calculate the data and add some random noise
        data = R_data.calc()[0]

        np.random.seed(0)  # reset seed to have a reproducible test
        noise = np.random.uniform(low=-np.max(data) / 50.,
                                  high=np.max(data) / 50.,
                                  size=data.shape)
        data = data + noise

        if sig0 is True:
            # convert the calculated results do sigma0
            signorm = 4. * np.pi * np.cos(inc)
            data = signorm * data

        if dB is True:
            # convert the calculated results to dB
            data = 10. * np.log10(data)

        # define the mask for selecting non-rectangular arrays of data (this is
        # done to show that fitting also works for non-rectangular datasets)

        np.random.seed(0)  # reset seed to have a reproducible test
        inc_lengths = np.random.randint(minincnum, maxincnum, Nmeasurements)
        selects = []
        for i in range(Nmeasurements):
            np.random.seed(0)  # reset seed to have a reproducible test
            selects += [
                np.random.choice(range(maxincnum),
                                 inc_lengths[i],
                                 replace=False)
            ]

        # generate dataset of the shape [ [inc_0, data_0], [inc_1, data_1], ..]
        # with inc_i and data_i being arrays of varying length
        dataset = []
        for i, row in enumerate(inc):
            dataset = dataset + [[inc[i][selects[i]], data[i][selects[i]]]]

        # ---------------------------------------------------------------------
        # ------------------------------- FITTING -----------------------------

        # initialize fit-class
        testfit = Fits(sig0=sig0, dB=dB)

        # define sympy-symbols for definition of V and SRF
        t1 = sp.Symbol('t1')

        V = Rayleigh(omega=0.1, tau=0.1)
        # values for NormBRDF are set to known values (i.e. rdata)
        SRF = HGsurface(ncoefs=10, t=t1, NormBRDF=rdata, a=[1., 1., 1.])

        # select random numbers within the boundaries as sart-values
        np.random.seed(0)  # reset seed to have a reproducible test
        ostart = (omax - omin) * np.random.random() + omin
        np.random.seed(0)  # reset seed to have a reproducible test
        tstart = (tmax - tmin) * np.random.random() + tmin
        taustart = (taumax - taumin) * np.random.random() + taumin

        # define which parameter should be fitted
        param_dict = {
            'tau': [taustart] * (Nmeasurements - Neq),
            'omega': ostart,
            't1': [tstart] * (Nmeasurements)
        }

        # optionally define fixed parameters
        fixed_dict = {'NormBRDF': rdata}

        # define boundary-conditions
        bounds_dict = {
            't1': ([tmin] * (Nmeasurements), [tmax] * (Nmeasurements)),
            'tau': ([taumin] * (Nmeasurements - Neq),
                    [taumax] * (Nmeasurements - Neq)),
            'omega': ([omin], [omax])
        }

        # setup param_dyn_dict
        param_dyn_dict = {}
        for key in param_dict:
            param_dyn_dict[key] = np.linspace(
                1, len(np.atleast_1d(param_dict[key])), Nmeasurements)

        # fit only a single parameter to the datasets that have equal tau
        for i in equal_tau_selects:
            param_dyn_dict['tau'][i] = param_dyn_dict['tau'][
                equal_tau_selects[0]]

        # provide true-values for comparison of fitted results
        truevals = {
            'tau': taudata,
            'omega': omegadata,
            't1': tdata,
        }

        # perform fit
        fit = testfit.monofit(V=V,
                              SRF=SRF,
                              dataset=dataset,
                              param_dict=param_dict,
                              bounds_dict=bounds_dict,
                              fixed_dict=fixed_dict,
                              param_dyn_dict=param_dyn_dict,
                              verbose=2,
                              ftol=1.e-8,
                              xtol=1.e-8,
                              gtol=1.e-8,
                              x_scale='jac',
                              max_nfev=500)

        # ----------- calculate R^2 values and errors of parameters -----------

        # scatterplot, r2 = testfit.printscatter(fit, pointsize=4,
        #                                       c=fit[3][~fit[4]],
        #                                       cmap='coolwarm',
        #                                       regression=True)

        (res_lsq, R, data, inc, mask, weights, res_dict, start_dict,
         fixed_dict) = fit

        # sicne fit[0].fun gives the residuals weighted with respect to
        # weights, the model calculation can be gained via
        # estimates = fit[0].fun/weights + measurements

        estimates = np.reshape(fit[0].fun / weights, data.shape)

        # apply mask
        measures = data[~mask]
        estimates = estimates[~mask] + measures

        # evaluate linear regression to get r-value etc.
        slope, intercept, r_value, p_value, std_err = linregress(
            estimates, measures)
        # calculate R^2 value
        r2 = r_value**2

        # check if r^2 between original and fitted data is > 0.95
        self.assertTrue(r2 > 0.95, msg='r^2 condition not  met')

        # set mean-error values for the derived parameters
        if sig0 is True and dB is False:
            errdict = {'tau': 0.03, 'omega': 0.008, 't1': 0.05}

        if sig0 is False and dB is False:
            errdict = {'tau': 0.03, 'omega': 0.01, 't1': 0.08}

        if sig0 is True and dB is True:
            errdict = {'tau': 0.03, 'omega': 0.01, 't1': 0.09}

        if sig0 is False and dB is True:
            errdict = {'tau': 0.03, 'omega': 0.01, 't1': 0.09}

        for key in truevals:
            err = abs(fit[6][key] - truevals[key]).mean()
            self.assertTrue(err < errdict[key],
                            msg='derived error' + str(err) + 'too high for ' +
                            str(key))

        return truevals, fit, r2
Example #17
0
import time

# some speed benchmarking ...

S = CosineLobe(ncoefs=10, i=5)
V = Rayleigh(tau=0.7, omega=0.3)

I0 = 1.

theta_i = np.pi / 2.
theta_ex = 0.234234
phi_i = np.pi / 2.
phi_ex = 0.

RT = RT1(I0, theta_i, theta_ex, phi_i, phi_ex, RV=V, SRF=S, geometry='vvvv')
#~ print RT.fn
#~ print len(RT.fn)

#~ start = time.time()
#~ for i in xrange(10):
#~ for n in xrange(len(RT.fn)):
#~ RT._get_fn(n, theta_i, phi_i, theta_ex, phi_ex)
#~ end = time.time()
#~ print('Time for get_fn (10x): ', end - start)

start = time.time()
for i in xrange(10):
    RT.interaction()
end = time.time()
print('Time for interaction (10x): ', end - start)