def test_propagated_correlation(self): '''Tests setting covariance between two objects. ''' x = e.Measurement(10, 1) y = e.Measurement(20, 2) x.set_correlation(y, 0.5) self.assertEqual(x.get_correlation(y), 0.5)
def test_set_covariance(self): '''Tests setting covariance between two objects. ''' x = e.Measurement(10, 1) y = e.Measurement(20, 2) x.set_covariance(y, 2) self.assertEqual(x.get_covariance(y), 2)
def test_array_covariance(self): '''Tests covariance calculated from the data arrays from the two Measurement objects. ''' x = e.Measurement([1, 2, 3, 4, 5]) y = e.Measurement([2, 4, 6, 8, 10]) self.assertEqual(x.get_covariance(y), 5)
def test_set_correlation(self): '''Tests setting covariance between two objects. ''' x = e.Measurement([1, 2, 3, 4]) y = e.Measurement([2, 3, 4, 1]) result = x * y + x result.get_covariance(y) self.assertAlmostEqual(x.get_correlation(y), -.2)
def test_array_correlation(self): '''Tests covariance calculated from the data arrays from the two Measurement objects. ''' x = e.Measurement([1, 2, 3, 4, 5]) y = e.Measurement([2, 4, 6, 8, 10]) x.get_covariance(y) self.assertAlmostEqual(x.get_correlation(y), 1, places=7)
def test_propagated_covariance(self): '''Tests the propagation of correlation between two objects through the derivative method. ''' x = e.Measurement(10, 1) y = e.Measurement(20, 2) x.set_covariance(y, 2) result = x * y + x self.assertEqual(result.get_covariance(y), 82)
def test3(): '''Test of elementary operators. ''' x = e.Measurement(10, 1) y = e.Measurement(20, 2) assert x+y == x.mean+y.mean assert x-y == x.mean-y.mean assert x*y == x.mean*y.mean assert x/y == x.mean/y.mean assert x**y == x.mean**y.mean
def test_unit_parsing(self): '''Tests parsing of unit strings. ''' test1 = e.Measurement(10, 1, units='kg*m/s^2') test2 = e.Measurement(10, 1, units='kg^1m^1s^-2') test3 = e.Measurement(10, 1, units='kg^1*m^1/s^2') units = {'kg': 1, 'm': 1, 's': -2} self.assertEqual(test1.units, units) self.assertEqual(test2.units, units) self.assertEqual(test3.units, units)
def test4(): '''Test of derivative method. ''' x = e.Measurement(3, 0.4) y = e.Measurement(12, 1) assert (x+y).get_derivative(y) == 1 assert (x-y).get_derivative(x) == 1 assert (x*y).get_derivative(y) == x.mean assert (x/y).get_derivative(x) == 1/y.mean assert (x**y).get_derivative(x) == y.mean*x.mean**(y.mean-1) assert e.sin(x).get_derivative(x) == m.cos(x.mean) assert e.cos(x).get_derivative(x) == -m.sin(x.mean) assert e.tan(x).get_derivative(x) == m.cos(x.mean)**-2 assert e.exp(x).get_derivative(x) == m.exp(x.mean)
def test_unit_propagation(self): '''Tests unit propagation of Measurements ''' L = e.Measurement(12, 1, name='Distance', units='m') v = e.Measurement(5, 0.1, name='Velocity', units=['m', 1, 's', -1]) t = L / v self.assertEqual(L.units, {'m': 1}) self.assertEqual(v.units, {'s': -1, 'm': 1}) self.assertEqual(t.units, {'s': 1}) x = e.Measurement(2, 0.3, name='Length', units='m') x2 = x + L self.assertEqual(x2.units, {'m': 1}) L = v * t self.assertEqual(L.units, {'m': 1})
def test_derivative(self): '''Tests derivative of functions of Measurement objects ''' x = e.Measurement(3, 0.4) y = e.Measurement(12, 1) self.assertEqual((x + y).get_derivative(y), 1) self.assertEqual((x - y).get_derivative(x), 1) self.assertEqual((x * y).get_derivative(y), x.mean) self.assertEqual((x / y).get_derivative(x), 1 / y.mean) self.assertEqual((x**y).get_derivative(x), y.mean * x.mean**(y.mean - 1)) self.assertEqual(e.sin(x).get_derivative(x), m.cos(x.mean)) self.assertEqual(e.cos(x).get_derivative(x), -m.sin(x.mean)) self.assertEqual(e.tan(x).get_derivative(x), m.cos(x.mean)**-2) self.assertEqual(e.exp(x).get_derivative(x), m.exp(x.mean))
def test6(): '''Test naming and unit propagation ''' L = e.Measurement(12, 1, name='Distance', units='m') v = e.Measurement(5, 0.1, name='Velocity', units=['m', 1, 's', -1]) t = L/v assert L.units == {'m': 1} assert v.units == {'s': -1, 'm': 1} assert t.units == {'s': 1} x = e.Measurement(2, 0.3, name='Length', units='m') x2 = x + L assert x2.units == {'m': 1} L = v*t assert L.units == {'m': 1}
def test1(): '''Test of data entry methods. ''' x = e.Measurement(10, 1) assert x.mean == 10 assert x.std == 1 x = e.Measurement([9, 10, 11], [1]) assert x.mean == 10 x = e.Measurement(9, 10, 11) assert x.mean == 10 assert x.std == 1 x = e.Measurement([9, 1], [10, 1], [11, 1]) assert x.mean == 10
def test8(): '''Test of public methods to return Measurement object attributes. ''' x = e.Measurement(10, 1, name='x', units='m') y = e.Measurement(13, 2, name='y', units=['m', 1]) a = x+y d = e.Measurement(21, 1, name='Distance', units='m') t = e.Measurement(7, 2, name='Interval', units='s') v = d/t assert x.get_mean() == 10 assert y.get_error() == 2 assert a.get_derivative(x) == 1 assert a.get_name() == 'x+y' assert a.get_units() == 'm' assert v.get_units() == 'm^1 s^-1 ' or v.get_units() == 's^-1 m^1 '
def test_measurement_functions(self): '''Tests mathematical functions on Measurement objects ''' x = e.Measurement(3.2, 0.01) y = e.Measurement(0.23, 0.04) self.assertEqual(e.sin(x), m.sin(x.mean)) self.assertEqual(e.cos(x), m.cos(x.mean)) self.assertEqual(e.tan(x), m.tan(x.mean)) self.assertEqual(e.csc(x), 1 / m.sin(x.mean)) self.assertEqual(e.sec(x), 1 / m.cos(x.mean)) self.assertEqual(e.cot(x), 1 / m.tan(x.mean)) self.assertEqual(e.exp(x), m.exp(x.mean)) self.assertEqual(e.log(x), m.log(x.mean)) self.assertEqual(e.asin(y), m.asin(y.mean)) self.assertEqual(e.acos(y), m.acos(y.mean)) self.assertEqual(e.atan(x), m.atan(x.mean))
def test2(): '''Test of elementary functions. ''' x = e.Measurement(10, 1) y = e.Measurement(0, 0.1) assert e.sin(x) == m.sin(x.mean) assert e.cos(x) == m.cos(x.mean) assert e.tan(x) == m.tan(x.mean) assert e.csc(x) == 1/m.sin(x.mean) assert e.sec(x) == 1/m.cos(x.mean) assert e.cot(x) == 1/m.tan(x.mean) assert e.exp(x) == m.exp(x.mean) assert e.log(x) == m.log(x.mean) assert e.asin(y) == m.asin(y.mean) assert e.acos(y) == m.acos(y.mean) assert e.atan(x) == m.atan(x.mean)
def test_public_methods(self): '''Test of public methods to return Measurement object attributes. ''' x = e.Measurement(10, 1, name='x', units='m') y = e.Measurement(13, 2, name='y', units=['m', 1]) a = x + y d = e.Measurement(21, 1, name='Distance', units='m') t = e.Measurement(7, 2, name='Interval', units='s') v = d / t self.assertEqual(x.mean, 10) self.assertEqual(y.std, 2) self.assertEqual(a.get_derivative(x), 1) self.assertEqual(a.name, 'x+y') self.assertEqual(a.get_units_str(), 'm') self.assertTrue(v.get_units_str() == 'm^1 s^-1 ' or v.get_units_str() == 's^-1 m^1 ')
def test_single_measurement(self): '''Tests creating a Measurement from a single measurement with uncertainty ''' x = e.Measurement(10, 1) self.assertEqual(x.mean, 10) self.assertEqual(x.std, 1) x.mean = 3 x.std = 0.1 self.assertEqual(x.mean, 3) self.assertEqual(x.std, 0.1)
def test_append(self): '''Tests appending new values to a MeasurementArray. ''' x = e.MeasurementArray([3, 2], 1) x = x.append(1) to_append = e.Measurement(4, 1) x = x.append(to_append) self.assertEqual(x[2], 1) self.assertEqual(x[3], to_append)
def test_insert(self): '''Tests inserting new values into a MeasurementArray. ''' x = e.MeasurementArray([3, 1], 1) x = x.insert(1, 2) to_insert = e.Measurement(4, 1) x = x.insert(2, to_insert) self.assertEqual(x[1], 2) self.assertEqual(x[2], to_insert)
def test_measurement_comparisons(self): '''Tests comparisons of Measurement objects ''' x = e.Measurement(3.2, 0.01) y = e.Measurement(0.23, 0.04) z = e.Measurement(0.23, 0.01) self.assertFalse(x == y) self.assertFalse(y == x) self.assertTrue(y == z) self.assertTrue(z == y) self.assertFalse(x <= y) self.assertFalse(y >= x) self.assertTrue(y >= z) self.assertTrue(z <= y) self.assertTrue(x > y) self.assertTrue(y < x) self.assertFalse(y > z) self.assertFalse(z < y)
def test_printing(self): '''Test of printing methods and sigfigs. ''' # Test of standard printing without figs ################################## x = e.Measurement(12563.2, 1.637) e.set_print_style('Latex') self.assertEqual(x.__str__(), '(12563 \pm 2)') x = e.Measurement(156.2, 12) e.set_print_style('Default') self.assertEqual(x.__str__(), '160 +/- 10') x = e.Measurement(1360.2, 16.9) e.set_print_style('Sci') self.assertEqual(x.__str__(), '(136 +/- 2)*10^(1)') # Test of figs set on central value ####################################### e.set_print_style('Default', 3) x = e.Measurement(12.3, 0.1, name='x') self.assertEqual(x.__str__(), 'x = 12.3 +/- 0.1') e.set_print_style('Latex', 4) x = e.Measurement(12.3, 0.156, name='x') self.assertEqual(x.__str__(), 'x = (1230 \pm 16)*10^{-2}') e.set_print_style('Sci', 5) x = e.Measurement(123.456, 0.789, name='x') self.assertEqual(x.__str__(), 'x = (12346 +/- 79)*10^(-2)') # Test of figs set on uncertainty ######################################### x = e.Measurement(12.35, 0.1237) e.set_print_style('Default') e.set_sigfigs_error() self.assertEqual(x.__str__(), '12.350 +/- 0.124') x = e.Measurement(120, 0.1237795) e.set_print_style('Latex') e.set_sigfigs_error(5) self.assertEqual(x.__str__(), '(12000000 \pm 12378)*10^{-5}') x = e.Measurement(12.38, 0.1237) e.set_print_style('Sci') e.set_sigfigs_error(1) self.assertEqual(x.__str__(), '(124 +/- 1)*10^(-1)')
def test_multiple_measurements(self): '''Tests creating a Measurement from a multiple measurements ''' x = e.Measurement([9, 10, 11]) self.assertEqual(x.mean, 10) self.assertEqual(x.std, 1)
def test_measurement_elementary(self): '''Tests elementary operations on Measurement objects ''' x = e.Measurement(2, 0.01) y = e.Measurement(5, 0.2) self.assertEqual(x + y, e.Measurement(7, 0.2)) self.assertEqual(y + x, e.Measurement(7, 0.2)) self.assertEqual(x - y, e.Measurement(-3, .2)) self.assertEqual(y - x, e.Measurement(3, .2)) self.assertEqual(x * y, e.Measurement(10, 0.4)) self.assertEqual(y * x, e.Measurement(10, 0.4)) self.assertEqual(x / y, e.Measurement(.4, .02)) self.assertEqual(y / x, e.Measurement(2.5, 0.1)) self.assertEqual(x**y, e.Measurement(32, 5)) self.assertEqual(y**x, e.Measurement(25, 2))
def fit(self, dataset, fit_range=None, fit_count=0, name=None): ''' Perform a fit of the fit_function to a data set. :param dataset: The dataset to be fit. :type dataset: XYDataSet :param fit_range: The range to plot the fit on. :type fit_range: list :param fit_count: The number of the fit. :type fit_count: int :param name: The name of the fit function. :type name: str :returns: The parameters of the fit. :rtype: Measurement_Array ''' if self.fit_function is None: print("Error: fit function not set!") return #Grab the data xdata = dataset.xdata ydata = dataset.ydata xerr = dataset.xerr yerr = dataset.yerr nz = np.count_nonzero(yerr) if nz < ydata.size and nz != 0: print( "Warning: some errors on data are zero, switching to MC errors" ) dataset.y.error_method = "MC" yerr = dataset.y.stds #now, check again nz = np.count_nonzero(yerr) if nz < ydata.size and nz != 0: yerr[yerr == 0] = ydata[yerr == 0] / 1000000 #We're ok, modify the errors in the dataset to be the MC ones else: dataset.yerr = yerr #If user specified a fit range, reduce the data: if type(fit_range) in ARRAY and len(fit_range) is 2: indices = np.where( np.logical_and(xdata >= fit_range[0], xdata <= fit_range[1])) xdata = xdata[indices] ydata = ydata[indices] xerr = xerr[indices] yerr = yerr[indices] #if the x errors are not zero, convert them to equivalent errors in y #TODO: check the math on this... #The maximum number of function evaluations maxfev = 200 * (xdata.size + 1) if q.settings[ "fit_max_fcn_calls"] == -1 else q.settings["fit_max_fcn_calls"] try: warns = [] with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always", sp.OptimizeWarning) self.fit_pars, self.fit_pcov = sp.curve_fit(self.fit_function, xdata, ydata, sigma=yerr, p0=self.parguess, maxfev=maxfev) warns = w if len(warns) > 0 and (self.fit_function == Rlinear or self.fit_function == Rpolynomial): p, V = np.polyfit(x=xdata, y=ydata, deg=self.fit_npars - 1, cov=True, w=1 / yerr) self.fit_pars = p[::-1] self.fit_pcov = np.flipud(np.fliplr(V)) self.fit_pars_err = np.sqrt(np.diag(self.fit_pcov)) except RuntimeError: print( "Error: Fit could not converge; are the y errors too small? Is the function defined?" ) print("Is the parameter guess good?") return None # Use derivative method to factor x error into fit if xerr.nonzero()[0].size: yerr_eff = np.sqrt((yerr**2 + np.multiply( xerr, num_der(lambda x: self.fit_function(x, *self.fit_pars), xdata)) **2)) try: warns = [] with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always", sp.OptimizeWarning) self.fit_pars, self.fit_pcov = sp.curve_fit( self.fit_function, xdata, ydata, sigma=yerr_eff, p0=self.parguess, maxfev=maxfev) warns = w if len(warns) == 1 and (self.fit_function == Rlinear or self.fit_function == Rpolynomial): p, V = np.polyfit(x=xdata, y=ydata, deg=self.fit_npars - 1, cov=True, w=1 / yerr) self.fit_pars = p[::-1] self.fit_pcov = np.flipud(np.fliplr(V)) self.fit_pars_err = np.sqrt(np.diag(self.fit_pcov)) except RuntimeError: print( "Error: Fit could not converge; are the y errors too small? Is the function defined?" ) print("Is the parameter guess good?") return None #this should already be true, but let's be sure: self.fit_npars = self.fit_pars.size #This is to catch the case of scipy.optimize failing to determin #the covariance matrix for i in range(self.fit_npars): if self.fit_pars_err[i] == float( 'inf') or self.fit_pars_err[i] == float('nan'): #print("Warning: Error for fit parameter",i,"cannot be trusted") self.fit_pars_err[i] = 0 for j in range(self.fit_npars): if self.fit_pcov[i][j] == float( 'inf') or self.fit_pcov[i][j] == float('nan'): #print("Warning: Covariance between parameters",i,j,"cannot be trusted") self.fit_pcov[i][j] = 0. parnames = dataset.name + "_" + self.fit_function_name + "_fit{}".format( fit_count) + "_fitpars" self.fit_parameters = qe.MeasurementArray(self.fit_npars, name=parnames) for i in range(self.fit_npars): if self.fit_function_name is 'gaussian': if i is 0: name = 'mean' elif i is 1: name = 'sigma' elif i == 2: name = 'normalization' elif self.fit_function_name is 'linear': if i is 0: name = 'intercept' elif i is 1: name = 'slope' elif self.fit_function_name is 'exponential': if i is 0: name = 'amplitude' elif i is 1: name = 'decay-constant' else: name = 'par%d' % (i) name = parnames + "_" + name self.fit_parameters[i] = qe.Measurement(self.fit_pars[i], self.fit_pars_err[i], name=name) for i in range(self.fit_npars): for j in range(i + 1, self.fit_npars): self.fit_parameters[i].set_covariance(self.fit_parameters[j], self.fit_pcov[i][j]) #Calculate the residuals: yfit = self.fit_function(dataset.xdata, *self.fit_pars) self.fit_yres = qe.MeasurementArray((dataset.ydata - yfit), dataset.yerr) #Calculate the chi-squared: self.fit_chi2 = 0 for i in range(xdata.size): if self.fit_yres[i].std != 0: self.fit_chi2 += (self.fit_yres[i].mean / self.fit_yres[i].std)**2 self.fit_ndof = self.fit_yres.size - self.fit_npars - 1 return self.fit_parameters