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.)
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
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.)
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)
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]]))
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)))
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))
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)))
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]))
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)
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)
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
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)):
# 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.,
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))
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
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)