예제 #1
0
def main():

    # Make the data and the recipe
    strufile = "data/C60.stru"
    q = numpy.arange(1, 20, 0.05)
    makeData(strufile, q, "C60.iq", 1.0, 100.68, 0.005, 0.13, 2)

    # Make the recipe
    recipe = makeRecipe(strufile, "C60.iq")

    # Optimize
    scipyOptimize(recipe)

    # Generate and print the FitResults
    res = FitResults(recipe)
    # We want to see how much speed-up we get from bringing the scale and
    # background outside of the intensity generator.  Get the number of calls
    # to the residual function from the FitRecipe, and the number of calls to
    # 'iofq' from the IntensityGenerator.
    rescount = recipe.fithooks[0].count
    calcount = recipe.bucky.I.count
    footer = "iofq called %i%% of the time"%int(100.0*calcount/rescount)
    res.printResults(footer = footer)

    # Plot!
    plotResults(recipe)

    return
예제 #2
0
def main():
    """Refine the C60 molecule.

    From previous examples we know that the radius of the model structure is
    slightly too small. The annealing algorithm has to determine the proper
    radius, and must also account for thermal vibrations in the PDF.

    """

    molecule = makeC60()
    recipe = makeRecipe(molecule, "data/C60.gr")
    recipe.fithooks[0].verbose = 0

    # Optimize
    # Group related atomic positions for the optimizer
    parlist = [getXYZNames(i) for i in xrange(60)]
    groupAnneal(recipe, parlist)

    # Print results
    recipe.fix("all")
    res = FitResults(recipe, showfixed=False)
    res.printResults()

    # Save the structure
    molecule.write("C60_refined.stru", "pdffit")

    # Plot results
    plotResults(recipe)

    return
예제 #3
0
def main():
    """Refine the C60 molecule.

    From previous examples we know that the radius of the model structure is
    slightly too small. The annealing algorithm has to determine the proper
    radius, and must also account for thermal vibrations in the PDF.

    """

    molecule = makeC60()
    recipe = makeRecipe(molecule, "data/C60.gr")
    recipe.fithooks[0].verbose = 0

    # Optimize
    # Group related atomic positions for the optimizer
    parlist = [getXYZNames(i) for i in xrange(60)]
    groupAnneal(recipe, parlist)

    # Print results
    recipe.fix("all")
    res = FitResults(recipe, showfixed = False)
    res.printResults()

    # Save the structure
    molecule.write("C60_refined.stru", "pdffit")

    # Plot results
    plotResults(recipe)

    return
예제 #4
0
def main():

    # Make the data and the recipe
    strufile = "data/C60.stru"
    q = numpy.arange(1, 20, 0.05)
    makeData(strufile, q, "C60.iq", 1.0, 100.68, 0.005, 0.13, 2)

    # Make the recipe
    recipe = makeRecipe(strufile, "C60.iq")

    # Optimize
    scipyOptimize(recipe)

    # Generate and print the FitResults
    res = FitResults(recipe)
    # We want to see how much speed-up we get from bringing the scale and
    # background outside of the intensity generator.  Get the number of calls
    # to the residual function from the FitRecipe, and the number of calls to
    # 'iofq' from the IntensityGenerator.
    rescount = recipe.fithooks[0].count
    calcount = recipe.bucky.I.count
    footer = "iofq called %i%% of the time"%int(100.0*calcount/rescount)
    res.printResults(footer = footer)

    # Plot!
    plotResults(recipe)

    return
예제 #5
0
파일: pdffit.py 프로젝트: ml-evs/matador
    def regression(self, fit, title):
        """ Apply least squares to the free parameters. """
        print('Fitting PDF of', title, 'to expt. data.')
        fit.fithooks[0].verbose = 0

        # We can now execute the fit using scipy's least square optimizer.
        # free parameters one-by-one and fit
        self.plot_fit(fit, title, num=0)
        print(title, '[1/3]')
        fit.free("scale")
        leastsq(fit.residual, fit.values)
        self.plot_fit(fit, title, num=1)
        print(title, '[2/3]')
        fit.free("delta2")
        leastsq(fit.residual, fit.values)
        self.plot_fit(fit, title, num=2)
        print(title, '[3/3]')
        fit.free("all")
        leastsq(fit.residual, fit.values)
        self.plot_fit(fit, title, num=3)
        print(title, 'Done!')

        ContributionResult = FitResults(fit)
        ContributionResult.saveResults(title + '.results')

        return
예제 #6
0
파일: model.py 프로젝트: st3107/pdffitx
 def __init__(self, recipe: md.MyRecipe):
     self._recipe = recipe
     self._contribution = next(iter(recipe.contributions.values()))
     self._fit_result = FitResults(self._recipe, update=False)
     self._verbose: int = 1
     self._order: tp.List[tp.Union[str, tp.Iterable[str]]] = []
     self._options: dict = {}
     self._fit_state = None
예제 #7
0
def main():
    """Set up and refine the recipe."""

    # Make the data and the recipe
    cdsciffile = "data/CdS.cif"
    znsciffile = "data/ZnS.cif"
    data = "data/CdS_ZnS_nano.gr"

    # Make the recipe
    stru1 = loadCrystal(cdsciffile)
    stru2 = loadCrystal(znsciffile)
    recipe = makeRecipe(stru1, stru2, data)
    from diffpy.srfit.fitbase.fithook import PlotFitHook
    recipe.pushFitHook(PlotFitHook())
    recipe.fithooks[0].verbose = 3

    # Optimize - we do this in steps to help convergence
    recipe.fix("all")

    # Start with the lattice parameters. In makeRecipe, these were tagged with
    # "lat". Here is how we use that.
    recipe.free("lat")
    leastsq(recipe.residual, recipe.values, maxfev = 50)

    # Now the scale and phase fraction.
    recipe.free("scale", "scale_CdS")
    leastsq(recipe.residual, recipe.values, maxfev = 50)

    # The ADPs.
    recipe.free("adp")
    leastsq(recipe.residual, recipe.values, maxfev = 100)

    # The delta2 parameters.
    recipe.free("delta2_cds", "delta2_zns")
    leastsq(recipe.residual, recipe.values, maxfev = 50)

    # The shape parameters.
    recipe.free("radius", "thickness")
    leastsq(recipe.residual, recipe.values, maxfev = 50)

    # The positional parameters.
    recipe.free("xyz")
    leastsq(recipe.residual, recipe.values)

    # Generate and print the FitResults
    res = FitResults(recipe)
    res.printResults()

    # Plot!
    plotResults(recipe)
    return
예제 #8
0
def main():
    """Set up and refine the recipe."""

    # Make the data and the recipe
    cdsciffile = "data/CdS.cif"
    znsciffile = "data/ZnS.cif"
    data = "data/CdS_ZnS_nano.gr"

    # Make the recipe
    stru1 = CreateCrystalFromCIF(file(cdsciffile))
    stru2 = CreateCrystalFromCIF(file(znsciffile))
    recipe = makeRecipe(stru1, stru2, data)
    from diffpy.srfit.fitbase.fithook import PlotFitHook
    recipe.pushFitHook(PlotFitHook())
    recipe.fithooks[0].verbose = 3

    # Optimize - we do this in steps to help convergence
    recipe.fix("all")

    # Start with the lattice parameters. In makeRecipe, these were tagged with
    # "lat". Here is how we use that.
    recipe.free("lat")
    leastsq(recipe.residual, recipe.values, maxfev=50)

    # Now the scale and phase fraction.
    recipe.free("scale", "scale_CdS")
    leastsq(recipe.residual, recipe.values, maxfev=50)

    # The ADPs.
    recipe.free("adp")
    leastsq(recipe.residual, recipe.values, maxfev=100)

    # The delta2 parameters.
    recipe.free("delta2_cds", "delta2_zns")
    leastsq(recipe.residual, recipe.values, maxfev=50)

    # The shape parameters.
    recipe.free("radius", "thickness")
    leastsq(recipe.residual, recipe.values, maxfev=50)

    # The positional parameters.
    recipe.free("xyz")
    leastsq(recipe.residual, recipe.values)

    # Generate and print the FitResults
    res = FitResults(recipe)
    res.printResults()

    # Plot!
    plotResults(recipe)
    return
예제 #9
0
def gaussianfit(x, y, dy=None, A=1.0, sig=1.0, x0=0.0):
#def gaussianfit(arg):
    '''main function to fit and plot gaussian curve
        x, y, dy:   gaussian date to be fitted 
        A, sig, x0: initial value
    '''
    #print type(arg)
    dy = np.ones_like(x) if dy==None else dy
    
    recipe = makeRecipe(x, y, dy, A, sig, x0)
    scipyOptimize(recipe)
    res = FitResults(recipe)
    res.printResults()
    plotResults(recipe)
    return 
예제 #10
0
파일: main.py 프로젝트: xpdAcq/pdffitx
def report(recipe: MyRecipe) -> FitResults:
    """Print out the fitting result.

    Parameters
    ----------
    recipe : MyRecipe
        The recipe after refinement.

    Returns
    -------
    res : FitResults
        The object contains the fit results.
    """
    res = FitResults(recipe)
    res.printResults()
    return res
예제 #11
0
def main():

    # Create the recipe
    recipe = makeRecipeII()

    # Refine using the optimizer of your choice
    scipyOptimize(recipe)

    # Get the results in a FitResults object.
    res = FitResults(recipe)

    # Print the results
    res.printResults()

    # Plot the results
    plotResults(recipe)

    return
예제 #12
0
def main():

    # Create the recipe
    recipe = makeRecipeII()

    # Refine using the optimizer of your choice
    scipyOptimize(recipe)

    # Get the results in a FitResults object.
    res = FitResults(recipe)

    # Print the results
    res.printResults()

    # Plot the results
    plotResults(recipe)

    return
예제 #13
0
 def refine(self):
     '''Optimize the recipe created above using scipy.
     '''
     from scipy.optimize.minpack import leastsq
     leastsq(self.recipe.residual, self.recipe.values)
     self.results = FitResults(self.recipe)
     print("Fit results:\n")
     print(self.results)
     return
예제 #14
0
def main():

    p = Profile()
    p.loadtxt("data/gaussian.dat")

    # FitContribution operations
    # "|="  -   Union of necessary components.
    # "<<"  -   Inject a parameter value
    c = FitContribution("g1")
    c |= p
    c |= "A * exp(-0.5*(x-x0)**2/sigma**2)"
    c.A << 0.5
    c.x0 << 5
    c.sigma << 1

    # FitRecipe operations
    # "|="  -   Union of necessary components.
    # "+="  -   Add Parameter or create a new one. Each tuple is a set of
    #           arguments for either setVar or addVar.
    # "*="  -   Constrain a parameter. Think of "*" as a push-pin holding one
    #           parameter's value to that of another.
    # "%="  -   Restrain a parameter or equation. Think of "%" as a rope
    #           loosely tying parameters to a value.
    r = FitRecipe()
    r |= c
    r += (c.A, 0.5), (c.x0, 5), "sig"
    r *= c.sigma, "sig"
    r %= c.A, 0.5, 0.5

    from gaussianrecipe import scipyOptimize

    scipyOptimize(r)

    res = FitResults(r)

    # Print the results.
    res.printResults()

    # Plot the results.
    from gaussianrecipe import plotResults

    plotResults(r)

    return
예제 #15
0
def main():
    """The workflow of creating, running and inspecting a fit."""

    # Create the recipe
    recipe = makeRecipe()

    # Refine using the optimizer of your choice
    scipyOptimize(recipe)

    # Get the results.
    res = FitResults(recipe)

    # Print the results
    res.printResults()

    # Plot the results
    plotResults(recipe)

    return
예제 #16
0
def main():
    """The workflow of creating, running and inspecting a fit."""

    # Create the recipe
    recipe = makeRecipe()

    # Refine using the optimizer of your choice
    scipyOptimize(recipe)

    # Get the results.
    res = FitResults(recipe)

    # Print the results
    res.printResults()

    # Plot the results
    plotResults(recipe)

    return
예제 #17
0
def main():

    p = Profile()
    p.loadtxt("data/gaussian.dat")

    # FitContribution operations
    # "|="  -   Union of necessary components.
    # "<<"  -   Inject a parameter value
    c = FitContribution("g1")
    c |= p
    c |= "A * exp(-0.5*(x-x0)**2/sigma**2)"
    c.A << 0.5
    c.x0 << 5
    c.sigma << 1

    # FitRecipe operations
    # "|="  -   Union of necessary components.
    # "+="  -   Add Parameter or create a new one. Each tuple is a set of
    #           arguments for either setVar or addVar.
    # "*="  -   Constrain a parameter. Think of "*" as a push-pin holding one
    #           parameter's value to that of another.
    # "%="  -   Restrain a parameter or equation. Think of "%" as a rope
    #           loosely tying parameters to a value.
    r = FitRecipe()
    r |= c
    r += (c.A, 0.5), (c.x0, 5), 'sig'
    r *= c.sigma, 'sig'
    r %= c.A, 0.5, 0.5

    from gaussianrecipe import scipyOptimize
    scipyOptimize(r)

    res = FitResults(r)

    # Print the results.
    res.printResults()

    # Plot the results.
    from gaussianrecipe import plotResults
    plotResults(r)

    return
예제 #18
0
def main():

    molecule = makeC60()
    # Make the data and the recipe
    recipe = makeRecipe(molecule, "data/C60.gr")
    # Tell the fithook that we want very verbose output.
    recipe.fithooks[0].verbose = 3

    # Optimize
    from scipy.optimize import leastsq
    leastsq(recipe.residual, recipe.getValues())

    # Print results
    res = FitResults(recipe)
    res.printResults()

    # Plot results
    plotResults(recipe)

    return
예제 #19
0
def main():

    # Make two different data sets, each from the same structure, but with
    # different scale, noise, broadening and background.
    strufile = "data/C60.stru"
    q = numpy.arange(1, 20, 0.05)
    makeData(strufile, q, "C60_1.iq", 8.1, 101.68, 0.008, 0.12, 2, 0.01)
    makeData(strufile, q, "C60_2.iq", 3.2, 101.68, 0.02, 0.003, 0, 1)

    # Make the recipe
    recipe = makeRecipe(strufile, "C60_1.iq", "C60_2.iq")

    # Optimize
    # Since the backgrounds have a large effect on the profile, we will refine
    # them first, but do so separately.
    # To refine the background from the first contribution, we will fix
    # all other parameters and give the second contribution no weight in the
    # fit.
    recipe.fix("all")
    recipe.free("bcoeffs1")
    recipe.setWeight(recipe.bucky2, 0)
    scipyOptimize(recipe)
    # Now do the same for the second background
    recipe.fix("all")
    recipe.free("bcoeffs1")
    recipe.setWeight(recipe.bucky2, 1)
    recipe.setWeight(recipe.bucky1, 0)
    scipyOptimize(recipe)
    # Now refine everything with the structure parameters included
    recipe.free("all")
    recipe.setWeight(recipe.bucky1, 1)
    scipyOptimize(recipe)

    # Generate and print the FitResults
    res = FitResults(recipe)
    res.printResults()

    # Plot!
    plotResults(recipe)

    return
예제 #20
0
def main():

    # Make two different data sets, each from the same structure, but with
    # different scale, noise, broadening and background.
    strufile = "data/C60.stru"
    q = numpy.arange(1, 20, 0.05)
    makeData(strufile, q, "C60_1.iq", 8.1, 101.68, 0.008, 0.12, 2, 0.01)
    makeData(strufile, q, "C60_2.iq", 3.2, 101.68, 0.02, 0.003, 0, 1)

    # Make the recipe
    recipe = makeRecipe(strufile, "C60_1.iq", "C60_2.iq")

    # Optimize
    # Since the backgrounds have a large effect on the profile, we will refine
    # them first, but do so separately.
    # To refine the background from the first contribution, we will fix
    # all other parameters and give the second contribution no weight in the
    # fit.
    recipe.fix("all")
    recipe.free("bcoeffs1")
    recipe.setWeight(recipe.bucky2, 0)
    scipyOptimize(recipe)
    # Now do the same for the second background
    recipe.fix("all")
    recipe.free("bcoeffs1")
    recipe.setWeight(recipe.bucky2, 1)
    recipe.setWeight(recipe.bucky1, 0)
    scipyOptimize(recipe)
    # Now refine everything with the structure parameters included
    recipe.free("all")
    recipe.setWeight(recipe.bucky1, 1)
    scipyOptimize(recipe)

    # Generate and print the FitResults
    res = FitResults(recipe)
    res.printResults()

    # Plot!
    plotResults(recipe)

    return
예제 #21
0
def _make_df(recipe: MyRecipe) -> Tuple[pd.DataFrame, FitResults]:
    """

    :param recipe: fit recipe.
    :return:
    """
    df = pd.DataFrame()
    res = FitResults(recipe)
    df["name"] = ["Rw", "half_chi2"] + res.varnames
    df["val"] = [res.rw, res.chi2 / 2] + res.varvals.tolist()
    df["std"] = [np.nan, np.nan] + res.varunc
    df = df.set_index("name")
    return df, res
예제 #22
0
def _make_df(recipe: MyRecipe) -> pd.DataFrame:
    """
    get Rw and fitting parameter values from recipe and make them a pandas dataframe
    :param recipe: fit recipe.
    :return:
    """
    df = pd.DataFrame()
    res = recipe.res = FitResults(recipe)
    df["name"] = ["Rw", "half_chi2"] + res.varnames
    df["val"] = [res.rw, res.chi2 / 2] + res.varvals.tolist()
    df["std"] = [0, 0] + res.varunc
    df = df.set_index("name")
    return df
예제 #23
0
def main():
    """The workflow of creating, running and inspecting a fit."""

    # Start by creating the recipe. The recipe describes the data to be fit,
    # the profile generator used to simulate the data and the variables that
    # will be tuned by the optimizer.
    recipe = makeRecipe()

    # Refine using the optimizer of your choice.
    scipyOptimize(recipe)

    # Get the results in a FitResults object. The FitResults object stores the
    # current state of the recipe, and uses it to calculate useful statistics
    # about the fit.
    res = FitResults(recipe)

    # Print the results.
    res.printResults()

    # Plot the results.
    plotResults(recipe)

    return
예제 #24
0
def main():
    """The workflow of creating, running and inspecting a fit."""

    # Start by creating the recipe. The recipe describes the data to be fit,
    # the profile generator used to simulate the data and the variables that
    # will be tuned by the optimizer.
    recipe = makeRecipe()

    # Refine using the optimizer of your choice.
    scipyOptimize(recipe)

    # Get the results in a FitResults object. The FitResults object stores the
    # current state of the recipe, and uses it to calculate useful statistics
    # about the fit.  
    res = FitResults(recipe)

    # Print the results.
    res.printResults()

    # Plot the results.
    plotResults(recipe)

    return
예제 #25
0
파일: exporter.py 프로젝트: xpdAcq/pdffitx
def save_res(recipe: FitRecipe, base_name: str, folder: str) -> Path:
    """Save the fitting results.

    Parameters
    ----------
    recipe : FitRecipe
        The refined recipe.

    base_name : str
        The base name of the result file. The file name will be "{base_name}.res".

    folder : str
        The folder to save the fitting result file.

    Returns
    -------
    res_file : Path
        The path to the fitting result file.
    """
    res_file = Path(folder) / "{}.res".format(base_name)
    res = FitResults(recipe)
    res.saveResults(str(res_file))
    return res_file
예제 #26
0
def main():

    # Make the data and the recipe
    data = "../data/MEF_300-00000.gr"
    basename = "MEF_300K_LS"
    print basename

    # Make the recipe
    from diffpy.Structure import Structure
    stru1 = Structure(filename='../data/MEF.cif')
    stru2 = Structure(filename='../data/MEF.xyz')
    stru3 = Structure(filename='../data/MEF.xyz')
    recipe = makeRecipe(stru1, stru2, stru3, data)
    if _plot:
        from diffpy.srfit.fitbase.fithook import PlotFitHook
        recipe.pushFitHook(PlotFitHook())
    recipe.fithooks[0].verbose = 3

    from scipy.optimize import leastsq
    leastsq(recipe.residual, recipe.values)

    # Save structures
    stru1.write(basename + "_Cryst_B_zoomed.stru", "pdffit")
    stru2.write(basename + "_Mole_B_zoomed.xyz", "xyz")
    stru2.write(basename + "_Intra_zoomed.xyz", "xyz")

    profile = recipe.MEF.profile
    
    #import IPython.Shell; IPython.Shell.IPShellEmbed(argv=[])()
    profile.savetxt(basename + ".fit")

    # Generate and print the FitResults
    res = FitResults(recipe)
    res.printResults()

    header = "MEF Organic PDF fit.\n"
    res.saveResults(basename + ".res", header=header)
    
    # Plot!
    if _plot:
        plotResults(recipe)
예제 #27
0
def main():

    # Make the data and the recipe
    data = "../data/ON_RT_5-00000.gr"
    basename = "ROY_Least_Squares"
    print basename

    # Make the recipe
    from diffpy.Structure import Structure
    stru1 = Structure(filename='../data/QAXMEH_ON.cif')
    stru2 = Structure(filename='../data/QAXMEH_ON.xyz'
                      )  # this is non-distorted structure, keep it fixed.
    stru3 = Structure(filename='../data/QAXMEH_ON.xyz')

    recipe = makeRecipe(stru1, stru2, stru3, data)
    if _plot:
        from diffpy.srfit.fitbase.fithook import PlotFitHook
        recipe.pushFitHook(PlotFitHook())
    recipe.fithooks[0].verbose = 3

    from scipy.optimize import leastsq
    leastsq(recipe.residual, recipe.values)

    # Save structures
    stru1.write(basename + "_Cryst_B_zoomed.stru", "pdffit")
    stru2.write(basename + "_Mole_B_zoomed.xyz", "xyz")
    stru2.write(basename + "_Intra_zoomed.xyz", "xyz")

    profile = recipe.ROY.profile
    profile.savetxt(basename + ".fit")

    res = FitResults(recipe)
    res.printResults()

    header = "A+B-C.\n"
    res.saveResults(basename + ".res", header=header)

    # Plot!
    if _plot:
        plotResults(recipe, basename)
예제 #28
0
def main():
    """
    This will run by default when the file is executed using
    "python file.py" in the command line

    Parameters
    ----------
    None

    Returns
    ----------
    None
    """

    # Make some folders to store our output files.
    resdir = Path("res")
    fitdir = Path("fit")
    figdir = Path("fig")

    folders = [resdir, fitdir, figdir]

    # Loop over all folders
    for folder in folders:

        # If the folder does not exist...
        if not folder.exists():
            # ...then we create it.
            folder.mkdir()

    # Let the user know what fit we are running by printing to terminal.
    basename = FIT_ID
    print(f"\n{basename}\n")

    # Establish the full location of the data.
    data = DPATH / GR_NAME

    # Establish the location of the cif file with the structure of interest
    # and load it into a diffpy structure object.
    strudir = DPATH
    cif_file = strudir / CIF_NAME

    # Initialize the Fit Recipe by giving it this diffpy structure
    # as well as the path to the data file.

    p_cif = getParser('cif')
    structure = p_cif.parseFile(str(cif_file))
    space_group = p_cif.spacegroup.short_name

    # Initialize the Fit Recipe by giving it this diffpy structure
    # as well as the path to the data file.
    recipe = makerecipe(cif_file, data)

    # Let's set the calculation range!
    recipe.crystal.profile.setCalculationRange(xmin=PDF_RMIN,
                                               xmax=PDF_RMAX,
                                               dx=PDF_RSTEP)

    # Add, initialize, and tag variables in the Fit Recipe object.
    # In this case we also add psize, which is the NP size.
    recipe.addVar(recipe.crystal.s1, SCALE_I, tag="scale")

    # Set an equation, based on your PDF generators. Here we add an extra layer
    # of complexity, incorporating "f" int our equation. This new term
    # incorporates damping to our PDF to model the effect of finite crystallite size.
    # In this case we use a function which models a spherical NP.
    from diffpy.srfit.pdf.characteristicfunctions import sphericalCF
    recipe.crystal.registerFunction(sphericalCF, name="f")
    recipe.crystal.setEquation("s1*G1*f")

    recipe.addVar(recipe.crystal.psize, PSIZE_I, tag="psize")

    # Initialize the instrument parameters, Q_damp and Q_broad, and
    # assign Q_max and Q_min.
    # Note, here we do not add the qdamp and qbroad parameters to the fit!!!
    # They are fixed here, because we refined them in the Ni standard fit!
    recipe.crystal.G1.qdamp.value = QDAMP_I
    recipe.crystal.G1.qbroad.value = QBROAD_I
    recipe.crystal.G1.setQmax(QMAX)
    recipe.crystal.G1.setQmin(QMIN)

    # Use the srfit function constrainAsSpaceGroup to constrain
    # the lattice and ADP parameters according to the Fm-3m space group.
    from diffpy.srfit.structure import constrainAsSpaceGroup
    spacegroupparams = constrainAsSpaceGroup(recipe.crystal.G1.phase,
                                             space_group)

    # Add and initialize delta, the lattice parameter, and a thermal parameter,
    # but not instrumental parameters to Fit Recipe.
    # The instrumental parameters will remain fixed at values obtained from
    # the Ni calibrant in our previous example. As we have not added them through
    # recipe.addVar, they cannot be refined.
    for par in spacegroupparams.latpars:
        recipe.addVar(par, value=CUBICLAT_I, name="fcc_Lat", tag="lat")

    for par in spacegroupparams.adppars:
        recipe.addVar(par, value=UISO_I, name="fcc_ADP", tag="adp")

    recipe.addVar(recipe.crystal.G1.delta2,
                  name="Pt_Delta2",
                  value=DELTA2_I,
                  tag="d2")

    # Tell the Fit Recipe we want to write the maximum amount of
    # information to the terminal during fitting.
    recipe.fithooks[0].verbose = 0

    refine_params = ["scale", "lat", "psize", "adp", "d2", "all"]

    recipe.fix("all")

    for params in refine_params:
        recipe.free(params)
        print(f"\n****\nFitting {recipe.getNames()} against "
              f"{GR_NAME} with {CIF_NAME}\n")
        least_squares(recipe.residual, recipe.values, x_scale="jac")

    # We use the savetxt method of the profile to write a text file
    # containing the measured and fitted PDF to disk.
    # The file is named based on the basename we created earlier, and
    # written to the fitdir directory.
    profile = recipe.crystal.profile
    profile.savetxt(fitdir / (basename + ".fit"))

    # We use the FitResults function to parse out the results from
    # the optimized Fit Recipe.
    res = FitResults(recipe)

    # We print these results to the terminal.
    res.printResults()

    # We grab the fit Rw
    rw = res.rw

    # We use the saveResults method of FitResults to write a text file
    # containing the fitted parameters and fit quality indices to disk.
    # The file is named based on the basename we created earlier, and
    # written to the resdir directory.
    header = "crystal_HF.\n"
    res.saveResults(resdir / (basename + ".res"), header=header)

    # We use the plotresults function we created earlier to make a plot of
    # the measured, calculated, and difference curves. We show this
    # as an interactive window and then write a pdf file to disk.
    # The file is named based on the basename we created earlier, and
    # written to the figdir directory.
    plotresults(recipe, figdir / basename)

    # Let make a dictionary to hold our results. This way make reloading the
    # fit parameters easier later
    refined_dict = dict()

    refined_dict['rw'] = rw.item()

    # We loop over the variable names, the variable values, and the variable uncertainties (esd)
    for name, val, unc in zip(res.varnames, res.varvals, res.varunc):
        # We store the refined value for this variable using the "value" key.
        # We use the ".item()" method because "res.varvals" exist as
        # numpy.float64 objects, and we want them as regular python floats.
        if name not in refined_dict:
            refined_dict[name] = dict()
        refined_dict[name]["value"] = val.item()
        refined_dict[name]["uncert"] = unc.item()

    with open(basename + ".yml", 'w') as outfile:
        yaml.safe_dump(refined_dict, outfile)
예제 #29
0
def default_refine(gr_file: str,
                   res_dir: str,
                   stru_file: str = None) -> Tuple[float, str, str]:
    """
    Refine the G(r) using a default recipe for Ni.
    Parameters
    ----------
    gr_file
        Path to the gr file.
    res_dir
        Directory to save csv and fgr file.
    stru_file
        User defined structure file. If None, the default file will be used:
        "/Users/sst/project/cal_and_int/Ni.cif"
    Returns
    -------
    rw
        Rw value.
    csv_file
        Path to fitting parameters csv file.
    fgr_file
        Path to fitted data fgr file.
    """
    file_name_base = os.path.splitext(os.path.basename(gr_file))[0]
    print(f"Refine {file_name_base}, please wait ...")

    default_stru_file = "/Users/sst/project/Myscripts/tests/Ni.cif"
    stru_file = stru_file if stru_file else default_stru_file
    ni = GenConfig("Ni", stru_file, ncpu=4)
    config_ni = ConConfig(name="one_phase",
                          data_id=0,
                          data_file=gr_file,
                          fit_range=(1., 60., .01),
                          eq="Ni",
                          phases=ni,
                          qparams=(0.04, 0.02))
    recipe = make(config_ni)

    con: FitContribution = recipe.one_phase
    gen: PDFGenerator = con.Ni

    recipe.addVar(gen.scale, value=0.4)
    recipe.addVar(gen.delta2, value=2.0)
    recipe.addVar(gen.qdamp)
    recipe.addVar(gen.qbroad)
    sgpars = constrainAsSpaceGroup(gen.phase, 225)
    for par in sgpars.latpars:
        recipe.addVar(par, tag="lat")
    for par in sgpars.adppars:
        recipe.addVar(par, tag="adp", value=0.006)

    recipe.fix("all")
    recipe.free("scale")
    fit(recipe, verbose=0)
    recipe.free("lat")
    fit(recipe, verbose=0)
    recipe.free("adp")
    fit(recipe, verbose=0)
    recipe.free("delta2")
    fit(recipe, verbose=0)
    recipe.free("qdamp", "qbroad")
    fit(recipe, verbose=0)

    rw = float(FitResults(recipe).rw)
    base_name = os.path.join(res_dir, file_name_base)
    csv_file, fgr_file = old_save(recipe, "one_phase", base_name)

    plot(recipe)
    plt.title(f"Ni fitting (Rw = {rw:.3f})")
    plt.show()

    return rw, csv_file, fgr_file
    pylab.plot(nr,ndiff,'g-',label="G(r) neutron diff")
    pylab.plot(nr,ndiffzero,'k-')
    pylab.xlabel("$r (\AA)$")
    pylab.ylabel("$G (\AA^{-2})$")
    pylab.legend(loc=1)

    pylab.show()
    return

if __name__ == "__main__":

    # Make the data and the recipe
    ciffile = "data/ni.cif"
    xdata = "data/ni-q27r60nodg-xray.gr"
    ndata = "data/ni-q27r100-neutron.gr"

    # Make the recipe
    recipe = makeRecipe(ciffile, xdata, ndata)

    # Optimize
    scipyOptimize(recipe)

    # Generate and print the FitResults
    res = FitResults(recipe)
    res.printResults()

    # Plot!
    plotResults(recipe)

# End of file
예제 #31
0
def main():
    """
    This will run by default when the file is executed using
    "python file.py" in the command line

    Parameters
    ----------
    None

    Returns
    ----------
    None
    """

    # Make some folders to store our output files.
    resdir = Path("res")
    fitdir = Path("fit")
    figdir = Path("fig")

    folders = [resdir, fitdir, figdir]

    # Loop over all folders
    for folder in folders:

        # If the folder does not exist...
        if not folder.exists():
            # ...then we create it.
            folder.mkdir()

    # Let the user know what fit we are running by printing to terminal.
    basename = FIT_ID
    print(f"\n{basename}\n")

    # Establish the full location of the two datasets.
    xray_data = DPATH / XRAY_GR_NAME
    nuetron_data = DPATH / NEUTRON_GR_NAME

    # Establish the location of the cif file with the structure of interest
    # and load it into a diffpy structure object.
    strudir = DPATH
    cif_file = strudir / CIF_NAME

    p_cif = getParser('cif')
    structure = p_cif.parseFile(str(cif_file))
    space_group = p_cif.spacegroup.short_name

    # Initialize the Fit Recipe by giving it this diffpy structure
    # as well as the path to the data file.
    # Here we use a new function, which takes both datasets.
    recipe = makerecipe_coref(cif_file, xray_data, nuetron_data)

    # We first want to add two scale parameters to our fit recipe,
    # one for each dataset.
    recipe.addVar(recipe.xray.s1, XRAY_SCALE_I, tag="scale")
    recipe.addVar(recipe.neutron.s2, NEUTRON_SCALE_I, tag="scale")

    # Let's set the calculation range!
    # Here we use a loop to make it easier to edit both ranges.
    for cont in recipe._contributions.values():
        cont.profile.setCalculationRange(xmin=PDF_RMIN, xmax=PDF_RMAX, dx=PDF_RSTEP)


    # assign Q_max and Q_min, all part of the PDF Generator object.
    # It's possible that the PDFParse function we used above
    # already parsed out ths information, but in case it didn't, we set it
    # explicitly again here.
    # We do it for both neutron and PDF configurations
    recipe.xray.xray_G.setQmax(XRAY_QMAX)
    recipe.xray.xray_G.setQmin(XRAY_QMIN)
    recipe.neutron.neutron_G.setQmax(NEUTRON_QMAX)
    recipe.neutron.neutron_G.setQmin(NEUTRON_QMAX)

    # Initialize and add the instrument parameters, Q_damp and Q_broad, and
    # delta and instrumental parameters to Fit Recipe.
    # We give them unique names, and tag them with our choice of relevant strings.
    # Again, two datasets means we need to do this for each.
    recipe.addVar(recipe.xray.xray_G.delta2,
                  name="Ni_Delta2",
                  value=DELTA2_I,
                  tag="d2")

    recipe.constrain(recipe.neutron.neutron_G.delta2,
                  "Ni_Delta2")

    recipe.addVar(recipe.xray.xray_G.qdamp,
                  name="xray_Calib_Qdamp",
                  value=XRAY_QDAMP_I,
                  tag="inst")

    recipe.addVar(recipe.xray.xray_G.qbroad,
                  name="xray_Calib_Qbroad",
                  value=XRAY_QBROAD_I,
                  tag="inst")

    recipe.addVar(recipe.neutron.neutron_G.qdamp,
                  name="neutron_Calib_Qdamp",
                  value=NEUTRON_QDAMP_I,
                  tag="inst")

    recipe.addVar(recipe.neutron.neutron_G.qbroad,
                  name="neutron_Calib_Qbroad",
                  value=NEUTRON_QBROAD_I,
                  tag="inst")

    # Configure some additional fit variables pertaining to symmetry.
    # We can use the srfit function constrainAsSpaceGroup to constrain
    # the lattice and ADP parameters according to the Fm-3m space group.
    # First we establish the relevant parameters, then we cycle through
    # the parameters and activate and tag them.
    # We must explicitly set the ADP parameters, because in this case, the
    # CIF had no ADP data.
    from diffpy.srfit.structure import constrainAsSpaceGroup

    # Create the symmetry distinct parameter sets, and constrain them
    # in the generator.
    neutron_spacegroupparams = constrainAsSpaceGroup(recipe.neutron.neutron_G.phase,
                                                     space_group)
    xray_spacegroupparams = constrainAsSpaceGroup(recipe.xray.xray_G.phase,
                                                  space_group)

    # Loop over all the symmetry distinct lattice parameters and add
    # them to the recipe.
    # We give them unique names, and tag them with our choice of a relevant string.
    for xray_par, neutron_par in zip(xray_spacegroupparams.latpars, neutron_spacegroupparams.latpars):
        recipe.addVar(xray_par,
                      value=CUBICLAT_I,
                      name="fcc_Lat",
                      tag="lat")
        recipe.constrain(neutron_par,
                         "fcc_Lat")

    # Loop over all the symmetry distinct ADPs and add
    # them to the recipe.
    # We give them unique names, and tag them with our choice of a relevant string.
    for xray_par, neutron_par in zip(xray_spacegroupparams.adppars, neutron_spacegroupparams.adppars):
        recipe.addVar(xray_par,
                      value=UISO_I,
                      name="fcc_ADP",
                      tag="adp")
        recipe.constrain(neutron_par,
                         "fcc_ADP")

    # Tell the Fit Recipe we want to write the maximum amount of
    # information to the terminal during fitting.
    recipe.fithooks[0].verbose = 3

    # During the optimization, we fix and free parameters sequentially
    # as you would in PDFgui. This leads to more stability in the refinement.
    # We first fix all variables. "all" is a tag which incorporates
    # every parameter.
    recipe.fix("all")

    # Here will will set the weight of each contribution. In this case, we give each equal weight
    conts = list(recipe._contributions.values())

    for cont in conts:
        recipe.setWeight(cont, 1.0/len(conts))

    # We then run a fit using the SciPy function "least_squares" which
    # takes as its arguments the function to be optimized, here recipe.residual,
    # as well as initial values for the fitted parameters, provided by
    # recipe.values. The x_scale="jac" argument is an optional argument
    # that provides for a bit more stability in the refinement.
    # "least_squares" is a bit more robust than "leastsq,"
    # which is another optimization function provided by SciPy.
    # "least_squares" supports bounds on refined parameters,
    #  while "leastsq" does not.

    refine_params = ["scale", "lat", "adp", "d2", "all"]

    for params in refine_params:
        recipe.free(params)
        print(f"\n****\nFitting {recipe.getNames()} against "
              f"{XRAY_GR_NAME} and {NEUTRON_GR_NAME} with {CIF_NAME}\n")
        least_squares(recipe.residual, recipe.values, x_scale="jac")

    # We use the savetxt method of the profile to write a text file
    # containing the measured and fitted PDF to disk.
    # The file is named based on the basename we created earlier, and
    # written to the fitdir directory.
    profile = recipe.crystal.profile
    profile.savetxt(fitdir / (basename + ".fit"))

    # We use the FitResults function to parse out the results from
    # the optimized Fit Recipe.
    res = FitResults(recipe)

    # We print these results to the terminal.
    res.printResults()

    # We grab the fit Rw
    rw = res.rw

    # We use the saveResults method of FitResults to write a text file
    # containing the fitted parameters and fit quality indices to disk.
    # The file is named based on the basename we created earlier, and
    # written to the resdir directory.
    header = "crystal_HF.\n"
    res.saveResults(resdir / (basename + ".res"), header=header)

    # We use the plotresults function we created earlier to make a plot of
    # the measured, calculated, and difference curves. We show this
    # as an interactive window and then write a pdf file to disk.
    # The file is named based on the basename we created earlier, and
    # written to the figdir directory.
    plotresults(recipe, figdir / basename)

    # Let make a dictionary to hold our results. This way make reloading the
    # fit parameters easier later
    refined_dict = dict()

    refined_dict['rw'] = rw.item()

    recipe.free("all")
    # We loop over the variable names, the variable values, and the variable uncertainties (esd)
    for name, val, unc in zip(res.varnames, res.varvals, res.varunc):
        # We store the refined value for this variable using the "value" key.
        # We use the ".item()" method because "res.varvals" exist as
        # numpy.float64 objects, and we want them as regular python floats.
        if name not in refined_dict:
            refined_dict[name] = dict()
        refined_dict[name]["value"] = val.item()
        refined_dict[name]["uncert"] = unc.item()

    # Finally, let's write our dictionary to a yaml file!
    with open(basename + ".yml", 'w') as outfile:
        yaml.safe_dump(refined_dict, outfile)
예제 #32
0
    pylab.plot(r,diffzero,'k-')
    pylab.xlabel("$r (\AA)$")
    pylab.ylabel("$G (\AA^{-2})$")
    pylab.legend(loc=1)

    pylab.show()
    return


if __name__ == "__main__":

    # Make the data and the recipe
    niciffile = "data/ni.cif"
    siciffile = "data/si.cif"
    data = "data/si90ni10-q27r60-xray.gr"

    # Make the recipe
    recipe = makeRecipe(niciffile, siciffile, data)

    # Optimize
    scipyOptimize(recipe)

    # Generate and print the FitResults
    res = FitResults(recipe)
    res.printResults()

    # Plot!
    plotResults(recipe)

# End of file
예제 #33
0
# We fix Qdamp based on prior information about our beamline.
mnofit.addVar(nucpdf.qdamp, 0.03)

# Turn off printout of iteration number.
mnofit.clearFitHooks()

# Initial structural fit
print("Refine PDF using scipy's least-squares optimizer:")
print("  variables:", mnofit.names)
print("  initial values:", mnofit.values)
leastsq(mnofit.residual, mnofit.values)
print("  final values:", mnofit.values)
print()
# Obtain and display the fit results.
mnoresults = FitResults(mnofit)
print("FIT RESULTS\n")
print(mnoresults)

# Get the experimental data from the recipe
r = mnofit.totpdf.profile.x
gobs = mnofit.totpdf.profile.y

# Get the calculated PDF and compute the difference between the calculated and
# measured PDF
gcalc = mnofit.totpdf.evaluate()
baseline = 1.1 * gobs.min()
gdiff = gobs - gcalc

# Plot the structural refinement
ax = plt.figure().add_subplot(111)
예제 #34
0
# The FitRecipe.scalarResidual function returns the sum of squares and can
# be used with a minimizer that expects scalar function:

from scipy.optimize import fmin
fmin(recipe.scalarResidual, [1, 1])
print(recipe.names, "-->", recipe.values)
plt.plot(profile.x, profile.y, 'x', profile.x, profile.ycalc, '-')
plt.title('Line fit using the fmin scalar optimizer')

# <demo> --- stop ---

# For a converged fit recipe, the details of the fit can be extracted
# with the FitResults class.

from diffpy.srfit.fitbase import FitResults
res = FitResults(recipe)
print(res)

# <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)
# We fix Qdamp based on prior information about our beamline.
MnOFit.addVar(MnOPDF.qdamp, 0.03, fixed=True)

# Turn off printout of iteration number.
MnOFit.clearFitHooks()

# We can now execute the fit using scipy's least square optimizer.
print("Refine PDF using scipy's least-squares optimizer:")
print("  variables:", MnOFit.names)
print("  initial values:", MnOFit.values)
leastsq(MnOFit.residual, MnOFit.values)
print("  final values:", MnOFit.values)
print()

# Obtain and display the fit results.
MnOResults = FitResults(MnOFit)
print("FIT RESULTS\n")
print(MnOResults)

# Get the experimental data from the recipe
r = MnOFit.MnO.profile.x
gobs = MnOFit.MnO.profile.y

# Get the calculated PDF and compute the difference between the calculated and
# measured PDF
gcalc = MnOFit.MnO.evaluate()
baseline = 1.1 * gobs.min()
gdiff = gobs - gcalc
baseline2 = 1.2 * (gdiff + baseline).min()

### NOW DO THE MPDF REFINEMENT USING THE RESIDUAL FROM THE ATOMIC PDF
예제 #36
0
파일: model.py 프로젝트: st3107/pdffitx
class ModelBase:
    """The template for the model class."""

    def __init__(self, recipe: md.MyRecipe):
        self._recipe = recipe
        self._contribution = next(iter(recipe.contributions.values()))
        self._fit_result = FitResults(self._recipe, update=False)
        self._verbose: int = 1
        self._order: tp.List[tp.Union[str, tp.Iterable[str]]] = []
        self._options: dict = {}
        self._fit_state = None

    def parallel(self, ncpu: int) -> None:
        """Parallel computing.

        Parameters
        ----------
        ncpu :
            Number of CPUs.
        """
        fc = self.get_contribution()
        for g in fc.generators.values():
            g.parallel(ncpu)

    def set_xrange(self, start: float = None, end: float = None, step: float = None) -> None:
        """Set fitting range.

        Parameters
        ----------
        start :
            Start of x. x >= start
        end :
            End of x. x <= end
        step :
            Step of x. x[i] - x[i-1] == step

        Returns
        -------
        None
        """
        profile = self.get_profile()
        profile.setCalculationRange(xmin=start, xmax=end, dx=step)

    def set_verbose(self, level: int) -> None:
        """Set verbose level.

        Parameters
        ----------
        level :
            The level used. 0 means quiet.

        Returns
        -------
        None
        """
        self._verbose = level

    def get_verbose(self) -> int:
        """Get verbose level

        Returns
        -------
        Verbose level.
        """
        return self._verbose

    def set_options(self, **kwargs) -> None:
        """Set options for fitting.

        Parameters
        ----------
        kwargs :
            The options for the scipy.optimize.least_squares.

        Returns
        -------
        None
        """
        self._options = kwargs

    def get_options(self) -> dict:
        """Get options for fitting.

        Returns
        -------
        A dictionary of options.
        """
        return self._options

    def set_order(self, *order: tp.Union[str, tp.Iterable[str]]) -> None:
        """Set the order of fitting parameters.

        Parameters
        ----------
        order :
            A list of list or string.

        Returns
        -------
        None

        Examples
        --------
        if order is ["A", ["B", "C"]], "A" will be first refined and "B", "C" will be added after and refined.
        """
        order = list(order)
        self._check_order(order)
        self._order = order

    def _check_order(self, order: tp.Any) -> None:
        """Check the order."""
        tags = set(self._recipe._tagmanager.alltags())
        if isinstance(order, str):
            if not hasattr(self._recipe, order) and order not in tags:
                raise ValueError("'{}' is not in the variable names.".format(order))
        elif isinstance(order, tp.Iterable):
            for x in order:
                self._check_order(x)
        else:
            raise TypeError("'{}' is not allowed.".format(type(order)))

    def get_order(self) -> tp.List[tp.Union[str, tp.Iterable[str]]]:
        """Get the order of the parameters

        Returns
        -------
        A list of parameters.
        """
        return self._order

    def set_value(self, **kwargs) -> None:
        """Set the parameter values.

        Parameters
        ----------
        kwargs :
            In the format of param = value.

        Returns
        -------
        None
        """
        self._check_params(kwargs.keys())
        for name, value in kwargs.items():
            var: Parameter = getattr(self._recipe, name)
            var.setValue(value)

    def get_param(self, name: str) -> Parameter:
        """Get the parameters."""
        if not hasattr(self._recipe, name):
            raise KeyError("No such parameter call '{}' in the recipe.".format(name))
        return getattr(self._recipe, name)

    def set_bound(self, **kwargs) -> None:
        """Set the bound.

        Parameters
        ----------
        kwargs :
            In the form of param = (lb, ub)

        Returns
        -------
        None
        """
        self._check_params(kwargs.keys())
        for name, bound in kwargs.items():
            var: Parameter = getattr(self._recipe, name)
            var.boundRange(*bound)

    def set_rel_bound(self, **kwargs) -> None:
        """Set the bound relatively to current value.

        Parameters
        ----------
        kwargs :
            In the form of param = (lb, ub)

        Returns
        -------
        None
        """
        self._check_params(kwargs.keys())
        for name, bound in kwargs.items():
            var: Parameter = getattr(self._recipe, name)
            var.boundWindow(*bound)

    def _check_params(self, params):
        """Check the parameters."""
        for param in params:
            if not hasattr(self._recipe, param):
                raise KeyError("There is no parameter called '{}'".format(param))

    def _create_recipe(self) -> md.MyRecipe:
        """Place holder for the method to create the recipe."""
        raise NotImplemented

    def get_contribution(self) -> md.MyContribution:
        """Get the first contribution in recipe.

        Returns
        -------
        A FitContribution.
        """
        return self._contribution

    def get_generators(self) -> tp.Dict[str, tp.Callable]:
        """Get the generators in a dictionary."""
        return self.get_contribution().generators

    def calc_phase(self, name: str) -> xr.DataArray:
        """Calculate the data from a generator.

        Parameters
        ----------
        name :
            The name of a generator.

        Returns
        -------
        A xarray.DataArray of calculated y with x as the coordinate.
        """
        gs = self.get_generators()
        p = self.get_profile()
        if name not in gs:
            raise KeyError("There are no generators named '{}'.".format(name))
        y = gs[name](p.x)
        arr = xr.DataArray(y, coords={"x": x}, dims=["x"])
        arr["y"].attrs["standard_name"] = "G"
        arr["y"].attrs["units"] = r"Å$^{-2}$"
        arr["x"].attrs["standard_name"] = "r"
        arr["x"].attrs["units"] = "Å"
        return arr

    def set_profile(self, profile: Profile) -> None:
        """Set the data profile.

        Parameters
        ----------
        profile :
            A data profile.

        Returns
        -------
        None
        """
        fc: md.MyContribution = self.get_contribution()
        fc.setProfile(profile)

    def get_profile(self) -> Profile:
        """Get the data profile."""
        fc = self.get_contribution()
        return fc.profile

    def optimize(self) -> None:
        """Optimize the model. The scipy.optimize.least_squares is used.

        Returns
        -------
        None
        """
        if not self._order:
            raise ValueError("No parameters to refine.")
        md.optimize(self._recipe, self._order, validate=False, verbose=self._verbose, **self._options)
        rw = self.get_rw()
        if self._verbose > 0:
            print("Optimization result: Rw = {:.6f}.".format(rw))

    def get_rw(self) -> float:
        """Calculate Rw value from profile.

        -------
        Rw value.
        """
        profile = self.get_profile()
        y, ycalc = profile.y, profile.ycalc
        return np.sqrt(np.sum((y - ycalc) ** 2) / np.sum(ycalc ** 2))

    def update(self) -> None:
        """Update the result."""
        return self._fit_result.update()

    def show(self) -> None:
        """Show the values of parameters."""
        self._recipe.show()

    def get_result(self) -> dict:
        """Get the result in a dictionary"""
        dct = dict()
        fr = self._fit_result
        n = len(fr.varnames)
        for i in range(n):
            dct[fr.varnames[i]] = fr.varvals[i]
        n = len(fr.fixednames)
        for i in range(n):
            dct[fr.fixednames[i]] = fr.fixedvals[i]
        dct["rw"] = self._fit_result.rw
        return dct

    def save(self, directory: str, file_prefix: str) -> None:
        """Save the model parameters. Must update before save.

        Parameters
        ----------
        directory :
            The directory to export the files.
        file_prefix :
            The prefix of the file name.

        Returns
        -------
        None
        """
        directory = pathlib.Path(directory)
        if not directory.is_dir():
            directory.mkdir(parents=True)
        path = directory.joinpath("{}.txt".format(file_prefix))
        self._fit_result.saveResults(path)

    def load(self, filepath: str) -> None:
        """Load the parameters for the model.

        Parameters
        ----------
        filepath :
            The path to the file or the string of the content or a IOstream.

        Returns
        -------
        None
        """
        initializeRecipe(self._recipe, filepath)

    def export_result(self) -> xr.Dataset:
        """Export the result in a dataset."""
        dct = self.get_result()
        ds = xr.Dataset(dct)
        for name in ds.variables:
            ds[name].attrs["long_name"] = get_symbol(name)
            ds[name].attrs["units"] = get_unit(name)
        ds["rw"].attrs["long_name"] = "$R_w$"
        return ds

    def export_fits(self) -> xr.Dataset:
        """Export the fits in a dataset."""
        profile = self.get_profile()
        ds = xr.Dataset(
            {"y": (["x"], profile.y), "ycalc": (["x"], profile.ycalc), "yobs": (["xobs"], profile.yobs)},
            {"x": (["x"], profile.x), "xobs": (["xobs"], profile.xobs)}
        )
        ds["y"].attrs["standard_name"] = "G"
        ds["y"].attrs["units"] = r"Å$^{-2}$"
        ds["ycalc"].attrs["standard_name"] = "G"
        ds["ycalc"].attrs["units"] = r"Å$^{-2}$"
        ds["yobs"].attrs["standard_name"] = "G"
        ds["yobs"].attrs["units"] = r"Å$^{-2}$"
        ds["x"].attrs["standard_name"] = "r"
        ds["x"].attrs["units"] = "Å"
        ds["xobs"].attrs["standard_name"] = "r"
        ds["xobs"].attrs["units"] = "Å"
        return ds

    def save_result(self, directory: str, file_prefix: str) -> None:
        """Save the fitting result.

        Parameters
        ----------
        directory :
            The directory to export the files.
        file_prefix :
            The prefix of the file name.

        Returns
        -------
        None
        """
        directory = pathlib.Path(directory)
        if not directory.is_dir():
            directory.mkdir(parents=True)
        result = self.export_result()
        path = directory.joinpath("{}_result.nc".format(file_prefix))
        result.to_netcdf(path)

    def save_fits(self, directory: str, file_prefix: str) -> None:
        """Save the fitted curves.

        Parameters
        ----------
        directory :
            The directory to export the files.
        file_prefix :
            The prefix of the file name.

        Returns
        -------
        None
        """
        directory = pathlib.Path(directory)
        if not directory.is_dir():
            directory.mkdir(parents=True)
        fits = self.export_fits()
        path = directory.joinpath("{}_fits.nc".format(file_prefix))
        fits.to_netcdf(path)

    def save_all(self, directory: str, file_prefix: str) -> None:
        """Save the results, fits and structures in a directory.

        Parameters
        ----------
        directory :
            The directory to export the files.
        file_prefix :
            The prefix of the file name.

        Returns
        -------
        None
        """
        self.save(directory, file_prefix)
        self.save_result(directory, file_prefix)
        self.save_fits(directory, file_prefix)

    def plot(self, **kwargs) -> None:
        """View the fitted curves.

        Returns
        -------
        None
        """
        fits = self.export_fits()
        plot_fits(fits, **kwargs)
예제 #37
0
    recipe.addVar(contribution.qdamp, 0.03, fixed=True)
    recipe.addVar(contribution.nickel.delta2, 5)

    # Give the recipe away so it can be used!
    return recipe


if __name__ == "__main__":

    # Make the data and the recipe
    ciffile = "data/ni.cif"
    data = "data/ni-q27r100-neutron.gr"

    # Make the recipe
    recipe = makeRecipe(ciffile, data)

    # Optimize
    scipyOptimize(recipe)
    # Save the file
    recipe.nickel.savetxt("nickel_example.fit")

    # Generate, print and save the FitResults
    res = FitResults(recipe)
    res.printResults()
    res.saveResults("nickel_example.res")

    # Plot!
    plotResults(recipe)

# End of file
예제 #38
0
cdseFit.constrain(lattice.b, zoomscale)
cdseFit.constrain(lattice.c, zoomscale)

# Turn off printout of iteration number.
cdseFit.clearFitHooks()

# We can now execute the fit using scipy's least square optimizer.
print("Refine PDF using scipy's least-squares optimizer:")
print("  variables:", cdseFit.names)
print("  initial values:", cdseFit.values)
leastsq(cdseFit.residual, cdseFit.values)
print("  final values:", cdseFit.values)
print()

# Obtain and display the fit results.
cdseResults = FitResults(cdseFit)
print("FIT RESULTS\n")
print(cdseResults)

# Plot the observed and refined PDF.

# Get the experimental data from the recipe
r = cdseFit.CdSe.profile.x
gobs = cdseFit.CdSe.profile.y

# Get the calculated PDF and compute the difference between the calculated and
# measured PDF
gcalc = cdseFit.CdSe.evaluate()
baseline = 1.1 * gobs.min()
gdiff = gobs - gcalc
예제 #39
0
# We fix Qdamp based on prior information about our beamline.
niFit.addVar(niPDF.qdamp, 0.03, fixed=True)

# Turn off printout of iteration number.
niFit.clearFitHooks()

# We can now execute the fit using scipy's least square optimizer.
print("Refine PDF using scipy's least-squares optimizer:")
print("  variables:", niFit.names)
print("  initial values:", niFit.values)
leastsq(niFit.residual, niFit.values)
print("  final values:", niFit.values)
print()

# Obtain and display the fit results.
niResults = FitResults(niFit)
print("FIT RESULTS\n")
print(niResults)

# Plot the observed and refined PDF.

# Get the experimental data from the recipe
r = niFit.nickel.profile.x
gobs = niFit.nickel.profile.y

# Get the calculated PDF and compute the difference between the calculated and
# measured PDF
gcalc = niFit.nickel.evaluate()
baseline = 1.1 * gobs.min()
gdiff = gobs - gcalc
예제 #40
0
# The FitRecipe.scalarResidual function returns the sum of squares and can
# be used with a minimizer that expects scalar function:

from scipy.optimize import fmin
fmin(rec.scalarResidual, [1, 1])
print(rec.names, "-->", rec.values)
plt.plot(linedata.x, linedata.y, 'x', linedata.x, linedata.ycalc, '-')
plt.title('Line fit using the fmin scalar optimizer')

# <demo> --- stop ---

# For a converged fit recipe, the details of the fit can be extracted
# with the FitResults class.

from diffpy.srfit.fitbase import FitResults
res = FitResults(rec)
print(res)

# <demo> --- stop ---

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

rec.fix(B=0)

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

# The fit can be rerun with a constant variable B.
leastsq(rec.residual, rec.values)
예제 #41
0
    recipe.addVar(contribution.scale, 1)
    recipe.addVar(contribution.qdamp, 0.03, fixed = True)
    recipe.addVar(contribution.nickel.delta2, 5)

    # Give the recipe away so it can be used!
    return recipe

if __name__ == "__main__":

    # Make the data and the recipe
    ciffile = "data/ni.cif"
    data = "data/ni-q27r100-neutron.gr"

    # Make the recipe
    recipe = makeRecipe(ciffile, data)

    # Optimize
    scipyOptimize(recipe)
    # Save the file
    recipe.nickel.savetxt("nickel_example.fit")

    # Generate, print and save the FitResults
    res = FitResults(recipe)
    res.printResults()
    res.saveResults("nickel_example.res")

    # Plot!
    plotResults(recipe)

# End of file