def test_initial_data_processing(self): """ Test whether the background and scale are handled properly when creating an InvariantCalculator object """ length = len(self.data.x) self.assertEqual(length, len(self.data.y)) inv = invariant.InvariantCalculator(self.data) self.assertEqual(length, len(inv._data.x)) self.assertEqual(inv._data.x[0], self.data.x[0]) # Now the same thing with a background value bck = 0.1 inv = invariant.InvariantCalculator(self.data, background=bck) self.assertEqual(inv._background, bck) self.assertEqual(length, len(inv._data.x)) self.assertEqual(inv._data.y[0] + bck, self.data.y[0]) # Now the same thing with a scale value scale = 0.1 inv = invariant.InvariantCalculator(self.data, scale=scale) self.assertEqual(inv._scale, scale) self.assertEqual(length, len(inv._data.x)) self.assertAlmostEqual(inv._data.y[0] / scale, self.data.y[0], 7)
def test_use_case_3(self): """ Invariant with low-Q extrapolation """ # Create invariant object. Background and scale left as defaults. inv = invariant.InvariantCalculator(data=self.data) # Set the extrapolation parameters for the low-Q range # The npts parameter should have a good default. # The range parameter should be 'high' or 'low' # The function parameter should default to None. If it is None, # the method should pick a good default (Guinier at low-Q and 1/q^4 at high-Q). # The method should also check for consistency of the extrapolation and function # parameters. For instance, you might not want to allow 'high' and 'guinier'. # The power parameter (not shown below) should default to 4. inv.set_extrapolation(range='low', npts=10, function='guinier') # The version of the call without error # At this point, we could still compute Q* without extrapolation by calling # get_qstar with arguments, or with extrapolation=None. qstar = inv.get_qstar(extrapolation='low') # The version of the call with error qstar, qstar_err = inv.get_qstar_with_error(extrapolation='low') # Get the volume fraction and surface v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) # Test results self.assertAlmostEquals(qstar, 7.49e-5, 1) self.assertAlmostEquals(v, 0.005648401, 4) self.assertAlmostEquals(s, 941.7452, 3)
def test_use_case_6(self): """ Invariant with high-Q extrapolation """ # Create invariant object. Background and scale left as defaults. inv = invariant.InvariantCalculator(data=self.data) # Set the extrapolation parameters for the high-Q range inv.set_extrapolation(range='low', npts=10, function='power_law', power=4) # The version of the call without error # The function parameter defaults to None, then is picked to be 'power_law' for extrapolation='high' qstar = inv.get_qstar(extrapolation='low') # The version of the call with error qstar, qstar_err = inv.get_qstar_with_error(extrapolation='low') # Get the volume fraction and surface v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) # Test results self.assertAlmostEquals(qstar, 7.49e-5, 2) self.assertAlmostEquals(v, 0.005952674, 3) self.assertAlmostEquals(s, 941.7452, 3)
def test_qstar_low_q_guinier(self): """ Test low-q extrapolation with a Guinier """ inv = invariant.InvariantCalculator(self.data) # Basic sanity check _qstar = inv.get_qstar() qstar, dqstar = inv.get_qstar_with_error() self.assertEqual(qstar, _qstar) # Low-Q Extrapolation # Check that the returned invariant is what we expect given # the result we got without extrapolation inv.set_extrapolation('low', npts=10, function='guinier') qs_extr, dqs_extr = inv.get_qstar_with_error('low') delta_qs_extr, delta_dqs_extr = inv.get_qstar_low() self.assertEqual(qs_extr, _qstar + delta_qs_extr) self.assertEqual( dqs_extr, math.sqrt(dqstar * dqstar + delta_dqs_extr * delta_dqs_extr)) # We don't expect the extrapolated invariant to be very far from the # result without extrapolation. Let's test for a result within 10%. self.assertTrue(math.fabs(qs_extr - qstar) / qstar < 0.1) # Check that the two results are consistent within errors # Note that the error on the extrapolated value takes into account # a systematic error for the fact that we may not know the shape of I(q) at low Q. self.assertTrue(math.fabs(qs_extr - qstar) < dqs_extr)
def test_use_case_1(self): """ Invariant without extrapolation """ # Create invariant object. Background and scale left as defaults. inv = invariant.InvariantCalculator(data=self.data) # We have to be able to tell the InvariantCalculator whether we want the # extrapolation or not. By default, when the user doesn't specify, we # should compute Q* without extrapolation. That's what should be done in __init__. # We call get_qstar() with no argument, which signifies that we do NOT # want extrapolation. qstar = inv.get_qstar() # The volume fraction and surface use Q*. That means that the following # methods should check that Q* has been computed. If not, it should # compute it by calling get_qstare(), leaving the parameters as default. v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) # Test results self.assertAlmostEquals(qstar, 7.48959e-5, 2) self.assertAlmostEquals(v, 0.005644689, 4) self.assertAlmostEquals(s, 941.7452, 3)
def test_low_data(self): """ Invariant with low-Q extrapolation with slit smear """ # Create invariant object. Background and scale left as defaults. inv = invariant.InvariantCalculator(data=self.data) # Set the extrapolation parameters for the low-Q range inv.set_extrapolation(range='low', npts=self.npts, function='guinier') self.assertEqual(inv._low_extrapolation_npts, self.npts) self.assertEqual(inv._low_extrapolation_function.__class__, invariant.Guinier) # Data boundaries for fiiting qmin = inv._data.x[0] qmax = inv._data.x[inv._low_extrapolation_npts - 1] # Extrapolate the low-Q data inv._fit(model=inv._low_extrapolation_function, qmin=qmin, qmax=qmax, power=inv._low_extrapolation_power) qstar = inv.get_qstar(extrapolation='low') #Compution the y 's coming out of the invariant when computing extrapolated #low data . expect the fit engine to have been already called and the guinier # to have the radius and the scale fitted data_in_range = inv.get_extra_data_low( q_start=self.data.x[0], npts=inv._low_extrapolation_npts) test_y = data_in_range.y self.assert_( len(test_y) == len(self.data.y[:inv._low_extrapolation_npts])) for i in range(inv._low_extrapolation_npts): value = math.fabs(test_y[i] - self.data.y[i]) / self.data.y[i] self.assert_(value < 0.001)
def test_low_q(self): """ Invariant with low-Q extrapolation """ # Create invariant object. Background and scale left as defaults. inv = invariant.InvariantCalculator(data=self.data) # Set the extrapolation parameters for the low-Q range inv.set_extrapolation(range='low', npts=20, function='power_law') self.assertEqual(inv._low_extrapolation_npts, 20) self.assertEqual(inv._low_extrapolation_function.__class__, invariant.PowerLaw) # Data boundaries for fitting qmin = inv._data.x[0] qmax = inv._data.x[inv._low_extrapolation_npts - 1] # Extrapolate the low-Q data inv._fit(model=inv._low_extrapolation_function, qmin=qmin, qmax=qmax, power=inv._low_extrapolation_power) self.assertAlmostEqual(self.scale, inv._low_extrapolation_function.scale, 6) self.assertAlmostEqual(self.m, inv._low_extrapolation_function.power, 6)
def test_low_q(self): """ Invariant with low-Q extrapolation with slit smear """ # Create invariant object. Background and scale left as defaults. inv = invariant.InvariantCalculator(data=self.data) # Set the extrapolation parameters for the low-Q range inv.set_extrapolation(range='low', npts=self.npts, function='guinier') self.assertEqual(inv._low_extrapolation_npts, self.npts) self.assertEqual(inv._low_extrapolation_function.__class__, invariant.Guinier) # Data boundaries for fiiting qmin = inv._data.x[0] qmax = inv._data.x[inv._low_extrapolation_npts - 1] # Extrapolate the low-Q data inv._fit(model=inv._low_extrapolation_function, qmin=qmin, qmax=qmax, power=inv._low_extrapolation_power) qstar = inv.get_qstar(extrapolation='low') test_y = inv._low_extrapolation_function.evaluate_model( x=self.data.x[:inv._low_extrapolation_npts]) self.assert_( len(test_y) == len(self.data.y[:inv._low_extrapolation_npts])) for i in range(inv._low_extrapolation_npts): value = math.fabs(test_y[i] - self.data.y[i]) / self.data.y[i] self.assert_(value < 0.001)
def test_use_case_5(self): """ Invariant with both high- and low-Q extrapolation """ # Create invariant object. Background and scale left as defaults. inv = invariant.InvariantCalculator(data=self.data_q_smear) # Set the extrapolation parameters for the low- and high-Q ranges inv.set_extrapolation(range='low', npts=10, function='guinier') inv.set_extrapolation(range='high', npts=10, function='power_law', power=4) # The version of the call without error # The function parameter defaults to None, then is picked to be 'power_law' for extrapolation='high' qstar = inv.get_qstar(extrapolation='both') # The version of the call with error qstar, qstar_err = inv.get_qstar_with_error(extrapolation='both') # Get the volume fraction and surface # WHY SHOULD THIS FAIL? #self.assertRaises(RuntimeError, inv.get_volume_fraction_with_error, 2.6e-6) #self.assertRaises(RuntimeError, inv.get_surface_with_error, 2.6e-6, 2) # Test results self.assertAlmostEquals(qstar, 0.00460319, 3)
def test_qstar_high_q(self): """ Test high-q extrapolation """ inv = invariant.InvariantCalculator(self.data) # Basic sanity check _qstar = inv.get_qstar() qstar, dqstar = inv.get_qstar_with_error() self.assertEqual(qstar, _qstar) # High-Q Extrapolation # Check that the returned invariant is what we expect given # the result we got without extrapolation inv.set_extrapolation('high', npts=20, function='power_law') qs_extr, dqs_extr = inv.get_qstar_with_error('high') delta_qs_extr, delta_dqs_extr = inv.get_qstar_high() # From previous analysis using SasView, we expect an exponent of about 3 self.assertTrue( math.fabs(inv._high_extrapolation_function.power - 3) < 0.1) self.assertEqual(qs_extr, _qstar + delta_qs_extr) self.assertAlmostEqual( dqs_extr, math.sqrt(dqstar * dqstar + delta_dqs_extr * delta_dqs_extr), 10) # We don't expect the extrapolated invariant to be very far from the # result without extrapolation. Let's test for a result within 10%. #TODO: verify whether this test really makes sense #self.assertTrue(math.fabs(qs_extr-qstar)/qstar<0.1) # Check that the two results are consistent within errors self.assertTrue(math.fabs(qs_extr - qstar) < dqs_extr)
def test_use_case_4(self): """ Invariant with high-Q extrapolation """ # Create invariant object. Background and scale left as defaults. inv = invariant.InvariantCalculator(data=self.data_q_smear) # Set the extrapolation parameters for the high-Q range inv.set_extrapolation(range='high', npts=10, function='power_law', power=4) # The version of the call without error qstar = inv.get_qstar(extrapolation='high') # The version of the call with error qstar, qstar_err = inv.get_qstar_with_error(extrapolation='high') # Get the volume fraction and surface # WHY SHOULD THIS FAIL? #self.assertRaises(RuntimeError, inv.get_volume_fraction_with_error, 2.6e-6) # Check that an exception is raised when the 'surface' is not defined # WHY SHOULD THIS FAIL? #self.assertRaises(RuntimeError, inv.get_surface_with_error, 2.6e-6, 2) # Test results self.assertAlmostEquals(qstar, 0.0045773, 2)
def test_use_case_1(self): """ Invariant without extrapolation """ inv = invariant.InvariantCalculator(data=self.data_q_smear) qstar = inv.get_qstar() v = inv.get_volume_fraction(contrast=2.6e-6) s = inv.get_surface(contrast=2.6e-6, porod_const=2) # Test results self.assertAlmostEquals(qstar, 1.361677e-3, 4) self.assertAlmostEquals(v, 0.115352622, 2) self.assertAlmostEquals(s, 941.7452, 3)
def test_qstar_low_q_power_law(self): """ Test low-q extrapolation with a power law """ inv = invariant.InvariantCalculator(self.data) # Basic sanity check _qstar = inv.get_qstar() qstar, dqstar = inv.get_qstar_with_error() self.assertEqual(qstar, _qstar) # Low-Q Extrapolation # Check that the returned invariant is what we expect given inv.set_extrapolation('low', npts=10, function='power_law') qs_extr, dqs_extr = inv.get_qstar_with_error('low') delta_qs_extr, delta_dqs_extr = inv.get_qstar_low() # A fit using SasView gives 0.0655 for the value of the exponent self.assertAlmostEqual(inv._low_extrapolation_function.power, 0.0655, 3) if False: npts = len(inv._data.x) - 1 import matplotlib.pyplot as plt plt.loglog(inv._data.x[:npts], inv._data.y[:npts], 'o', label='Original data', markersize=10) plt.loglog(inv._data.x[:npts], inv._low_extrapolation_function.evaluate_model( inv._data.x[:npts]), 'r', label='Fitted line') plt.legend() plt.show() self.assertEqual(qs_extr, _qstar + delta_qs_extr) self.assertAlmostEqual( dqs_extr, math.sqrt(dqstar * dqstar + delta_dqs_extr * delta_dqs_extr), 15) # We don't expect the extrapolated invariant to be very far from the # result without extrapolation. Let's test for a result within 10%. self.assertTrue(math.fabs(qs_extr - qstar) / qstar < 0.1) # Check that the two results are consistent within errors # Note that the error on the extrapolated value takes into account # a systematic error for the fact that we may not know the shape of I(q) at low Q. self.assertTrue(math.fabs(qs_extr - qstar) < dqs_extr)
def test_error_treatment(self): x = numpy.asarray(numpy.asarray([0, 1, 2, 3])) y = numpy.asarray(numpy.asarray([1, 1, 1, 1])) # These are all the values of the dy array that would cause # us to set all dy values to 1.0 at __init__ time. dy_list = [[], None, [0, 0, 0, 0]] for dy in dy_list: data = Data1D(x=x, y=y, dy=dy) inv = invariant.InvariantCalculator(data) self.assertEqual(len(inv._data.x), len(inv._data.dy)) self.assertEqual(len(inv._data.dy), 4) for i in range(4): self.assertEqual(inv._data.dy[i], 1)
def test_use_case_2(self): """ Invariant without extrapolation. Invariant, volume fraction and surface are given with errors. """ # Create invariant object. Background and scale left as defaults. inv = invariant.InvariantCalculator(data=self.data_q_smear) # Get the invariant with errors qstar, qstar_err = inv.get_qstar_with_error() # Get the volume fraction and surface v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) # Test results self.assertAlmostEquals(qstar, 1.361677e-3, 4) self.assertAlmostEquals(v, 0.115352622, 2) self.assertAlmostEquals(s, 941.7452, 3)
def test_use_case_2(self): """ Invariant without extrapolation. Invariant, volume fraction and surface are given with errors. """ # Create invariant object. Background and scale left as defaults. inv = invariant.InvariantCalculator(data=self.data) # Get the invariant with errors qstar, qstar_err = inv.get_qstar_with_error() # The volume fraction and surface use Q*. That means that the following # methods should check that Q* has been computed. If not, it should # compute it by calling get_qstare(), leaving the parameters as default. v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) # Test results self.assertAlmostEquals(qstar, 7.48959e-5, 2) self.assertAlmostEquals(v, 0.005644689, 1) self.assertAlmostEquals(s, 941.7452, 3)
def test_use_case_3(self): """ Invariant with low-Q extrapolation """ # Create invariant object. Background and scale left as defaults. inv = invariant.InvariantCalculator(data=self.data_q_smear) # Set the extrapolation parameters for the low-Q range inv.set_extrapolation(range='low', npts=20, function='guinier') # The version of the call without error qstar = inv.get_qstar(extrapolation='low') # The version of the call with error qstar, qstar_err = inv.get_qstar_with_error(extrapolation='low') # Get the volume fraction and surface v, dv = inv.get_volume_fraction_with_error(contrast=2.6e-6) s, ds = inv.get_surface_with_error(contrast=2.6e-6, porod_const=2) # Test results self.assertAlmostEquals(qstar, 0.00138756, 2) self.assertAlmostEquals(v, 0.117226896, 2) self.assertAlmostEquals(s, 941.7452, 3)
def test_bad_parameter_name(self): """ The set_extrapolation method checks that the name of the extrapolation function and the name of the q-range to extrapolate (high/low) is recognized. """ inv = invariant.InvariantCalculator(self.data) self.assertRaises(ValueError, inv.set_extrapolation, 'low', npts=4, function='not_a_name') self.assertRaises(ValueError, inv.set_extrapolation, 'not_a_range', npts=4, function='guinier') self.assertRaises(ValueError, inv.set_extrapolation, 'high', npts=4, function='guinier')
def test_high_data(self): """ Invariant with low-Q extrapolation with slit smear """ # Create invariant object. Background and scale left as defaults. inv = invariant.InvariantCalculator(data=self.data) # Set the extrapolation parameters for the low-Q range inv.set_extrapolation(range='high', npts=self.npts, function='power_law') self.assertEqual(inv._high_extrapolation_npts, self.npts) self.assertEqual(inv._high_extrapolation_function.__class__, invariant.PowerLaw) # Data boundaries for fiiting xlen = len(self.data.x) start = xlen - inv._high_extrapolation_npts qmin = inv._data.x[start] qmax = inv._data.x[xlen - 1] # Extrapolate the high-Q data inv._fit(model=inv._high_extrapolation_function, qmin=qmin, qmax=qmax, power=inv._high_extrapolation_power) qstar = inv.get_qstar(extrapolation='high') data_in_range = inv.get_extra_data_high( q_end=max(self.data.x), npts=inv._high_extrapolation_npts) test_y = data_in_range.y self.assert_(len(test_y) == len(self.data.y[start:])) temp = self.data.y[start:] for i in range(len(self.data.x[start:])): value = math.fabs(test_y[i] - temp[i]) / temp[i] self.assert_(value < 0.001)
def test_qstar_full_q(self): """ Test high-q extrapolation """ inv = invariant.InvariantCalculator(self.data) # Basic sanity check _qstar = inv.get_qstar() qstar, dqstar = inv.get_qstar_with_error() self.assertEqual(qstar, _qstar) # High-Q Extrapolation # Check that the returned invariant is what we expect given # the result we got without extrapolation inv.set_extrapolation('low', npts=10, function='guinier') inv.set_extrapolation('high', npts=20, function='power_law') qs_extr, dqs_extr = inv.get_qstar_with_error('both') delta_qs_low, delta_dqs_low = inv.get_qstar_low() delta_qs_hi, delta_dqs_hi = inv.get_qstar_high() self.assertAlmostEqual(qs_extr, _qstar + delta_qs_low + delta_qs_hi, 8) self.assertAlmostEqual(dqs_extr, math.sqrt(dqstar*dqstar + delta_dqs_low*delta_dqs_low \ + delta_dqs_hi*delta_dqs_hi), 8) # We don't expect the extrapolated invariant to be very far from the # result without extrapolation. Let's test for a result within 10%. #TODO: verify whether this test really makes sense #self.assertTrue(math.fabs(qs_extr-qstar)/qstar<0.1) # Check that the two results are consistent within errors self.assertTrue(math.fabs(qs_extr - qstar) < dqs_extr) def _check_values(to_check, reference, tolerance=0.05): self.assertTrue( math.fabs(to_check - reference) / reference < tolerance, msg="Tested value = " + str(to_check)) # The following values should be replaced by values pulled from IGOR # Volume Fraction: v, dv = inv.get_volume_fraction_with_error(1, None) _check_values(v, 1.88737914186e-15) v_l, dv_l = inv.get_volume_fraction_with_error(1, 'low') _check_values(v_l, 1.94289029309e-15) v_h, dv_h = inv.get_volume_fraction_with_error(1, 'high') _check_values(v_h, 6.99440505514e-15) v_b, dv_b = inv.get_volume_fraction_with_error(1, 'both') _check_values(v_b, 6.99440505514e-15) # Specific Surface: s, ds = inv.get_surface_with_error(1, 1, None) _check_values(s, 3.1603095786e-09) s_l, ds_l = inv.get_surface_with_error(1, 1, 'low') _check_values(s_l, 3.1603095786e-09) s_h, ds_h = inv.get_surface_with_error(1, 1, 'high') _check_values(s_h, 3.1603095786e-09) s_b, ds_b = inv.get_surface_with_error(1, 1, 'both') _check_values(s_b, 3.1603095786e-09)