Ejemplo n.º 1
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
Ejemplo n.º 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
Ejemplo n.º 3
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
Ejemplo n.º 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
Ejemplo n.º 5
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
Ejemplo n.º 6
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
Ejemplo n.º 7
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 
Ejemplo n.º 8
0
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
Ejemplo n.º 9
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
Ejemplo n.º 10
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
Ejemplo n.º 11
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
Ejemplo n.º 12
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
Ejemplo n.º 13
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
Ejemplo n.º 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
Ejemplo n.º 15
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
Ejemplo n.º 16
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)
Ejemplo n.º 17
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
Ejemplo n.º 18
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
Ejemplo n.º 19
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)
Ejemplo n.º 20
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
Ejemplo n.º 21
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
Ejemplo n.º 22
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 = "res"
    fitdir = "fit"
    figdir = "fig"

    folders = [resdir, fitdir, figdir]

    # Let's define our working directory.
    base_dir = Path()

    yaml_file = base_dir / (FIT_ID_BASE + "refined_params.yml")

    # This is a bit different than what we've done before.
    # We are going to look at a set of temperatures, so we want
    # to find all the relevant data files in the "DPATH" folder
    # we identified earlier which match a certain pattern.

    # To do this we will use list comprehension

    # For every file we find, we will link it up with the data path
    data_files = list(DPATH.glob(f"*{GR_NAME_BASE}*.gr"))

    # We now want to grab the temperature at which each file was measured.
    # We again use list comprehension, and we re-use the variable "temp"
    # This specific procedure depends on how the file is named.
    # In our case, we carefully named each file as:
    # "composition_TTTK.gr" where TTT is the temperature in Kelvin.

    # First we strip off the directory information for every file in "data_files"
    # This gives us a list of just full file names, without directories.
    temps = [f.stem for f in data_files]

    # Next we split every base filename into a list, delimited by "_"
    # We keep the second entry from this list, because we know it has the
    # temperature in the form TTTK.
    temps = [t.split('_')[1] for t in temps]

    # We want the temperature as an integer, so we need to drop the "K"
    # from each string and cast the values as integers using "int()"
    # Strings can be slides like arrays, so "[:-1]" means "take all the
    # values except the last one."
    temps = [int(t[:-1]) for t in temps]

    # This will sort the data files and temperatures in descending order
    # based on the temperature values.
    temps, data_files = zip(*sorted(zip(temps, data_files), reverse=True))

    # We want to test two structure models, so we should find both the cif files.
    # Similar to how we found the data files, we use list comprehension

    # For every file we find, we will link it up with the data path
    cif_files = list(DPATH.glob(f"*{CIF_NAME_BASE}*.cif"))

    # We initialize and empty dictionary, where we will save all
    # the details of the refined parameters.
    if yaml_file.exists():
        print(f"\n{yaml_file.name} exists, loading!\n")
        with open(yaml_file, 'r') as infile:
            refined_dict = yaml.safe_load(infile)
    else:
        print(f"\n{yaml_file.name} does not exist, creating!\n")
        refined_dict = dict()

    # We want to do a separate temperature series on each of the structures,
    # so we will use a loop on all the cif files we found.
    for cif in cif_files:

        # Let's get the space group, so we can refer to it later.
        p_cif = getParser('cif')
        p_cif.parseFile(str(cif))
        space_group = p_cif.spacegroup.short_name

        # Backslashes are bad form, so let's remove them...
        structure_string = space_group.replace("/", "_on_")

        # Lets check if we already ran this fit...so we dont duplicate work
        if structure_string not in refined_dict:
            print(f"\n{structure_string} IS NOT in dictionary!\n")
            # Nest a dictionary inside "refined_dict" with a key defined by "structure_string"
            refined_dict[structure_string] = dict()

            # This is just for ease of coding/readability
            sg_dict = refined_dict[structure_string]
            done = False
        elif structure_string in refined_dict:
            print(f"\n{structure_string} IS IN dictionary!\n")
            sg_dict = refined_dict[structure_string]
            done = True

        # Where will we work? here!
        work_dir = base_dir / structure_string

        # Make our folders!
        for folder in folders:
            new_folder = work_dir / folder
            if not new_folder.exists():
                new_folder.mkdir(parents=True)

        # Make a recipe based on this cif file, and the first data file in
        # "data_files"
        # We can pass in any data file at this point, this is only to initialize
        # the recipe, and we will replace this data before refining.
        recipe = makerecipe(cif, data_files[0])

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

        # Initialize the instrument parameters, Q_damp and Q_broad, and
        # assign Q_max and Q_min.
        recipe.crystal.G1.qdamp.value = QDAMP_I
        recipe.crystal.G1.qbroad.value = QBROAD_I
        recipe.crystal.G1.setQmax(QMAX)
        recipe.crystal.G1.setQmin(QMIN)

        # Add, initialize, and tag the scale variable.
        recipe.addVar(recipe.crystal.s1, SCALE_I, tag="scale")

        # Use the srfit function constrainAsSpaceGroup to constrain
        # the lattice and ADP parameters according to the space group setting,
        # in this case, contained in the function argument "sg"
        #
        from diffpy.srfit.structure import constrainAsSpaceGroup

        spacegroupparams = constrainAsSpaceGroup(recipe.crystal.G1.phase,
                                                 space_group)

        for par in spacegroupparams.latpars:
            recipe.addVar(par, fixed=False, tag="lat")

        for par in spacegroupparams.adppars:
            recipe.addVar(par, fixed=False, tag="adp")

        # Note: here we also can refine atomic coordinates.
        # In our previous examples, all the atoms were on symmetry
        # operators, so their positions could not be refined.
        for par in spacegroupparams.xyzpars:
            recipe.addVar(par, fixed=False, tag="xyz")

        # Add delta, but not instrumental parameters to Fit Recipe.
        recipe.addVar(recipe.crystal.G1.delta2,
                      name="Delta2",
                      value=DELTA1_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

        # As we are doing a temperature series through a phase transition, we want to fit many
        # different data sets, each at a different temperature.
        # for this we will loop over both "temps" and "data_files"
        for file, temp in zip(data_files, temps):
            print(f"\nProcessing {file.name}!\n")

            if temp not in sg_dict:
                print(
                    f"\nT = {temp} K NOT IN {structure_string} dictionary, creating!\n"
                )
                # Nest a dictionary inside the nested dictionary "refined_dict[stru_type]"
                # with a key defined by "temp"
                sg_dict[temp] = dict()
                temp_dict = sg_dict[temp]
                done = False
            elif temp in sg_dict:
                print(f"\nT = {temp} K IS IN {structure_string} dictionary!\n")
                temp_dict = sg_dict[temp]
                done = True

            # We create a unique string to identify our fit,
            # using the structure type and the temperature.
            # This will be used when we write files later.
            basename = f"{FIT_ID_BASE}{structure_string}_{str(temp)}_K"

            # Print the basename to the terminal.
            print(f"\nWorking on {basename}!\n")

            # We now want to load in the proper dataset for the given temperature.
            # We do this by creating a new profile object and loading it into the fit recipe.
            profile = Profile()
            parser = PDFParser()
            parser.parseFile(file)
            profile.loadParsedData(parser)
            recipe.crystal.setProfile(profile)
            if not done:
                print(
                    f"{basename} is NOT DONE with structure {structure_string} at T = {temp} K\n"
                )

                # We are now ready to start the refinement.
                # During the optimization, fix and free parameters as you would
                # PDFgui. This leads to more stability in the refinement
                recipe.fix("all")

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

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

            elif done:

                print(
                    f"{basename} IS done with structure {structure_string} at T = {temp} K\n"
                )

                recipe.free("all")

                print("\nLoading parameters...\n")
                for var in recipe.getNames():
                    if var not in temp_dict:
                        print(
                            f"{var} is not in the dictionary!! Let's try to fix it..."
                        )
                        recipe.fix("all")
                        recipe.free(var)
                        print(f"\nFitting {recipe.getNames()}\n")
                        least_squares(recipe.residual,
                                      recipe.values,
                                      x_scale="jac")
                        recipe.free("all")
                    elif var in temp_dict:
                        var_dict = temp_dict[var]
                        val = var_dict["value"]
                        recipe.get(var).setValue(val)
                if not SKIP_DONE:
                    print("\nPolishing...\n")
                    recipe.free("all")
                    print(f"\nFitting {recipe.getNames()}\n")
                    least_squares(recipe.residual,
                                  recipe.values,
                                  x_scale="jac")

                    print("\nPolishing done\n")
            if (done and not SKIP_DONE) or not done or REPLOT_DONE:
                print(f"\nStarting to write results for {basename}"
                      f" with structure {structure_string} at T = {temp} K\n")
                # Print the fit results to the terminal.
                res = FitResults(recipe)
                print("\n******************\n")
                res.printResults()
                print("\n******************\n")
                rw = res.rw

                # Write the fitted data to a file.
                profile = recipe.crystal.profile
                profile.savetxt(work_dir / fitdir / (basename + ".fit"))

                # Now, as we will use the optimized fit recipe in the next loop,
                # we want to keep all the refined parameters for this part of the loop
                # we do this by recording everything in the nested dictionaries we made earlier.

                # 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 create a new nested dictionary based on each variable name
                    if name not in temp_dict:
                        temp_dict[name] = dict()
                    var_dict = temp_dict[name]
                    # 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.
                    var_dict["value"] = val.item()
                    var_dict["uncert"] = unc.item()

                # We also store the fit rw, for posterity.
                temp_dict['rw'] = rw.item()

                # Write the fit results to a file.
                header = "crystal_HF.\n"
                res.saveResults(work_dir / resdir / (basename + ".res"),
                                header=header)

                # Write a plot of the fit to a (pdf) file.
                plotresults(recipe, work_dir / figdir / basename)
                # plt.ion()

                # We now write this dictionary to a file for later use.
                with open(yaml_file, 'w') as outfile:
                    yaml.safe_dump(refined_dict, outfile)

    # We now write this dictionary to a file for later use.
    with open(yaml_file, 'w') as outfile:
        yaml.safe_dump(refined_dict, outfile)
Ejemplo n.º 23
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)
Ejemplo n.º 24
0
    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
Ejemplo n.º 25
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)
Ejemplo n.º 26
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