예제 #1
0
def makeRecipe():
    """Make the recipe for the fit.

    The instructions for what we want to refine, and how to refine it will be
    defined within a FitRecipe instance. The job of a FitRecipe is to collect
    and associate all the data, the fitting equations, fitting variables,
    constraints and restrations. We will demonstrate each of these within the
    code. 

    Data is held within a Profile object. The Profile is simply a container
    that holds the data, and the theoretical profile once it has been
    calculated.

    Data is associated with a fitting equation within a FitContribution. The
    FitContribution defines the equation and parameters that will be adjusted
    to fit the data. The fitting equation can be defined within a function or
    optionally within the ProfileGenerator class. We won't need the
    ProfileGenerator class in this example since the signature of the fitting
    equation (the 'debye' function defined below) is so simple. The
    FitContribution also defines the residual function to optimize for the
    data/equation pair. This can be modified, but we won't do that here.
    
    """
        
    ## The Profile
    # Create a Profile to hold the experimental and calculated signal.
    profile = Profile()

    # Load data and add it to the profile. It is our responsibility to get our
    # data into the profile.
    xydy = numpy.array(map(float, data.split()), dtype=float).reshape(-1,3)
    x, y, dy = numpy.hsplit(xydy, 3)
    profile.setObservedProfile(x, y, dy)

    ## The FitContribution
    # The FitContribution associates the profile with the Debye function. 
    contribution = FitContribution("pb")
    # Tell the contribution about the Profile. We will need to use the
    # independent variable (the temperature) from the data to calculate the
    # theoretical signal, so give it an informative name ('T') that we can use
    # later.
    contribution.setProfile(profile, xname="T")

    # We now need to create the fitting equation.  We tell the FitContribution
    # to use the 'debye' function defined below. The 'registerFunction' method
    # will let us do this. Since we haven't told it otherwise,
    # 'registerFunction' will extract the name of the function ('debye') and
    # the names of the arguments ('T', 'm', 'thetaD'). These arguments will
    # become Parameters of the FitContribution. Since we named the x-variable
    # 'T' above, the 'T' in the 'debye' equation will refer to this x-variable
    # whenever it is used.
    contribution.registerFunction(debye)

    # Now we can create the fitting equation. We want to extend the 'debye'
    # equation by adding a vertical offset. We could wrap 'debye' in a new
    # function with an offset, and register that instead of 'debye', but what
    # we do here is easier. 
    #
    # When we set the fitting equation, we do not need to specify the
    # Parameters to the 'debye' function since the FitContribution already
    # knows what they are. If we choose to specify the arguments, we can make
    # adjustments to their input values.  We wish to have the thetaD value in
    # the debye equation to be positive, so we specify the input as abs(thetaD)
    # in the equation below.  Furthermore, we know 'm', the mass of lead, so we
    # can specify that as well.
    contribution.setEquation("debye(T, 207.2, abs(thetaD)) + offset")

    ## The FitRecipe
    # The FitRecipe lets us define what we want to fit. It is where we can
    # create variables, constraints and restraints. If we had multiple profiles
    # to fit simultaneously, the contribution from each could be added to the
    # recipe.
    recipe = FitRecipe()
    recipe.addContribution(contribution)

    # Specify which Parameters we want to refine.

    # Vary the offset
    recipe.addVar(contribution.offset, 0)
    # We also vary the Debye temperature.
    recipe.addVar(contribution.thetaD, 100)

    # We would like to 'suggest' that the offset should remain positive. This
    # is somethine that we know about the system that might help the refinement
    # converge to a physically reasonable result.  We will do this with a soft
    # contraint, or restraint. Here we restrain the offset variable to between
    # 0 and infinity. We tell the recipe that we want to scale the penalty for
    # breaking the restraint by the point-average chi^2 value so that the
    # restraint is roughly as significant as any other data point throughout
    # the fit.
    recipe.restrain(recipe.offset, lb = 0, scaled = True)

    # We're done setting up the recipe. We can now do other things with it.
    return recipe
def makeRecipe(niciffile, siciffile, datname):
    """Create a fitting recipe for crystalline PDF data."""

    # Load data and add it to the profile
    contribution = PDFContribution("nisi")
    contribution.loadData(datname)
    contribution.setCalculationRange(xmax=20)

    stru = CreateCrystalFromCIF(file(niciffile))
    contribution.addStructure("ni", stru)

    stru = CreateCrystalFromCIF(file(siciffile))
    contribution.addStructure("si", stru)

    # Make the FitRecipe and add the FitContribution.
    recipe = FitRecipe()
    recipe.addContribution(contribution)

    ## Configure the fit variables
    # Start by configuring the scale factor and resolution factors.
    # We want the sum of the phase scale factors to be 1.
    recipe.newVar("scale_ni", 0.1)
    recipe.constrain(contribution.ni.scale, "scale_ni")
    recipe.constrain(contribution.si.scale, "1 - scale_ni")
    # We also want the resolution factor to be the same on each. This is done
    # for free by the PDFContribution. We simply need to add it to the recipe.
    recipe.addVar(contribution.qdamp, 0.03)

    # Vary the gloabal scale as well.
    recipe.addVar(contribution.scale, 1)

    # Now we can configure the structural parameters. Since we're using
    # ObjCrystCrystalParSets, the space group constraints are automatically
    # applied to each phase. We must selectively vary the free parameters.
    #
    # First the nickel parameters.
    # Note that ni is the name of the PDFGenerator that was automatically
    # created by the PDFContribution. We selected this name in addStructure
    # above.
    phase_ni = contribution.ni.phase
    for par in phase_ni.sgpars:
        recipe.addVar(par, name=par.name + "_ni")
    recipe.addVar(contribution.ni.delta2, name="delta2_ni")
    # Next the silicon parameters
    phase_si = contribution.si.phase
    for par in phase_si.sgpars:
        recipe.addVar(par, name=par.name + "_si")
    recipe.addVar(contribution.si.delta2, name="delta2_si")

    # We have prior information from the earlier examples so we'll use it here
    # in the form of restraints.
    #
    # The nickel lattice parameter was measured to be 3.527. The uncertainty
    # values are invalid for that measurement, since the data from which it is
    # derived has no uncertainty. Thus, we will tell the recipe to scale the
    # residual, which means that it will be weighted as much as the average
    # data point during the fit.
    recipe.restrain("a_ni", lb=3.527, ub=3.527, scaled=True)
    # Now we do the same with the delta2 and Biso parameters (remember that
    # Biso = 8*pi**2*Uiso)
    recipe.restrain("delta2_ni", lb=2.22, ub=2.22, scaled=True)
    recipe.restrain("Biso_0_ni", lb=0.454, ub=0.454, scaled=True)
    #
    # We can do the same with the silicon values. We haven't done a thorough
    # job of measuring the uncertainties in the results, so we'll scale these
    # as well.
    recipe.restrain("a_si", lb=5.430, ub=5.430, scaled=True)
    recipe.restrain("delta2_si", lb=3.54, ub=3.54, scaled=True)
    recipe.restrain("Biso_0_si", lb=0.645, ub=0.645, scaled=True)

    # Give the recipe away so it can be used!
    return recipe
def makeRecipe(niciffile, siciffile, datname):
    """Create a fitting recipe for crystalline PDF data."""

    ## The Profile
    profile = Profile()

    # Load data and add it to the profile
    parser = PDFParser()
    parser.parseFile(datname)
    profile.loadParsedData(parser)
    profile.setCalculationRange(xmax = 20)

    ## The ProfileGenerator
    # In order to fit two phases simultaneously, we must use two PDFGenerators.
    # PDFGenerator is designed to take care of as little information as it
    # must. (Don't do too much, and do it well.) A PDFGenerator can generate
    # the signal from only a single phase at a time. So, we will create one
    # PDFGenerator for each phase and compose them within the same
    # FitContribution. Note that both generators will be associated with the
    # same Profile within the FitContribution, so they will both be
    # automatically configured according to the metadata.
    #
    # The generator for the nickel phase. We call it "G_ni" and will use this
    # name later when we set the fitting equation in the FitContribution.
    generator_ni = PDFGenerator("G_ni")
    stru = CreateCrystalFromCIF(file(niciffile))
    generator_ni.setStructure(stru)
    # The generator for the silicon phase. We call it "G_si".
    generator_si = PDFGenerator("G_si")
    stru = CreateCrystalFromCIF(file(siciffile))
    generator_si.setStructure(stru)

    ## The FitContribution
    # Add both generators to the FitContribution. Add the Profile. This will
    # send the metadata to the generators.
    contribution = FitContribution("nisi")
    contribution.addProfileGenerator(generator_ni)
    contribution.addProfileGenerator(generator_si)
    contribution.setProfile(profile, xname = "r")

    # Write the fitting equation. We want to sum the PDFs from each phase and
    # multiply it by a scaling factor. We also want a certain phase scaling
    # relationship between the PDFs which we will enforce with constraints in
    # the FitRecipe.
    contribution.setEquation("scale * (G_ni +  G_si)")

    # Make the FitRecipe and add the FitContribution.
    recipe = FitRecipe()
    recipe.addContribution(contribution)

    ## Configure the fit variables
    # Start by configuring the scale factor and resolution factors.
    # We want the sum of the phase scale factors to be 1.
    recipe.newVar("scale_ni", 0.1)
    recipe.constrain(generator_ni.scale, "scale_ni")
    recipe.constrain(generator_si.scale, "1 - scale_ni")
    # We also want the resolution factor to be the same on each.
    recipe.newVar("qdamp", 0.03)
    recipe.constrain(generator_ni.qdamp, "qdamp")
    recipe.constrain(generator_si.qdamp, "qdamp")

    # Vary the gloabal scale as well.
    recipe.addVar(contribution.scale, 1)

    # Now we can configure the structural parameters. Since we're using
    # ObjCrystCrystalParSets, the space group constraints are automatically
    # applied to each phase. We must selectively vary the free parameters.
    #
    # First the nickel parameters
    phase_ni = generator_ni.phase
    for par in phase_ni.sgpars:
        recipe.addVar(par, name = par.name + "_ni")
    recipe.addVar(generator_ni.delta2, name = "delta2_ni")
    # Next the silicon parameters
    phase_si = generator_si.phase
    for par in phase_si.sgpars:
        recipe.addVar(par, name = par.name + "_si")
    recipe.addVar(generator_si.delta2, name = "delta2_si")

    # We have prior information from the earlier examples so we'll use it here
    # in the form of restraints.
    #
    # The nickel lattice parameter was measured to be 3.527. The uncertainty
    # values are invalid for that measurement, since the data from which it is
    # derived has no uncertainty. Thus, we will tell the recipe to scale the
    # residual, which means that it will be weighted as much as the average
    # data point during the fit.
    recipe.restrain("a_ni", lb = 3.527, ub = 3.527, scaled = True)
    # Now we do the same with the delta2 and Biso parameters (remember that
    # Biso = 8*pi**2*Uiso)
    recipe.restrain("delta2_ni", lb = 2.22, ub = 2.22, scaled = True)
    recipe.restrain("Biso_0_ni", lb = 0.454, ub = 0.454, scaled = True)
    #
    # We can do the same with the silicon values. We haven't done a thorough
    # job of measuring the uncertainties in the results, so we'll scale these
    # as well.
    recipe.restrain("a_si", lb = 5.430, ub = 5.430, scaled = True)
    recipe.restrain("delta2_si", lb = 3.54, ub = 3.54, scaled = True)
    recipe.restrain("Biso_0_si", lb = 0.645, ub = 0.645, scaled = True)

    # Give the recipe away so it can be used!
    return recipe
예제 #4
0
def makeRecipe():
    """Make the recipe for the fit.

    The instructions for what we want to refine, and how to refine it will be
    defined within a FitRecipe instance. The job of a FitRecipe is to collect
    and associate all the data, the fitting equations, fitting variables,
    constraints and restrations. We will demonstrate each of these within the
    code.

    Data is held within a Profile object. The Profile is simply a container
    that holds the data, and the theoretical profile once it has been
    calculated.

    Data is associated with a fitting equation within a FitContribution. The
    FitContribution defines the equation and parameters that will be adjusted
    to fit the data. The fitting equation can be defined within a function or
    optionally within the ProfileGenerator class. We won't need the
    ProfileGenerator class in this example since the signature of the fitting
    equation (the 'debye' function defined below) is so simple. The
    FitContribution also defines the residual function to optimize for the
    data/equation pair. This can be modified, but we won't do that here.

    """

    ## The Profile
    # Create a Profile to hold the experimental and calculated signal.
    profile = Profile()

    # Load data and add it to the profile. It is our responsibility to get our
    # data into the profile.
    xydy = numpy.array(map(float, data.split()), dtype=float).reshape(-1,3)
    x, y, dy = numpy.hsplit(xydy, 3)
    profile.setObservedProfile(x, y, dy)

    ## The FitContribution
    # The FitContribution associates the profile with the Debye function.
    contribution = FitContribution("pb")
    # Tell the contribution about the Profile. We will need to use the
    # independent variable (the temperature) from the data to calculate the
    # theoretical signal, so give it an informative name ('T') that we can use
    # later.
    contribution.setProfile(profile, xname="T")

    # We now need to create the fitting equation.  We tell the FitContribution
    # to use the 'debye' function defined below. The 'registerFunction' method
    # will let us do this. Since we haven't told it otherwise,
    # 'registerFunction' will extract the name of the function ('debye') and
    # the names of the arguments ('T', 'm', 'thetaD'). These arguments will
    # become Parameters of the FitContribution. Since we named the x-variable
    # 'T' above, the 'T' in the 'debye' equation will refer to this x-variable
    # whenever it is used.
    contribution.registerFunction(debye)

    # Now we can create the fitting equation. We want to extend the 'debye'
    # equation by adding a vertical offset. We could wrap 'debye' in a new
    # function with an offset, and register that instead of 'debye', but what
    # we do here is easier.
    #
    # When we set the fitting equation, we do not need to specify the
    # Parameters to the 'debye' function since the FitContribution already
    # knows what they are. If we choose to specify the arguments, we can make
    # adjustments to their input values.  We wish to have the thetaD value in
    # the debye equation to be positive, so we specify the input as abs(thetaD)
    # in the equation below.  Furthermore, we know 'm', the mass of lead, so we
    # can specify that as well.
    contribution.setEquation("debye(T, 207.2, abs(thetaD)) + offset")

    ## The FitRecipe
    # The FitRecipe lets us define what we want to fit. It is where we can
    # create variables, constraints and restraints. If we had multiple profiles
    # to fit simultaneously, the contribution from each could be added to the
    # recipe.
    recipe = FitRecipe()
    recipe.addContribution(contribution)

    # Specify which Parameters we want to refine.

    # Vary the offset
    recipe.addVar(contribution.offset, 0)
    # We also vary the Debye temperature.
    recipe.addVar(contribution.thetaD, 100)

    # We would like to 'suggest' that the offset should remain positive. This
    # is somethine that we know about the system that might help the refinement
    # converge to a physically reasonable result.  We will do this with a soft
    # contraint, or restraint. Here we restrain the offset variable to between
    # 0 and infinity. We tell the recipe that we want to scale the penalty for
    # breaking the restraint by the point-average chi^2 value so that the
    # restraint is roughly as significant as any other data point throughout
    # the fit.
    recipe.restrain(recipe.offset, lb = 0, scaled = True)

    # We're done setting up the recipe. We can now do other things with it.
    return recipe
예제 #5
0
파일: pdffit.py 프로젝트: ml-evs/matador
    def make_recipe(self, structure, sg):
        """ Construct PDF with diffpy. """

        # construct a PDFContribution object
        pdf = PDFContribution("Contribution")
        # read experimental data
        try:
            pdf.loadData(self.input_file)
        except:
            print_failure('Failed to parse ' + self.input_file +
                          '. Exiting...')
            exit()

        print('Constructing PDF object for', structure.title)

        pdf.setCalculationRange(self.xmin, self.xmax, self.dx)
        pdf.addStructure("Contribution", structure)

        # create FitRecipe to calculate PDF with chosen fit variable
        fit = FitRecipe()
        fit.addContribution(pdf)
        # configure variables and add to recipe
        if sg != 'xxx' and sg is not None:
            print(sg)
            spacegroup_params = constrainAsSpaceGroup(pdf.Contribution.phase,
                                                      sg)
        else:
            cart_lat = abc2cart([[
                structure.lattice.a, structure.lattice.b, structure.lattice.c
            ],
                                 [
                                     structure.lattice.alpha,
                                     structure.lattice.beta,
                                     structure.lattice.gamma
                                 ]])
            positions_frac = structure.xyz
            atomic_numbers = []
            for atom in structure.element:
                atomic_numbers.append(get_atomic_number(atom))
            cell = (cart_lat, positions_frac, atomic_numbers)
            sg = int(
                spg.get_spacegroup(cell, symprec=1e-2).split(' ')[1].replace(
                    '(', '').replace(')', ''))
            spacegroup_params = constrainAsSpaceGroup(pdf.Contribution.phase,
                                                      sg)
        # print('Space group parameters:')
        # print(', '.join([param.name for param in spacegroup_params]))
        # iterate through spacegroup params and activate them
        for param in spacegroup_params.latpars:
            fit.addVar(param)
        for param in spacegroup_params.xyzpars:
            fit.addVar(param, fixed=True)
        # these next parameters are taken from Martin's PDFht.py,
        # though I have a feeling that was not their origin...
        # set initial ADP parameters
        for param in spacegroup_params.adppars:
            fit.addVar(param, value=0.03, fixed=True)
        # overall scale of PDF and delta2 parameter for correlated motion - from PDFht.py
        fit.addVar(pdf.scale, 1, fixed=True)
        fit.restrain(pdf.scale, lb=0, ub=0.1, scaled=True)
        fit.addVar(pdf.Contribution.delta2, 5, fixed=True)
        fit.restrain(pdf.Contribution.delta2, lb=1, ub=10, scaled=True)
        # fix Qdamp based on information about "our beamline": yep, no idea
        fit.addVar(pdf.qdamp, 0.03, fixed=True)
        fit.restrain(pdf.qdamp, lb=0, ub=0.1, scaled=True)

        return fit
예제 #6
0
# Fixed variables may be released with the "free" function.
# free("all") releases all fixed variables.
rec.free('all')

# Variables may be constrained to a result of an expression.
rec.constrain(rec.A, "2 * B")

# Perform linear fit where slope is twice the offset.
leastsq(rec.residual, rec.values)
print(FitResults(rec))
plt.plot(linedata.x, linedata.y, 'x', linedata.x, linedata.ycalc, '-')
plt.title('Line fit for variable A constrained to A = 2*B')

# <demo> --- stop ---

# Constraint expressions can be removed by calling the unconstrain function.
rec.unconstrain(rec.A)

# Variables may be restrained to a specific range.  Here "ub" is the upper
# boundary and "sig" acts as a standard deviation for ((x - ub)/sig)**2
# penalty function.

arst = rec.restrain(rec.A, ub=0.2, sig=0.001)

# Perform fit with the line slope restrained to a maximum value of 0.2:
leastsq(rec.residual, rec.values)
print(FitResults(rec))
plt.plot(linedata.x, linedata.y, 'x', linedata.x, linedata.ycalc, '-')
plt.title('Line fit with A restrained to an upper bound of 0.2')
예제 #7
0
def makeRecipe(niciffile, siciffile, datname):
    """Create a fitting recipe for crystalline PDF data."""

    # Load data and add it to the profile
    contribution = PDFContribution("nisi")
    contribution.loadData(datname)
    contribution.setCalculationRange(xmax = 20)

    stru = CreateCrystalFromCIF(file(niciffile))
    contribution.addStructure("ni", stru)

    stru = CreateCrystalFromCIF(file(siciffile))
    contribution.addStructure("si", stru)

    # Make the FitRecipe and add the FitContribution.
    recipe = FitRecipe()
    recipe.addContribution(contribution)

    ## Configure the fit variables
    # Start by configuring the scale factor and resolution factors.
    # We want the sum of the phase scale factors to be 1.
    recipe.newVar("scale_ni", 0.1)
    recipe.constrain(contribution.ni.scale, "scale_ni")
    recipe.constrain(contribution.si.scale, "1 - scale_ni")
    # We also want the resolution factor to be the same on each. This is done
    # for free by the PDFContribution. We simply need to add it to the recipe.
    recipe.addVar(contribution.qdamp, 0.03)

    # Vary the gloabal scale as well.
    recipe.addVar(contribution.scale, 1)

    # Now we can configure the structural parameters. Since we're using
    # ObjCrystCrystalParSets, the space group constraints are automatically
    # applied to each phase. We must selectively vary the free parameters.
    #
    # First the nickel parameters.
    # Note that ni is the name of the PDFGenerator that was automatically
    # created by the PDFContribution. We selected this name in addStructure
    # above.
    phase_ni = contribution.ni.phase
    for par in phase_ni.sgpars:
        recipe.addVar(par, name = par.name + "_ni")
    recipe.addVar(contribution.ni.delta2, name = "delta2_ni")
    # Next the silicon parameters
    phase_si = contribution.si.phase
    for par in phase_si.sgpars:
        recipe.addVar(par, name = par.name + "_si")
    recipe.addVar(contribution.si.delta2, name = "delta2_si")

    # We have prior information from the earlier examples so we'll use it here
    # in the form of restraints.
    #
    # The nickel lattice parameter was measured to be 3.527. The uncertainty
    # values are invalid for that measurement, since the data from which it is
    # derived has no uncertainty. Thus, we will tell the recipe to scale the
    # residual, which means that it will be weighted as much as the average
    # data point during the fit.
    recipe.restrain("a_ni", lb = 3.527, ub = 3.527, scaled = True)
    # Now we do the same with the delta2 and Biso parameters (remember that
    # Biso = 8*pi**2*Uiso)
    recipe.restrain("delta2_ni", lb = 2.22, ub = 2.22, scaled = True)
    recipe.restrain("Biso_0_ni", lb = 0.454, ub = 0.454, scaled = True)
    #
    # We can do the same with the silicon values. We haven't done a thorough
    # job of measuring the uncertainties in the results, so we'll scale these
    # as well.
    recipe.restrain("a_si", lb = 5.430, ub = 5.430, scaled = True)
    recipe.restrain("delta2_si", lb = 3.54, ub = 3.54, scaled = True)
    recipe.restrain("Biso_0_si", lb = 0.645, ub = 0.645, scaled = True)

    # Give the recipe away so it can be used!
    return recipe
예제 #8
0
def makeRecipe(niciffile, siciffile, datname):
    """Create a fitting recipe for crystalline PDF data."""

    ## The Profile
    profile = Profile()

    # Load data and add it to the profile
    parser = PDFParser()
    parser.parseFile(datname)
    profile.loadParsedData(parser)
    profile.setCalculationRange(xmax=20)

    ## The ProfileGenerator
    # In order to fit two phases simultaneously, we must use two PDFGenerators.
    # PDFGenerator is designed to take care of as little information as it
    # must. (Don't do too much, and do it well.) A PDFGenerator can generate
    # the signal from only a single phase at a time. So, we will create one
    # PDFGenerator for each phase and compose them within the same
    # FitContribution. Note that both generators will be associated with the
    # same Profile within the FitContribution, so they will both be
    # automatically configured according to the metadata.
    #
    # The generator for the nickel phase. We call it "G_ni" and will use this
    # name later when we set the fitting equation in the FitContribution.
    generator_ni = PDFGenerator("G_ni")
    stru = CreateCrystalFromCIF(file(niciffile))
    generator_ni.setStructure(stru)
    # The generator for the silicon phase. We call it "G_si".
    generator_si = PDFGenerator("G_si")
    stru = CreateCrystalFromCIF(file(siciffile))
    generator_si.setStructure(stru)

    ## The FitContribution
    # Add both generators to the FitContribution. Add the Profile. This will
    # send the metadata to the generators.
    contribution = FitContribution("nisi")
    contribution.addProfileGenerator(generator_ni)
    contribution.addProfileGenerator(generator_si)
    contribution.setProfile(profile, xname="r")

    # Write the fitting equation. We want to sum the PDFs from each phase and
    # multiply it by a scaling factor. We also want a certain phase scaling
    # relationship between the PDFs which we will enforce with constraints in
    # the FitRecipe.
    contribution.setEquation("scale * (G_ni +  G_si)")

    # Make the FitRecipe and add the FitContribution.
    recipe = FitRecipe()
    recipe.addContribution(contribution)

    ## Configure the fit variables
    # Start by configuring the scale factor and resolution factors.
    # We want the sum of the phase scale factors to be 1.
    recipe.newVar("scale_ni", 0.1)
    recipe.constrain(generator_ni.scale, "scale_ni")
    recipe.constrain(generator_si.scale, "1 - scale_ni")
    # We also want the resolution factor to be the same on each.
    recipe.newVar("qdamp", 0.03)
    recipe.constrain(generator_ni.qdamp, "qdamp")
    recipe.constrain(generator_si.qdamp, "qdamp")

    # Vary the gloabal scale as well.
    recipe.addVar(contribution.scale, 1)

    # Now we can configure the structural parameters. Since we're using
    # ObjCrystCrystalParSets, the space group constraints are automatically
    # applied to each phase. We must selectively vary the free parameters.
    #
    # First the nickel parameters
    phase_ni = generator_ni.phase
    for par in phase_ni.sgpars:
        recipe.addVar(par, name=par.name + "_ni")
    recipe.addVar(generator_ni.delta2, name="delta2_ni")
    # Next the silicon parameters
    phase_si = generator_si.phase
    for par in phase_si.sgpars:
        recipe.addVar(par, name=par.name + "_si")
    recipe.addVar(generator_si.delta2, name="delta2_si")

    # We have prior information from the earlier examples so we'll use it here
    # in the form of restraints.
    #
    # The nickel lattice parameter was measured to be 3.527. The uncertainty
    # values are invalid for that measurement, since the data from which it is
    # derived has no uncertainty. Thus, we will tell the recipe to scale the
    # residual, which means that it will be weighted as much as the average
    # data point during the fit.
    recipe.restrain("a_ni", lb=3.527, ub=3.527, scaled=True)
    # Now we do the same with the delta2 and Biso parameters (remember that
    # Biso = 8*pi**2*Uiso)
    recipe.restrain("delta2_ni", lb=2.22, ub=2.22, scaled=True)
    recipe.restrain("Biso_0_ni", lb=0.454, ub=0.454, scaled=True)
    #
    # We can do the same with the silicon values. We haven't done a thorough
    # job of measuring the uncertainties in the results, so we'll scale these
    # as well.
    recipe.restrain("a_si", lb=5.430, ub=5.430, scaled=True)
    recipe.restrain("delta2_si", lb=3.54, ub=3.54, scaled=True)
    recipe.restrain("Biso_0_si", lb=0.645, ub=0.645, scaled=True)

    # Give the recipe away so it can be used!
    return recipe
예제 #9
0
# Fixed variables may be released with the "free" function.
# free("all") releases all fixed variables.
rec.free('all')

# Variables may be constrained to a result of an expression.
rec.constrain(rec.A, "2 * B")

# Perform linear fit where slope is twice the offset.
leastsq(rec.residual, rec.values)
print(FitResults(rec))
plt.plot(linedata.x, linedata.y, 'x', linedata.x, linedata.ycalc, '-')
plt.title('Line fit for variable A constrained to A = 2*B')

# <demo> --- stop ---

# Constraint expressions can be removed by calling the unconstrain function.
rec.unconstrain(rec.A)

# Variables may be restrained to a specific range.  Here "ub" is the upper
# boundary and "sig" acts as a standard deviation for ((x - ub)/sig)**2
# penalty function.

arst = rec.restrain(rec.A, ub=0.2, sig=0.001)

# Perform fit with the line slope restrained to a maximum value of 0.2:
leastsq(rec.residual, rec.values)
print(FitResults(rec))
plt.plot(linedata.x, linedata.y, 'x', linedata.x, linedata.ycalc, '-')
plt.title('Line fit with A restrained to an upper bound of 0.2')
예제 #10
0
# <demo> --- stop ---

# Variables defined in the recipe can be fixed to a constant value.

recipe.fix(lgx0=51)

# The fixed variables can be checked using the "fixednames" and
# "fixedvalues" attributes of a recipe.
print("free:", recipe.names, "-->", recipe.names)
print("fixed:", recipe.fixednames, "-->", recipe.fixedvalues)

# The fit can be rerun with a constant variable B.
leastsq(recipe.residual, recipe.values)
print(FitResults(recipe))
plt.plot(profile.x, profile.y, 'x', profile.x, profile.ycalc, '-')
plt.title('Line fit for variable x0 fixed to x0=51')

# <demo> --- stop ---

# Fixed variables may be released with the "free" function.
# free("all") releases all fixed variables.
recipe.free('all')

arst = recipe.restrain(recipe.lgx0, lb=48, ub=52, sig=0.01)

# Perform fit with the line slope restrained to a maximum value of 0.2:
leastsq(recipe.residual, recipe.values)
print(FitResults(recipe))
plt.plot(profile.x, profile.y, 'x', profile.x, profile.ycalc, '-')
plt.title('Line fit with x0 restrained to the range 48 to 52')