예제 #1
1
    def testUpdate(self):
        """Update and change the profile to make sure generator is flushed."""
        gen = self.gen
        prof = self.profile

        # Make sure attributes get updated with a change in the calculation
        # points.
        x = arange(0, 9, 0.1)
        prof.setCalculationPoints(x)
        self.assertTrue(gen._value is None)
        val = gen.value
        self.assertTrue(array_equal(x, prof.ycalc))
        self.assertTrue(array_equal(prof.x, prof.ycalc))
        self.assertTrue(array_equal(val, prof.ycalc))
        self.assertTrue(array_equal(gen._value, prof.ycalc))

        # Make sure attributes get updated with a new profile.
        x = arange(0, 8, 0.1)
        prof = Profile()
        prof.setCalculationPoints(x)
        gen.setProfile(prof)
        self.assertTrue(gen._value is None)
        val = gen.value
        self.assertTrue(array_equal(x, prof.ycalc))
        self.assertTrue(array_equal(prof.x, prof.ycalc))
        self.assertTrue(array_equal(val, prof.ycalc))
        self.assertTrue(array_equal(gen._value, prof.ycalc))
        return
    def testUpdate(self):
        """Update and change the profile to make sure generator is flushed."""
        gen = self.gen
        prof = self.profile

        # Make sure attributes get updated with a change in the calculation
        # points.
        x = arange(0, 9, 0.1)
        prof.setCalculationPoints(x)
        self.assertTrue(gen._value is None)
        val = gen.value
        self.assertTrue(array_equal(x, val))

        # Verify generated value listens to changes in profile.x.
        x3 = x + 3
        prof.x = x3
        self.assertTrue(array_equal(x3, gen.value))

        # Make sure attributes get updated with a new profile.
        x = arange(0, 8, 0.1)
        prof = Profile()
        prof.setCalculationPoints(x)
        gen.setProfile(prof)
        self.assertTrue(gen._value is None)
        self.assertTrue(array_equal(x, gen.value))
        return
class TestProfileGenerator(unittest.TestCase):
    def setUp(self):
        self.gen = ProfileGenerator("test")
        self.profile = Profile()
        x = arange(0, 10, 0.1)
        self.profile.setCalculationPoints(x)
        self.gen.setProfile(self.profile)
        return

    def testOperation(self):
        """Test the operation method."""
        gen = self.gen
        prof = self.profile

        # Try the direct evaluation
        val = gen.operation()
        self.assertTrue(array_equal(prof.x, val))

        # Try evaluation through __call__
        val = gen(2 * prof.x)
        self.assertTrue(array_equal(2 * prof.x, val))
        return

    def testUpdate(self):
        """Update and change the profile to make sure generator is flushed."""
        gen = self.gen
        prof = self.profile

        # Make sure attributes get updated with a change in the calculation
        # points.
        x = arange(0, 9, 0.1)
        prof.setCalculationPoints(x)
        self.assertTrue(gen._value is None)
        val = gen.value
        self.assertTrue(array_equal(x, val))

        # Verify generated value listens to changes in profile.x.
        x3 = x + 3
        prof.x = x3
        self.assertTrue(array_equal(x3, gen.value))

        # Make sure attributes get updated with a new profile.
        x = arange(0, 8, 0.1)
        prof = Profile()
        prof.setCalculationPoints(x)
        gen.setProfile(prof)
        self.assertTrue(gen._value is None)
        self.assertTrue(array_equal(x, gen.value))
        return

    def test_pickling(self):
        """Test pickling of ProfileGenerator.
        """
        data = pickle.dumps(self.gen)
        gen2 = pickle.loads(data)
        self.assertEqual('test', gen2.name)
        x = self.profile.x
        self.assertTrue(array_equal(x, gen2.operation()))
        self.assertTrue(array_equal(3 * x, gen2(3 * x)))
        return
예제 #4
0
    def testUpdate(self):
        """Update and change the profile to make sure generator is flushed."""
        gen = self.gen
        prof = self.profile

        # Make sure attributes get updated with a change in the calculation
        # points.
        x = arange(0, 9, 0.1)
        prof.setCalculationPoints(x)
        self.assertTrue(gen._value is None)
        val = gen.value
        self.assertTrue(array_equal(x, prof.ycalc))
        self.assertTrue(array_equal(prof.x, prof.ycalc))
        self.assertTrue(array_equal(val, prof.ycalc))
        self.assertTrue(array_equal(gen._value, prof.ycalc))

        # Make sure attributes get updated with a new profile.
        x = arange(0, 8, 0.1)
        prof = Profile()
        prof.setCalculationPoints(x)
        gen.setProfile(prof)
        self.assertTrue(gen._value is None)
        val = gen.value
        self.assertTrue(array_equal(x, prof.ycalc))
        self.assertTrue(array_equal(prof.x, prof.ycalc))
        self.assertTrue(array_equal(val, prof.ycalc))
        self.assertTrue(array_equal(gen._value, prof.ycalc))
        return
예제 #5
0
    def testUpdate(self):
        """Update and change the profile to make sure generator is flushed."""
        gen = self.gen
        prof = self.profile

        # Make sure attributes get updated with a change in the calculation
        # points.
        x = arange(0, 9, 0.1)
        prof.setCalculationPoints(x)
        self.assertTrue(gen._value is None)
        val = gen.value
        self.assertTrue(array_equal(x, val))

        # Verify generated value listens to changes in profile.x.
        x3 = x + 3
        prof.x = x3
        self.assertTrue(array_equal(x3, gen.value))

        # Make sure attributes get updated with a new profile.
        x = arange(0, 8, 0.1)
        prof = Profile()
        prof.setCalculationPoints(x)
        gen.setProfile(prof)
        self.assertTrue(gen._value is None)
        self.assertTrue(array_equal(x, gen.value))
        return
예제 #6
0
    def testReplacements(self):
        """Test attribute integrity when objects get replaced."""
        fc = self.fitcontribution
        xobs = arange(0, 10, 0.5)
        yobs = xobs
        profile = self.profile
        profile.setObservedProfile(xobs, yobs)
        xobs2 = arange(0, 10, 0.8)
        yobs2 = 0.5 * xobs2
        profile2 = Profile()
        profile2.setObservedProfile(xobs2, yobs2)
        gen = self.gen

        # Validate equations
        fc.setProfile(profile)
        fc.addProfileGenerator(gen, "I")
        self.assertTrue(array_equal(gen.value, xobs))
        self.assertTrue(array_equal(fc._eq(), xobs))
        self.assertAlmostEquals(0, sum(fc._reseq()))
        eq = fc._eq
        reseq = fc._reseq

        # Now set a different profile
        fc.setProfile(profile2)
        self.assertTrue(fc.profile is profile2)
        self.assertTrue(gen.profile is profile2)
        self.assertTrue(fc._eq is eq)
        self.assertTrue(fc._reseq is reseq)
        self.assertTrue(fc._eq._value is None)
        self.assertTrue(fc._reseq._value is None)

        # Validate equations
        self.assertTrue(array_equal(xobs2, gen.value))
        self.assertTrue(array_equal(fc._eq(), gen.value))
        return
예제 #7
0
    def testReplacements(self):
        """Test attribute integrity when objects get replaced."""
        fc = self.fitcontribution
        xobs = arange(0, 10, 0.5)
        yobs = xobs
        profile = self.profile
        profile.setObservedProfile(xobs, yobs)
        xobs2 = arange(0, 10, 0.8)
        yobs2 = 0.5*xobs2
        profile2 = Profile()
        profile2.setObservedProfile(xobs2, yobs2)
        gen = self.gen

        # Validate equations
        fc.setProfile(profile)
        fc.addProfileGenerator(gen, "I")
        self.assertTrue(array_equal(gen.value, xobs))
        self.assertTrue(array_equal(fc._eq(), xobs))
        self.assertAlmostEquals(0, sum(fc._reseq()))
        eq = fc._eq
        reseq = fc._reseq

        # Now set a different profile
        fc.setProfile(profile2)
        self.assertTrue(fc.profile is profile2)
        self.assertTrue(gen.profile is profile2)
        self.assertTrue(fc._eq is eq)
        self.assertTrue(fc._reseq is reseq)
        self.assertTrue(fc._eq._value is None)
        self.assertTrue(fc._reseq._value is None)

        # Validate equations
        self.assertTrue(array_equal(xobs2, gen.value))
        self.assertTrue(array_equal(fc._eq(), gen.value))
        return
예제 #8
0
 def setUp(self):
     self.gen = ProfileGenerator("test")
     self.profile = Profile()
     x = arange(0, 10, 0.1)
     self.profile.setCalculationPoints(x)
     self.gen.setProfile(self.profile)
     return
예제 #9
0
class TestProfileGenerator(unittest.TestCase):

    def setUp(self):
        self.gen = ProfileGenerator("test")
        self.profile = Profile()
        x = arange(0, 10, 0.1)
        self.profile.setCalculationPoints(x)
        self.gen.setProfile(self.profile)
        return

    def testOperation(self):
        """Test the operation method."""
        gen = self.gen
        prof = self.profile

        # Try the direct evaluation
        gen.operation()
        self.assertTrue(array_equal(prof.x, prof.ycalc))

        # Try evaluation through __call__
        gen(prof.x)
        self.assertTrue(array_equal(prof.x, prof.ycalc))
        return

    def testUpdate(self):
        """Update and change the profile to make sure generator is flushed."""
        gen = self.gen
        prof = self.profile

        # Make sure attributes get updated with a change in the calculation
        # points.
        x = arange(0, 9, 0.1)
        prof.setCalculationPoints(x)
        self.assertTrue(gen._value is None)
        val = gen.value
        self.assertTrue(array_equal(x, prof.ycalc))
        self.assertTrue(array_equal(prof.x, prof.ycalc))
        self.assertTrue(array_equal(val, prof.ycalc))
        self.assertTrue(array_equal(gen._value, prof.ycalc))

        # Make sure attributes get updated with a new profile.
        x = arange(0, 8, 0.1)
        prof = Profile()
        prof.setCalculationPoints(x)
        gen.setProfile(prof)
        self.assertTrue(gen._value is None)
        val = gen.value
        self.assertTrue(array_equal(x, prof.ycalc))
        self.assertTrue(array_equal(prof.x, prof.ycalc))
        self.assertTrue(array_equal(val, prof.ycalc))
        self.assertTrue(array_equal(gen._value, prof.ycalc))
        return
예제 #10
0
class TestProfileGenerator(unittest.TestCase):
    def setUp(self):
        self.gen = ProfileGenerator("test")
        self.profile = Profile()
        x = arange(0, 10, 0.1)
        self.profile.setCalculationPoints(x)
        self.gen.setProfile(self.profile)
        return

    def testOperation(self):
        """Test the operation method."""
        gen = self.gen
        prof = self.profile

        # Try the direct evaluation
        gen.operation()
        self.assertTrue(array_equal(prof.x, prof.ycalc))

        # Try evaluation through __call__
        gen(prof.x)
        self.assertTrue(array_equal(prof.x, prof.ycalc))
        return

    def testUpdate(self):
        """Update and change the profile to make sure generator is flushed."""
        gen = self.gen
        prof = self.profile

        # Make sure attributes get updated with a change in the calculation
        # points.
        x = arange(0, 9, 0.1)
        prof.setCalculationPoints(x)
        self.assertTrue(gen._value is None)
        val = gen.value
        self.assertTrue(array_equal(x, prof.ycalc))
        self.assertTrue(array_equal(prof.x, prof.ycalc))
        self.assertTrue(array_equal(val, prof.ycalc))
        self.assertTrue(array_equal(gen._value, prof.ycalc))

        # Make sure attributes get updated with a new profile.
        x = arange(0, 8, 0.1)
        prof = Profile()
        prof.setCalculationPoints(x)
        gen.setProfile(prof)
        self.assertTrue(gen._value is None)
        val = gen.value
        self.assertTrue(array_equal(x, prof.ycalc))
        self.assertTrue(array_equal(prof.x, prof.ycalc))
        self.assertTrue(array_equal(val, prof.ycalc))
        self.assertTrue(array_equal(gen._value, prof.ycalc))
        return
예제 #11
0
    def __init__(self, datainfo):
        """Initialize the attributes.

        datainfo   --  The DataInfo object this wraps.

        """
        self._datainfo = datainfo
        Profile.__init__(self)

        self._xobs = self._datainfo.x
        self._yobs = self._datainfo.y
        if self._datainfo.dy is None or 0 == len(self._datainfo.dy):
            self._dyobs = ones_like(self.xobs)
        else:
            self._dyobs = self._datainfo.dy
        return
예제 #12
0
 def setUp(self):
     self.gen = ProfileGenerator("test")
     self.profile = Profile()
     x = arange(0, 10, 0.1)
     self.profile.setCalculationPoints(x)
     self.gen.setProfile(self.profile)
     return
예제 #13
0
    def __init__(self, datainfo):
        """Initialize the attributes.

        datainfo   --  The DataInfo object this wraps.

        """
        self._datainfo = datainfo
        Profile.__init__(self)

        self._xobs = self._datainfo.x
        self._yobs = self._datainfo.y
        if self._datainfo.dy is None or 0 == len(self._datainfo.dy):
            self._dyobs = ones_like(self.xobs)
        else:
            self._dyobs = self._datainfo.dy
        return
예제 #14
0
    def __init__(self, name="fit", conclass=FitContribution):
        """Initialization."""
        FitRecipe.__init__(self, name)
        self.fithooks[0].verbose = 3
        contribution = conclass("contribution")
        self.profile = Profile()
        contribution.setProfile(self.profile)
        self.addContribution(contribution)
        self.results = FitResults(self, update=False)

        # Adopt all the FitContribution methods
        public = [
            aname for aname in dir(contribution)
            if aname not in dir(self) and not aname.startswith("_")
        ]
        for mname in public:
            method = getattr(contribution, mname)
            setattr(self, mname, method)
        return
예제 #15
0
    def setUp(self):
        self.recipe = FitRecipe("recipe")
        self.recipe.fithooks[0].verbose = 0

        # Set up the Profile
        self.profile = Profile()
        x = linspace(0, pi, 10)
        y = sin(x)
        self.profile.setObservedProfile(x, y)

        # Set up the FitContribution
        self.fitcontribution = FitContribution("cont")
        self.fitcontribution.setProfile(self.profile)
        self.fitcontribution.setEquation("A*sin(k*x + c)")
        self.fitcontribution.A.setValue(1)
        self.fitcontribution.k.setValue(1)
        self.fitcontribution.c.setValue(0)

        self.recipe.addContribution(self.fitcontribution)
        return
예제 #16
0
    def setObservedProfile(self, xobs, yobs, dyobs = None):
        """Set the observed profile.

        This is overloaded to change the value within the datainfo object.

        Arguments
        xobs    --  Numpy array of the independent variable
        yobs    --  Numpy array of the observed signal.
        dyobs   --  Numpy array of the uncertainty in the observed signal. If
                    dyobs is None (default), it will be set to 1 at each
                    observed xobs.

        Raises ValueError if len(yobs) != len(xobs)
        Raises ValueError if dyobs != None and len(dyobs) != len(xobs)

        """
        Profile.setObservedProfile(self, xobs, yobs, dyobs)
        # Copy the arrays to the _datainfo attribute.
        self._datainfo.x = self._xobs
        self._datainfo.y = self._yobs
        self._datainfo.dy = self._dyobs
        return
예제 #17
0
    def setObservedProfile(self, xobs, yobs, dyobs=None):
        """Set the observed profile.

        This is overloaded to change the value within the datainfo object.

        Arguments
        xobs    --  Numpy array of the independent variable
        yobs    --  Numpy array of the observed signal.
        dyobs   --  Numpy array of the uncertainty in the observed signal. If
                    dyobs is None (default), it will be set to 1 at each
                    observed xobs.

        Raises ValueError if len(yobs) != len(xobs)
        Raises ValueError if dyobs != None and len(dyobs) != len(xobs)

        """
        Profile.setObservedProfile(self, xobs, yobs, dyobs)
        # Copy the arrays to the _datainfo attribute.
        self._datainfo.x = self._xobs
        self._datainfo.y = self._yobs
        self._datainfo.dy = self._dyobs
        return
예제 #18
0
    def __init__(self, name = "fit", conclass = FitContribution):
        """Initialization."""
        FitRecipe.__init__(self, name)
        self.fithooks[0].verbose = 3
        contribution = conclass("contribution")
        self.profile = Profile()
        contribution.setProfile(self.profile)
        self.addContribution(contribution)
        self.results = FitResults(self, update = False)

        # Adopt all the FitContribution methods
        public = [aname for aname in dir(contribution) if aname not in
                dir(self) and not aname.startswith("_")]
        for mname in public:
            method = getattr(contribution, mname)
            setattr(self, mname, method)
        return
예제 #19
0
파일: model.py 프로젝트: st3107/pdffitx
 def _create_recipe(self) -> md.MyRecipe:
     pgs = []
     for name, structure in self._structures.items():
         pg = md.PDFGenerator(name)
         pg.setStructure(structure, periodic=True)
         pgs.append(pg)
     fc = md.MyContribution(self.__class__.__name__)
     fc.setProfile(Profile())
     for pg in pgs:
         fc.addProfileGenerator(pg)
     for name, sf in self._characteristics.items():
         argnames = rename_args(sf, "{}_".format(name), fc.xname)
         fc.registerFunction(sf, name, argnames)
     fc.setEquation(self._equation)
     fr = md.MyRecipe()
     fr.clearFitHooks()
     fr.addContribution(fc)
     md.initialize(fr, **self._init_mode)
     return fr
예제 #20
0
    def setUp(self):
        self.recipe = FitRecipe("recipe")
        self.recipe.fithooks[0].verbose = 0

        # Set up the Profile
        self.profile = Profile()
        x = linspace(0, pi, 10)
        y = sin(x)
        self.profile.setObservedProfile(x, y)

        # Set up the FitContribution
        self.fitcontribution = FitContribution("cont")
        self.fitcontribution.setProfile(self.profile)
        self.fitcontribution.setEquation("A*sin(k*x + c)")
        self.fitcontribution.A.setValue(1)
        self.fitcontribution.k.setValue(1)
        self.fitcontribution.c.setValue(0)

        self.recipe.addContribution(self.fitcontribution)
        return
class TestProfileGenerator(unittest.TestCase):

    def setUp(self):
        self.gen = ProfileGenerator("test")
        self.profile = Profile()
        x = arange(0, 10, 0.1)
        self.profile.setCalculationPoints(x)
        self.gen.setProfile(self.profile)
        return


    def testOperation(self):
        """Test the operation method."""
        gen = self.gen
        prof = self.profile

        # Try the direct evaluation
        val = gen.operation()
        self.assertTrue(array_equal(prof.x, val))

        # Try evaluation through __call__
        val = gen(2 * prof.x)
        self.assertTrue(array_equal(2 * prof.x, val))
        return


    def testUpdate(self):
        """Update and change the profile to make sure generator is flushed."""
        gen = self.gen
        prof = self.profile

        # Make sure attributes get updated with a change in the calculation
        # points.
        x = arange(0, 9, 0.1)
        prof.setCalculationPoints(x)
        self.assertTrue(gen._value is None)
        val = gen.value
        self.assertTrue(array_equal(x, val))

        # Verify generated value listens to changes in profile.x.
        x3 = x + 3
        prof.x = x3
        self.assertTrue(array_equal(x3, gen.value))

        # Make sure attributes get updated with a new profile.
        x = arange(0, 8, 0.1)
        prof = Profile()
        prof.setCalculationPoints(x)
        gen.setProfile(prof)
        self.assertTrue(gen._value is None)
        self.assertTrue(array_equal(x, gen.value))
        return


    def test_pickling(self):
        """Test pickling of ProfileGenerator.
        """
        data = pickle.dumps(self.gen)
        gen2 = pickle.loads(data)
        self.assertEqual('test', gen2.name)
        x = self.profile.x
        self.assertTrue(array_equal(x, gen2.operation()))
        self.assertTrue(array_equal(3 * x, gen2(3 * x)))
        return
예제 #22
0
class TestFitRecipe(unittest.TestCase):

    def setUp(self):
        self.recipe = FitRecipe("recipe")
        self.recipe.fithooks[0].verbose = 0

        # Set up the Profile
        self.profile = Profile()
        x = linspace(0, pi, 10)
        y = sin(x)
        self.profile.setObservedProfile(x, y)

        # Set up the FitContribution
        self.fitcontribution = FitContribution("cont")
        self.fitcontribution.setProfile(self.profile)
        self.fitcontribution.setEquation("A*sin(k*x + c)")
        self.fitcontribution.A.setValue(1)
        self.fitcontribution.k.setValue(1)
        self.fitcontribution.c.setValue(0)

        self.recipe.addContribution(self.fitcontribution)
        return

    def testFixFree(self):
        recipe = self.recipe
        con = self.fitcontribution

        recipe.addVar(con.A, 2, tag = "tagA")
        recipe.addVar(con.k, 1, tag = "tagk")
        recipe.addVar(con.c, 0)
        recipe.newVar("B", 0)

        self.assertTrue(recipe.isFree(recipe.A))
        recipe.fix("tagA")
        self.assertFalse(recipe.isFree(recipe.A))
        recipe.free("tagA")
        self.assertTrue(recipe.isFree(recipe.A))
        recipe.fix("A")
        self.assertFalse(recipe.isFree(recipe.A))
        recipe.free("A")
        self.assertTrue(recipe.isFree(recipe.A))
        recipe.fix(recipe.A)
        self.assertFalse(recipe.isFree(recipe.A))
        recipe.free(recipe.A)
        self.assertTrue(recipe.isFree(recipe.A))
        recipe.fix(recipe.A)
        self.assertFalse(recipe.isFree(recipe.A))
        recipe.free("all")
        self.assertTrue(recipe.isFree(recipe.A))
        self.assertTrue(recipe.isFree(recipe.k))
        self.assertTrue(recipe.isFree(recipe.c))
        self.assertTrue(recipe.isFree(recipe.B))
        recipe.fix(recipe.A, "tagk", c = 3)
        self.assertFalse(recipe.isFree(recipe.A))
        self.assertFalse(recipe.isFree(recipe.k))
        self.assertFalse(recipe.isFree(recipe.c))
        self.assertTrue(recipe.isFree(recipe.B))
        self.assertEqual(3, recipe.c.value)
        recipe.fix("all")
        self.assertFalse(recipe.isFree(recipe.A))
        self.assertFalse(recipe.isFree(recipe.k))
        self.assertFalse(recipe.isFree(recipe.c))
        self.assertFalse(recipe.isFree(recipe.B))

        self.assertRaises(ValueError, recipe.free, "junk")
        self.assertRaises(ValueError, recipe.fix, tagA = 1)
        self.assertRaises(ValueError, recipe.fix, "junk")
        return

    def testVars(self):
        """Test to see if variables are added and removed properly."""
        recipe = self.recipe
        con = self.fitcontribution

        recipe.addVar(con.A, 2)
        recipe.addVar(con.k, 1)
        recipe.addVar(con.c, 0)
        recipe.newVar("B", 0)

        names = recipe.getNames()
        self.assertEqual(names, ["A", "k", "c", "B"])
        values = recipe.getValues()
        self.assertTrue((values == [2, 1, 0, 0]).all())

        # Constrain a parameter to the B-variable to give it a value
        p = Parameter("Bpar", -1)
        recipe.constrain(recipe.B, p)
        values = recipe.getValues()
        self.assertTrue((values == [2, 1, 0]).all())
        recipe.delVar(recipe.B)

        recipe.fix(recipe.k)

        names = recipe.getNames()
        self.assertEqual(names, ["A", "c"])
        values = recipe.getValues()
        self.assertTrue((values == [2, 0]).all())

        recipe.fix("all")
        names = recipe.getNames()
        self.assertEqual(names, [])
        values = recipe.getValues()
        self.assertTrue((values == []).all())

        recipe.free("all")
        names = recipe.getNames()
        self.assertEqual(3, len(names))
        self.assertTrue("A" in names)
        self.assertTrue("k" in names)
        self.assertTrue("c" in names)
        values = recipe.getValues()
        self.assertEqual(3, len(values))
        self.assertTrue(0 in values)
        self.assertTrue(1 in values)
        self.assertTrue(2 in values)
        return


    def testResidual(self):
        """Test the residual and everything that can change it."""

        # With thing set up as they are, the residual should be 0
        res = self.recipe.residual()
        self.assertAlmostEqual(0, dot(res, res))

        # Change the c value to 1 so that the equation evaluates as sin(x+1)
        x = self.profile.x
        y = sin(x+1)
        self.recipe.cont.c.setValue(1)
        res = self.recipe.residual()
        self.assertTrue( array_equal(y-self.profile.y, res) )

        # Try some constraints
        # Make c = 2*A, A = Avar
        var = self.recipe.newVar("Avar")
        self.recipe.constrain(self.fitcontribution.c, "2*A",
                {"A" : self.fitcontribution.A})
        self.assertEqual(2, self.fitcontribution.c.value)
        self.recipe.constrain(self.fitcontribution.A, var)
        self.assertEqual(1, var.getValue())
        self.assertEqual(self.recipe.cont.A.getValue(), var.getValue())
        # c is constrained to a constrained parameter.
        self.assertEqual(2, self.fitcontribution.c.value)
        # The equation should evaluate to sin(x+2)
        x = self.profile.x
        y = sin(x+2)
        res = self.recipe.residual()
        self.assertTrue( array_equal(y-self.profile.y, res) )

        # Now try some restraints. We want c to be exactly zero. It should give
        # a penalty of (c-0)**2, which is 4 in this case
        r1 = self.recipe.restrain(self.fitcontribution.c, 0, 0, 1)
        self.recipe._ready = False
        res = self.recipe.residual()
        chi2 = 4 + dot(y - self.profile.y, y - self.profile.y)
        self.assertAlmostEqual(chi2, dot(res, res) )

        # Clear the constraint and restore the value of c to 0. This should
        # give us chi2 = 0 again.
        self.recipe.unconstrain(self.fitcontribution.c)
        self.fitcontribution.c.setValue(0)
        res = self.recipe.residual([self.recipe.cont.A.getValue()])
        chi2 = 0
        self.assertAlmostEqual(chi2, dot(res, res) )

        # Remove the restraint and variable
        self.recipe.unrestrain(r1)
        self.recipe.delVar(self.recipe.Avar)
        self.recipe._ready = False
        res = self.recipe.residual()
        chi2 = 0
        self.assertAlmostEqual(chi2, dot(res, res) )

        # Add constraints at the fitcontribution level.
        self.fitcontribution.constrain(self.fitcontribution.c, "2*A")
        # This should evaluate to sin(x+2)
        x = self.profile.x
        y = sin(x+2)
        res = self.recipe.residual()
        self.assertTrue( array_equal(y-self.profile.y, res) )

        # Add a restraint at the fitcontribution level.
        r1 = self.fitcontribution.restrain(self.fitcontribution.c, 0, 0, 1)
        self.recipe._ready = False
        # The chi2 is the same as above, plus 4
        res = self.recipe.residual()
        x = self.profile.x
        y = sin(x+2)
        chi2 = 4 + dot(y - self.profile.y, y - self.profile.y)
        self.assertAlmostEqual(chi2, dot(res, res) )

        # Remove those
        self.fitcontribution.unrestrain(r1)
        self.recipe._ready = False
        self.fitcontribution.unconstrain(self.fitcontribution.c)
        self.fitcontribution.c.setValue(0)
        res = self.recipe.residual()
        chi2 = 0
        self.assertAlmostEqual(chi2, dot(res, res) )

        # Now try to use the observed profile inside of the equation
        # Set the equation equal to the data
        self.fitcontribution.setEquation("y")
        res = self.recipe.residual()
        self.assertAlmostEqual(0, dot(res, res))

        # Now add the uncertainty. This should give dy/dy = 1 for the residual
        self.fitcontribution.setEquation("y+dy")
        res = self.recipe.residual()
        self.assertAlmostEqual(len(res), dot(res, res))

        return


    def testPrintFitHook(self):
        "check output from default PrintFitHook."
        self.recipe.addVar(self.fitcontribution.c)
        self.recipe.restrain('c', lb=5)
        pfh, = self.recipe.getFitHooks()
        out = capturestdout(self.recipe.scalarResidual)
        self.assertEqual('', out)
        pfh.verbose = 1
        out = capturestdout(self.recipe.scalarResidual)
        self.assertTrue(out.strip().isdigit())
        self.assertFalse('\nRestraints:' in out)
        pfh.verbose = 2
        out = capturestdout(self.recipe.scalarResidual)
        self.assertTrue('\nResidual:' in out)
        self.assertTrue('\nRestraints:' in out)
        self.assertFalse('\nVariables' in out)
        pfh.verbose = 3
        out = capturestdout(self.recipe.scalarResidual)
        self.assertTrue('\nVariables' in out)
        self.assertTrue('c = ' in out)
        return
예제 #23
0
 def setUp(self):
     self.profile = Profile()
     return
예제 #24
0
class TestProfile(unittest.TestCase):

    def setUp(self):
        self.profile = Profile()
        return

    def testInit(self):
        profile = self.profile
        self.assertTrue(profile.xobs is None)
        self.assertTrue(profile.yobs is None)
        self.assertTrue(profile.dyobs is None)
        self.assertTrue(profile.x is None)
        self.assertTrue(profile.y is None)
        self.assertTrue(profile.dy is None)
        self.assertTrue(profile.ycalc is None)
        self.assertEquals(profile.meta, {})
        return

    def testSetObservedProfile(self):
        """Test the setObservedProfile method."""
        # Make a profile with defined dy

        x = arange(0, 10, 0.1)
        y = x
        dy = x

        prof = self.profile
        prof.setObservedProfile(x, y, dy)

        self.assertTrue( array_equal(x, prof.xobs) )
        self.assertTrue( array_equal(y, prof.yobs) )
        self.assertTrue( array_equal(dy, prof.dyobs) )

        # Make a profile with undefined dy
        x = arange(0, 10, 0.1)
        y = x
        dy = None

        self.profile.setObservedProfile(x, y, dy)

        self.assertTrue( array_equal(x, prof.xobs) )
        self.assertTrue( array_equal(y, prof.yobs) )
        self.assertTrue( array_equal(ones_like(prof.xobs), prof.dyobs))

        # Get the ranged profile to make sure its the same
        self.assertTrue( array_equal(x, prof.x) )
        self.assertTrue( array_equal(y, prof.y) )
        self.assertTrue( array_equal(ones_like(prof.xobs), prof.dy))

        return

    def testSetCalculationRange(self):
        """Test the setCalculationRange method."""
        x = arange(2, 10, 0.5)
        y = array(x)
        dy = array(x)

        prof = self.profile

        # Check call before data arrays are present
        self.assertRaises(AttributeError, prof.setCalculationRange)
        self.assertRaises(AttributeError, prof.setCalculationRange, 0)
        self.assertRaises(AttributeError, prof.setCalculationRange, 0,
                10)
        self.assertRaises(AttributeError, prof.setCalculationRange, 0,
                10, 0.2)

        prof.setObservedProfile(x, y, dy)

        # Test normal execution w/o arguments
        prof.setCalculationRange()
        self.assertTrue( array_equal(x, prof.x) )
        self.assertTrue( array_equal(y, prof.y) )
        self.assertTrue( array_equal(dy, prof.dy) )

        # Test a lower bound < xmin
        prof.setCalculationRange(xmin = 0)
        self.assertTrue( array_equal(x, prof.x) )
        self.assertTrue( array_equal(y, prof.y) )
        self.assertTrue( array_equal(dy, dprof.y) )

        # Test an upper bound > xmax
        prof.setCalculationRange(xmax = 100)
        prof.x, prof.y, dprof.y = prof.getRangedProfile()
        self.assertTrue( array_equal(x, prof.x) )
        self.assertTrue( array_equal(y, prof.y) )
        self.assertTrue( array_equal(dy, dprof.y) )

        # Test xmin > xmax
        self.assertRaises(ValueError, profile.setCalculationRange, xmin = 10,
                xmax = 3)

        # Test xmax - xmin < dx
        self.assertRaises(ValueError, profile.setCalculationRange, xmin = 3,
                xmax = 3 + 0.4, dx = 0.5)

        # Test dx <= 0
        self.assertRaises(ValueError, profile.setCalculationRange, dx = 0)
        self.assertRaises(ValueError, profile.setCalculationRange, dx =
                -0.000001)
        # This should be alright
        profile.setCalculationRange(dx = 0.000001)

        # Test an internal bound
        prof.setCalculationRange(4, 7)
        prof.x, prof.y, dprof.y = prof.getRangedProfile()
        self.assertTrue( array_equal(prof.x, arange(4, 7.5, 0.5) ) )
        self.assertTrue( array_equal(prof.y, arange(4, 7.5, 0.5) ) )
        self.assertTrue( array_equal(dprof.y, arange(4, 7.5, 0.5) ) )

        # Test a new grid
        prof.setCalculationRange(4, 7, 0.1)
        prof.x, prof.y, dprof.y = prof.getRangedProfile()
        self.assertTrue( array_equal(prof.x, arange(4, 7.1, 0.1) ) )
        self.assertAlmostEqual( 0, sum(prof.y- arange(4, 7.1, 0.1))**2 )
        self.assertAlmostEqual( 0, sum(dprof.y- arange(4, 7.1, 0.1))**2 )

        return

    def testSetCalculationRange(self):
        """Test the setCalculationRange method."""
        prof = self.profile

        x = arange(2, 10.5, 0.5)
        y = array(x)
        dy = array(x)

        # Test without data
        xcalc = arange(3, 12.2, 0.2)
        prof.setCalculationPoints(xcalc)
        self.assertTrue( array_equal(xcalc, prof.x) )

        # Add the data. This should change the bounds of the calculation array.
        prof.setObservedProfile(x, y, dy)
        self.assertTrue( array_equal(arange(3, 10.1, 0.2), prof.x ) )

        return

    def testLoadtxt(self):
        """Test the loadtxt method"""

        prof = self.profile
        data = datafile("testdata.txt")

        def _test(p):
            self.assertAlmostEqual(1e-2, p.x[0])
            self.assertAlmostEqual(1.105784e-1, p.y[0])
            self.assertAlmostEqual(1.802192e-3, p.dy[0])

        # Test normal load
        prof.loadtxt(data, usecols=(0,1,3))
        _test(prof)

        # Test trying to not set unpack
        prof.loadtxt(data, usecols=(0,1,3), unpack = False)
        _test(prof)
        prof.loadtxt(data, float, '#', None, None, 0, (0,1,3), False)
        _test(prof)

        # Try not including dy
        prof.loadtxt(data, usecols=(0,1))
        self.assertAlmostEqual(1e-2, prof.x[0])
        self.assertAlmostEqual(1.105784e-1, prof.y[0])
        self.assertAlmostEqual(1, prof.dy[0])

        # Try to include too little
        self.assertRaises(ValueError, prof.loadtxt, data, usecols=(0,))
        return
예제 #25
0
 def setUp(self):
     self.gen = ProfileGenerator("test")
     self.profile = Profile()
     self.fitcontribution = FitContribution("test")
     return
예제 #26
0
 def setUp(self):
     self.profile = Profile()
     return
예제 #27
0
class TestProfile(unittest.TestCase):

    def setUp(self):
        self.profile = Profile()
        return

    def testInit(self):
        profile = self.profile
        self.assertTrue(profile.xobs is None)
        self.assertTrue(profile.yobs is None)
        self.assertTrue(profile.dyobs is None)
        self.assertTrue(profile.x is None)
        self.assertTrue(profile.y is None)
        self.assertTrue(profile.dy is None)
        self.assertTrue(profile.ycalc is None)
        self.assertEqual(profile.meta, {})
        return

    def testSetObservedProfile(self):
        """Test the setObservedProfile method."""
        # Make a profile with defined dy

        x = arange(0, 10, 0.1)
        y = x
        dy = x

        prof = self.profile
        prof.setObservedProfile(x, y, dy)

        self.assertTrue( array_equal(x, prof.xobs) )
        self.assertTrue( array_equal(y, prof.yobs) )
        self.assertTrue( array_equal(dy, prof.dyobs) )

        # Make a profile with undefined dy
        x = arange(0, 10, 0.1)
        y = x
        dy = None

        self.profile.setObservedProfile(x, y, dy)

        self.assertTrue( array_equal(x, prof.xobs) )
        self.assertTrue( array_equal(y, prof.yobs) )
        self.assertTrue( array_equal(ones_like(prof.xobs), prof.dyobs))

        # Get the ranged profile to make sure its the same
        self.assertTrue( array_equal(x, prof.x) )
        self.assertTrue( array_equal(y, prof.y) )
        self.assertTrue( array_equal(ones_like(prof.xobs), prof.dy))

        return


    def testSetCalculationRange(self):
        """Test the setCalculationRange method."""
        x = arange(2, 9.6, 0.5)
        y = array(x)
        dy = array(x)
        prof = self.profile
        # Check call before data arrays are present
        self.assertRaises(AttributeError, prof.setCalculationRange)
        self.assertRaises(AttributeError, prof.setCalculationRange, 0)
        self.assertRaises(AttributeError, prof.setCalculationRange, 0, 5)
        self.assertRaises(AttributeError, prof.setCalculationRange, 0, 5, 0.2)
        # assign data
        prof.setObservedProfile(x, y, dy)
        # Test normal execution w/o arguments
        self.assertTrue(array_equal(x, prof.x))
        self.assertTrue(array_equal(y, prof.y))
        self.assertTrue(array_equal(dy, prof.dy))
        prof.setCalculationRange()
        self.assertTrue(array_equal(x, prof.x))
        self.assertTrue(array_equal(y, prof.y))
        self.assertTrue(array_equal(dy, prof.dy))
        # Test a lower bound < xmin
        prof.setCalculationRange(xmin=0)
        self.assertTrue(array_equal(x, prof.x))
        self.assertTrue(array_equal(y, prof.y))
        self.assertTrue(array_equal(dy, prof.dy))
        # Test an upper bound > xmax
        prof.setCalculationRange(xmax=100)
        self.assertTrue(array_equal(x, prof.x))
        self.assertTrue(array_equal(y, prof.y))
        self.assertTrue(array_equal(dy, prof.dy))
        # Test xmin > xmax
        self.assertRaises(ValueError, prof.setCalculationRange,
                          xmin=10, xmax=3)
        # Test xmax - xmin < dx
        self.assertRaises(ValueError, prof.setCalculationRange,
                          xmin=3, xmax=3.9, dx=1.0)
        # Test dx <= 0
        self.assertRaises(ValueError, prof.setCalculationRange, dx=0)
        self.assertRaises(ValueError, prof.setCalculationRange, dx=-0.000001)
        # using string other than 'obs'
        self.assertRaises(ValueError, prof.setCalculationRange, xmin='oobs')
        self.assertRaises(ValueError, prof.setCalculationRange, xmax='oobs')
        self.assertRaises(ValueError, prof.setCalculationRange, dx='oobs')
        # This should be alright
        prof.setCalculationRange(3, 5)
        prof.setCalculationRange(xmin='obs', xmax=7, dx=0.001)
        self.assertEqual(5001, len(prof.x))
        self.assertEqual(len(prof.x), len(prof.y))
        self.assertEqual(len(prof.x), len(prof.dy))
        # Test an internal bound
        prof.setCalculationRange(4, 7, dx='obs')
        self.assertTrue(array_equal(prof.x, arange(4, 7.1, 0.5)))
        self.assertTrue(array_equal(prof.y, arange(4, 7.1, 0.5)))
        self.assertTrue(array_equal(prof.y, arange(4, 7.1, 0.5)))
        # test setting only one of the bounds
        prof.setCalculationRange(xmin=3)
        self.assertTrue(array_equal(prof.x, arange(3, 7.1, 0.5)))
        self.assertTrue(array_equal(prof.x, prof.y))
        self.assertTrue(array_equal(prof.x, prof.dy))
        prof.setCalculationRange(xmax=5.1)
        self.assertTrue(array_equal(prof.x, arange(3, 5.1, 0.5)))
        self.assertTrue(array_equal(prof.x, prof.y))
        self.assertTrue(array_equal(prof.x, prof.dy))
        prof.setCalculationRange(dx=1)
        self.assertTrue(array_equal(prof.x, arange(3, 5.1)))
        self.assertTrue(array_equal(prof.x, prof.y))
        self.assertTrue(array_equal(prof.x, prof.dy))
        # Test a new grid
        prof.setCalculationRange(4.2, 7, 0.3)
        self.assertTrue(array_equal(prof.x, arange(4.2, 6.901, 0.3)))
        self.assertTrue(allclose(prof.x, prof.y))
        self.assertTrue(allclose(prof.x, prof.dy))
        prof.setCalculationRange(xmin=4.2, xmax=6.001)
        self.assertTrue(array_equal(prof.x, arange(4.2, 6.001, 0.3)))
        # resample on a clipped grid
        prof.setCalculationRange(dx=0.5)
        self.assertTrue(array_equal(prof.x, arange(4.5, 6.1, 0.5)))
        return


    def testSetCalculationPoints(self):
        """Test the setCalculationPoints method."""
        prof = self.profile

        x = arange(2, 10.5, 0.5)
        y = array(x)
        dy = array(x)

        # Test without data
        xcalc = arange(3, 12.2, 0.2)
        prof.setCalculationPoints(xcalc)
        self.assertTrue( array_equal(xcalc, prof.x) )

        # Add the data. This should change the bounds of the calculation array.
        prof.setObservedProfile(x, y, dy)
        self.assertTrue( array_equal(arange(3, 10.1, 0.2), prof.x ) )

        return

    def testLoadtxt(self):
        """Test the loadtxt method"""

        prof = self.profile
        data = datafile("testdata.txt")

        def _test(p):
            self.assertAlmostEqual(1e-2, p.x[0])
            self.assertAlmostEqual(1.105784e-1, p.y[0])
            self.assertAlmostEqual(1.802192e-3, p.dy[0])

        # Test normal load
        prof.loadtxt(data, usecols=(0,1,3))
        _test(prof)

        # Test trying to not set unpack
        prof.loadtxt(data, usecols=(0,1,3), unpack = False)
        _test(prof)
        prof.loadtxt(data, float, '#', None, None, 0, (0,1,3), False)
        _test(prof)

        # Try not including dy
        prof.loadtxt(data, usecols=(0,1))
        self.assertAlmostEqual(1e-2, prof.x[0])
        self.assertAlmostEqual(1.105784e-1, prof.y[0])
        self.assertAlmostEqual(1, prof.dy[0])

        # Try to include too little
        self.assertRaises(ValueError, prof.loadtxt, data, usecols=(0,))
        return
예제 #28
0
class TestFitRecipe(unittest.TestCase):
    def setUp(self):
        self.recipe = FitRecipe("recipe")
        self.recipe.fithooks[0].verbose = 0

        # Set up the Profile
        self.profile = Profile()
        x = linspace(0, pi, 10)
        y = sin(x)
        self.profile.setObservedProfile(x, y)

        # Set up the FitContribution
        self.fitcontribution = FitContribution("cont")
        self.fitcontribution.setProfile(self.profile)
        self.fitcontribution.setEquation("A*sin(k*x + c)")
        self.fitcontribution.A.setValue(1)
        self.fitcontribution.k.setValue(1)
        self.fitcontribution.c.setValue(0)

        self.recipe.addContribution(self.fitcontribution)
        return

    def testFixFree(self):
        recipe = self.recipe
        con = self.fitcontribution

        recipe.addVar(con.A, 2, tag="tagA")
        recipe.addVar(con.k, 1, tag="tagk")
        recipe.addVar(con.c, 0)
        recipe.newVar("B", 0)

        self.assertTrue(recipe.isFree(recipe.A))
        recipe.fix("tagA")
        self.assertFalse(recipe.isFree(recipe.A))
        recipe.free("tagA")
        self.assertTrue(recipe.isFree(recipe.A))
        recipe.fix("A")
        self.assertFalse(recipe.isFree(recipe.A))
        recipe.free("A")
        self.assertTrue(recipe.isFree(recipe.A))
        recipe.fix(recipe.A)
        self.assertFalse(recipe.isFree(recipe.A))
        recipe.free(recipe.A)
        self.assertTrue(recipe.isFree(recipe.A))
        recipe.fix(recipe.A)
        self.assertFalse(recipe.isFree(recipe.A))
        recipe.free("all")
        self.assertTrue(recipe.isFree(recipe.A))
        self.assertTrue(recipe.isFree(recipe.k))
        self.assertTrue(recipe.isFree(recipe.c))
        self.assertTrue(recipe.isFree(recipe.B))
        recipe.fix(recipe.A, "tagk", c=3)
        self.assertFalse(recipe.isFree(recipe.A))
        self.assertFalse(recipe.isFree(recipe.k))
        self.assertFalse(recipe.isFree(recipe.c))
        self.assertTrue(recipe.isFree(recipe.B))
        self.assertEquals(3, recipe.c.value)
        recipe.fix("all")
        self.assertFalse(recipe.isFree(recipe.A))
        self.assertFalse(recipe.isFree(recipe.k))
        self.assertFalse(recipe.isFree(recipe.c))
        self.assertFalse(recipe.isFree(recipe.B))

        self.assertRaises(ValueError, recipe.free, "junk")
        self.assertRaises(ValueError, recipe.fix, tagA=1)
        self.assertRaises(ValueError, recipe.fix, "junk")
        return

    def testVars(self):
        """Test to see if variables are added and removed properly."""
        recipe = self.recipe
        con = self.fitcontribution

        recipe.addVar(con.A, 2)
        recipe.addVar(con.k, 1)
        recipe.addVar(con.c, 0)
        recipe.newVar("B", 0)

        names = recipe.getNames()
        self.assertEquals(names, ["A", "k", "c", "B"])
        values = recipe.getValues()
        self.assertTrue((values == [2, 1, 0, 0]).all())

        # Constrain a parameter to the B-variable to give it a value
        p = Parameter("Bpar", -1)
        recipe.constrain(recipe.B, p)
        values = recipe.getValues()
        self.assertTrue((values == [2, 1, 0]).all())
        recipe.delVar(recipe.B)

        recipe.fix(recipe.k)

        names = recipe.getNames()
        self.assertEquals(names, ["A", "c"])
        values = recipe.getValues()
        self.assertTrue((values == [2, 0]).all())

        recipe.fix("all")
        names = recipe.getNames()
        self.assertEquals(names, [])
        values = recipe.getValues()
        self.assertTrue((values == []).all())

        recipe.free("all")
        names = recipe.getNames()
        self.assertEquals(3, len(names))
        self.assertTrue("A" in names)
        self.assertTrue("k" in names)
        self.assertTrue("c" in names)
        values = recipe.getValues()
        self.assertEquals(3, len(values))
        self.assertTrue(0 in values)
        self.assertTrue(1 in values)
        self.assertTrue(2 in values)
        return

    def testResidual(self):
        """Test the residual and everything that can change it."""

        # With thing set up as they are, the residual should be 0
        res = self.recipe.residual()
        self.assertAlmostEquals(0, dot(res, res))

        # Change the c value to 1 so that the equation evaluates as sin(x+1)
        x = self.profile.x
        y = sin(x + 1)
        self.recipe.cont.c.setValue(1)
        res = self.recipe.residual()
        self.assertTrue(array_equal(y - self.profile.y, res))

        # Try some constraints
        # Make c = 2*A, A = Avar
        var = self.recipe.newVar("Avar")
        self.recipe.constrain(self.fitcontribution.c, "2*A",
                              {"A": self.fitcontribution.A})
        self.assertEquals(2, self.fitcontribution.c.value)
        self.recipe.constrain(self.fitcontribution.A, var)
        self.assertEquals(1, var.getValue())
        self.assertEquals(self.recipe.cont.A.getValue(), var.getValue())
        # c is constrained to a constrained parameter.
        self.assertEquals(2, self.fitcontribution.c.value)
        # The equation should evaluate to sin(x+2)
        x = self.profile.x
        y = sin(x + 2)
        res = self.recipe.residual()
        self.assertTrue(array_equal(y - self.profile.y, res))

        # Now try some restraints. We want c to be exactly zero. It should give
        # a penalty of (c-0)**2, which is 4 in this case
        r1 = self.recipe.restrain(self.fitcontribution.c, 0, 0, 1)
        self.recipe._ready = False
        res = self.recipe.residual()
        chi2 = 4 + dot(y - self.profile.y, y - self.profile.y)
        self.assertAlmostEqual(chi2, dot(res, res))

        # Clear the constraint and restore the value of c to 0. This should
        # give us chi2 = 0 again.
        self.recipe.unconstrain(self.fitcontribution.c)
        self.fitcontribution.c.setValue(0)
        res = self.recipe.residual([self.recipe.cont.A.getValue()])
        chi2 = 0
        self.assertAlmostEqual(chi2, dot(res, res))

        # Remove the restraint and variable
        self.recipe.unrestrain(r1)
        self.recipe.delVar(self.recipe.Avar)
        self.recipe._ready = False
        res = self.recipe.residual()
        chi2 = 0
        self.assertAlmostEqual(chi2, dot(res, res))

        # Add constraints at the fitcontribution level.
        self.fitcontribution.constrain(self.fitcontribution.c, "2*A")
        # This should evaluate to sin(x+2)
        x = self.profile.x
        y = sin(x + 2)
        res = self.recipe.residual()
        self.assertTrue(array_equal(y - self.profile.y, res))

        # Add a restraint at the fitcontribution level.
        r1 = self.fitcontribution.restrain(self.fitcontribution.c, 0, 0, 1)
        self.recipe._ready = False
        # The chi2 is the same as above, plus 4
        res = self.recipe.residual()
        x = self.profile.x
        y = sin(x + 2)
        chi2 = 4 + dot(y - self.profile.y, y - self.profile.y)
        self.assertAlmostEqual(chi2, dot(res, res))

        # Remove those
        self.fitcontribution.unrestrain(r1)
        self.recipe._ready = False
        self.fitcontribution.unconstrain(self.fitcontribution.c)
        self.fitcontribution.c.setValue(0)
        res = self.recipe.residual()
        chi2 = 0
        self.assertAlmostEqual(chi2, dot(res, res))

        # Now try to use the observed profile inside of the equation
        # Set the equation equal to the data
        self.fitcontribution.setEquation("y")
        res = self.recipe.residual()
        self.assertAlmostEquals(0, dot(res, res))

        # Now add the uncertainty. This should give dy/dy = 1 for the residual
        self.fitcontribution.setEquation("y+dy")
        res = self.recipe.residual()
        self.assertAlmostEquals(len(res), dot(res, res))

        return
예제 #29
0
class SimpleRecipe(FitRecipe):
    """SimpleRecipe class.

    This is a FitRecipe with a built-in Profile (the 'profile' attribute) and
    FitContribution (the 'contribution' attribute). Unique methods from each of
    these are exposed through this class to facilitate the creation of a simple
    fit recipe.

    Attributes
    profile         --  The built-in Profile object.
    contribution    --  The built-in FitContribution object.
    results         --  The built-in FitResults object.
    name            --  A name for this FitRecipe.
    fithook         --  An object to be called whenever within the residual
                        (default FitHook()) that can pass information out of
                        the system during a refinement.
    _constraints    --  A dictionary of Constraints, indexed by the constrained
                        Parameter. Constraints can be added using the
                        'constrain' method.
    _oconstraints   --  An ordered list of the constraints from this and all
                        sub-components.
    _calculators    --  A managed dictionary of Calculators.
    _contributions  --  A managed OrderedDict of FitContributions.
    _parameters     --  A managed OrderedDict of parameters (in this case the
                        parameters are varied).
    _parsets        --  A managed dictionary of ParameterSets.
    _eqfactory      --  A diffpy.srfit.equation.builder.EquationFactory
                        instance that is used to create constraints and
                        restraints from string
    _fixed          --  A set of parameters that are not actually varied.
    _restraintlist  --  A list of restraints from this and all sub-components.
    _restraints     --  A set of Restraints. Restraints can be added using the
                        'restrain' or 'confine' methods.
    _ready          --  A flag indicating if all attributes are ready for the
                        calculation.
    _tagdict        --  A dictionary of tags to variables.
    _weights        --  List of weighing factors for each FitContribution. The
                        weights are multiplied by the residual of the
                        FitContribution when determining the overall residual.

    Properties
    names           --  Variable names (read only). See getNames.
    values          --  Variable values (read only). See getValues.

    """

    def __init__(self, name = "fit", conclass = FitContribution):
        """Initialization."""
        FitRecipe.__init__(self, name)
        self.fithooks[0].verbose = 3
        contribution = conclass("contribution")
        self.profile = Profile()
        contribution.setProfile(self.profile)
        self.addContribution(contribution)
        self.results = FitResults(self, update = False)

        # Adopt all the FitContribution methods
        public = [aname for aname in dir(contribution) if aname not in
                dir(self) and not aname.startswith("_")]
        for mname in public:
            method = getattr(contribution, mname)
            setattr(self, mname, method)
        return

    # Profile methods
    def loadParsedData(self, parser):
        """Load parsed data from a ProfileParser.

        This sets the xobs, yobs, dyobs arrays as well as the metadata.

        """
        return self.profile.loadParsedData(parser)

    def setObservedProfile(self, xobs, yobs, dyobs = None):
        """Set the observed profile.

        Arguments
        xobs    --  Numpy array of the independent variable
        yobs    --  Numpy array of the observed signal.
        dyobs   --  Numpy array of the uncertainty in the observed signal. If
                    dyobs is None (default), it will be set to 1 at each
                    observed xobs.

        Raises ValueError if len(yobs) != len(xobs)
        Raises ValueError if dyobs != None and len(dyobs) != len(xobs)

        """
        return self.profile.setObservedProfile(xobs, yobs, dyobs)


    def setCalculationRange(self, xmin=None, xmax=None, dx=None):
        """Set epsilon-inclusive calculation range.

        Adhere to the observed ``xobs`` points when ``dx`` is the same
        as in the data.  ``xmin`` and ``xmax`` are clipped at the bounds
        of the observed data.

        Parameters
        ----------

        xmin : float or "obs", optional
            The minimum value of the independent variable.  Keep the
            current minimum when not specified.  If specified as "obs"
            reset to the minimum observed value.
        xmax : float or "obs", optional
            The maximum value of the independent variable.  Keep the
            current maximum when not specified.  If specified as "obs"
            reset to the maximum observed value.
        dx : float or "obs", optional
            The sample spacing in the independent variable.  When different
            from the data, resample the ``x`` as anchored at ``xmin``.

        Note that xmin is always inclusive (unless clipped). xmax is inclusive
        if it is within the bounds of the observed data.

        Raises
        ------
        AttributeError
            If there is no observed data.
        ValueError
            When xmin > xmax or if dx <= 0.  Also if dx > xmax - xmin.
        """
        return self.profile.setCalculationRange(xmin, xmax, dx)


    def setCalculationPoints(self, x):
        """Set the calculation points.

        Arguments
        x   --  A non-empty numpy array containing the calculation points. If
                xobs exists, the bounds of x will be limited to its bounds.

        This will create y and dy on the specified grid if xobs, yobs and
        dyobs exist.

        """
        return self.profile.setCalculationPoints(x)

    def loadtxt(self, *args, **kw):
        """Use numpy.loadtxt to load data.

        Arguments are passed to numpy.loadtxt.
        unpack = True is enforced.
        The first two arrays returned by numpy.loadtxt are assumed to be x and
        y.  If there is a third array, it is assumed to by dy. Any other arrays
        are ignored. These are passed to setObservedProfile.

        Raises ValueError if the call to numpy.loadtxt returns fewer than 2
        arrays.

        Returns the x, y and dy arrays loaded from the file

        """
        return self.profile.loadtxt(*args, **kw)

    # FitContribution
    def setEquation(self, eqstr, ns = {}):
        """Set the profile equation for the FitContribution.

        This sets the equation that will be used when generating the residual.
        The equation will be usable within setResidualEquation as "eq", and it
        takes no arguments.

        eqstr   --  A string representation of the equation. Variables will be
                    extracted from this equation and be given an initial value
                    of 0.
        ns      --  A dictionary of Parameters, indexed by name, that are used
                    in the eqstr, but not registered (default {}).

        Raises ValueError if ns uses a name that is already used for a
        variable.

        """
        self.contribution.setEquation(eqstr, ns = {})
        # Extract variables
        for par in self.contribution:
            # Skip Profile  Parameters
            if par.name in ("x", "y", "dy"): continue
            if par.value is None:
                par.value = 0
            if par.name not in self._parameters:
                self.addVar(par)
        return

    def __call__(self):
        """Evaluate the contribution equation."""
        return self.contribution.evaluate()

    # FitResults methods

    def printResults(self, header = "", footer = ""):
        """Format and print the results.

        header  --  A header to add to the output (default "")
        footer  --  A footer to add to the output (default "")

        """
        self.results.printResults(header, footer, True)
        return

    def saveResults(self, filename, header = "", footer = ""):
        """Format and save the results.

        filename -  Name of the save file.
        header  --  A header to add to the output (default "")
        footer  --  A footer to add to the output (default "")

        """
        self.results.saveResults(filename, header, footer, True)
예제 #30
0
class SimpleRecipe(FitRecipe):
    """SimpleRecipe class.

    This is a FitRecipe with a built-in Profile (the 'profile' attribute) and
    FitContribution (the 'contribution' attribute). Unique methods from each of
    these are exposed through this class to facilitate the creation of a simple
    fit recipe.

    Attributes
    profile         --  The built-in Profile object.
    contribution    --  The built-in FitContribution object.
    results         --  The built-in FitResults object.
    name            --  A name for this FitRecipe.
    fithook         --  An object to be called whenever within the residual
                        (default FitHook()) that can pass information out of
                        the system during a refinement.
    _constraints    --  A dictionary of Constraints, indexed by the constrained
                        Parameter. Constraints can be added using the
                        'constrain' method.
    _oconstraints   --  An ordered list of the constraints from this and all
                        sub-components.
    _calculators    --  A managed dictionary of Calculators.
    _contributions  --  A managed OrderedDict of FitContributions.
    _parameters     --  A managed OrderedDict of parameters (in this case the
                        parameters are varied).
    _parsets        --  A managed dictionary of ParameterSets.
    _eqfactory      --  A diffpy.srfit.equation.builder.EquationFactory
                        instance that is used to create constraints and
                        restraints from string
    _fixed          --  A set of parameters that are not actually varied.
    _restraintlist  --  A list of restraints from this and all sub-components.
    _restraints     --  A set of Restraints. Restraints can be added using the
                        'restrain' or 'confine' methods.
    _ready          --  A flag indicating if all attributes are ready for the
                        calculation.
    _tagdict        --  A dictionary of tags to variables.
    _weights        --  List of weighing factors for each FitContribution. The
                        weights are multiplied by the residual of the
                        FitContribution when determining the overall residual.

    Properties
    names           --  Variable names (read only). See getNames.
    values          --  Variable values (read only). See getValues.

    """
    def __init__(self, name="fit", conclass=FitContribution):
        """Initialization."""
        FitRecipe.__init__(self, name)
        self.fithooks[0].verbose = 3
        contribution = conclass("contribution")
        self.profile = Profile()
        contribution.setProfile(self.profile)
        self.addContribution(contribution)
        self.results = FitResults(self, update=False)

        # Adopt all the FitContribution methods
        public = [
            aname for aname in dir(contribution)
            if aname not in dir(self) and not aname.startswith("_")
        ]
        for mname in public:
            method = getattr(contribution, mname)
            setattr(self, mname, method)
        return

    # Profile methods
    def loadParsedData(self, parser):
        """Load parsed data from a ProfileParser.

        This sets the xobs, yobs, dyobs arrays as well as the metadata.

        """
        return self.profile.loadParsedData(parser)

    def setObservedProfile(self, xobs, yobs, dyobs=None):
        """Set the observed profile.

        Arguments
        xobs    --  Numpy array of the independent variable
        yobs    --  Numpy array of the observed signal.
        dyobs   --  Numpy array of the uncertainty in the observed signal. If
                    dyobs is None (default), it will be set to 1 at each
                    observed xobs.

        Raises ValueError if len(yobs) != len(xobs)
        Raises ValueError if dyobs != None and len(dyobs) != len(xobs)

        """
        return self.profile.setObservedProfile(xobs, yobs, dyobs)

    def setCalculationRange(self, xmin=None, xmax=None, dx=None):
        """Set epsilon-inclusive calculation range.

        Adhere to the observed ``xobs`` points when ``dx`` is the same
        as in the data.  ``xmin`` and ``xmax`` are clipped at the bounds
        of the observed data.

        Parameters
        ----------

        xmin : float or "obs", optional
            The minimum value of the independent variable.  Keep the
            current minimum when not specified.  If specified as "obs"
            reset to the minimum observed value.
        xmax : float or "obs", optional
            The maximum value of the independent variable.  Keep the
            current maximum when not specified.  If specified as "obs"
            reset to the maximum observed value.
        dx : float or "obs", optional
            The sample spacing in the independent variable.  When different
            from the data, resample the ``x`` as anchored at ``xmin``.

        Note that xmin is always inclusive (unless clipped). xmax is inclusive
        if it is within the bounds of the observed data.

        Raises
        ------
        AttributeError
            If there is no observed data.
        ValueError
            When xmin > xmax or if dx <= 0.  Also if dx > xmax - xmin.
        """
        return self.profile.setCalculationRange(xmin, xmax, dx)

    def setCalculationPoints(self, x):
        """Set the calculation points.

        Arguments
        x   --  A non-empty numpy array containing the calculation points. If
                xobs exists, the bounds of x will be limited to its bounds.

        This will create y and dy on the specified grid if xobs, yobs and
        dyobs exist.

        """
        return self.profile.setCalculationPoints(x)

    def loadtxt(self, *args, **kw):
        """Use numpy.loadtxt to load data.

        Arguments are passed to numpy.loadtxt.
        unpack = True is enforced.
        The first two arrays returned by numpy.loadtxt are assumed to be x and
        y.  If there is a third array, it is assumed to by dy. Any other arrays
        are ignored. These are passed to setObservedProfile.

        Raises ValueError if the call to numpy.loadtxt returns fewer than 2
        arrays.

        Returns the x, y and dy arrays loaded from the file

        """
        return self.profile.loadtxt(*args, **kw)

    # FitContribution
    def setEquation(self, eqstr, ns={}):
        """Set the profile equation for the FitContribution.

        This sets the equation that will be used when generating the residual.
        The equation will be usable within setResidualEquation as "eq", and it
        takes no arguments.

        eqstr   --  A string representation of the equation. Variables will be
                    extracted from this equation and be given an initial value
                    of 0.
        ns      --  A dictionary of Parameters, indexed by name, that are used
                    in the eqstr, but not registered (default {}).

        Raises ValueError if ns uses a name that is already used for a
        variable.

        """
        self.contribution.setEquation(eqstr, ns={})
        # Extract variables
        for par in self.contribution:
            # Skip Profile  Parameters
            if par.name in ("x", "y", "dy"): continue
            if par.value is None:
                par.value = 0
            if par.name not in self._parameters:
                self.addVar(par)
        return

    def __call__(self):
        """Evaluate the contribution equation."""
        return self.contribution.evaluate()

    # FitResults methods

    def printResults(self, header="", footer=""):
        """Format and print the results.

        header  --  A header to add to the output (default "")
        footer  --  A footer to add to the output (default "")

        """
        self.results.printResults(header, footer, True)
        return

    def saveResults(self, filename, header="", footer=""):
        """Format and save the results.

        filename -  Name of the save file.
        header  --  A header to add to the output (default "")
        footer  --  A footer to add to the output (default "")

        """
        self.results.saveResults(filename, header, footer, True)