def makeRecipe(ciffile, datname): """Create a fitting recipe for crystalline PDF data.""" # Work directly with a custom PDFContribution to load the data contribution = PDFContribution("nickel") contribution.loadData(datname) contribution.setCalculationRange(xmin = 1, xmax = 20, dx = 0.1) # and the phase stru = Structure() stru.read(ciffile) contribution.addStructure("nickel", stru) ## Make the FitRecipe and add the FitContribution. recipe = FitRecipe() recipe.addContribution(contribution) ## Configure the fit variables phase = contribution.nickel.phase from diffpy.srfit.structure import constrainAsSpaceGroup sgpars = constrainAsSpaceGroup(phase, "Fm-3m") for par in sgpars.latpars: recipe.addVar(par) for par in sgpars.adppars: recipe.addVar(par, 0.005) 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
def makeRecipe(ciffile, datname): """Create a fitting recipe for crystalline PDF data.""" # Work directly with a custom PDFContribution to load the data contribution = PDFContribution("nickel") contribution.loadData(datname) contribution.setCalculationRange(xmin=1, xmax=20, dx=0.1) # and the phase stru = Structure() stru.read(ciffile) contribution.addStructure("nickel", stru) ## Make the FitRecipe and add the FitContribution. recipe = FitRecipe() recipe.addContribution(contribution) ## Configure the fit variables phase = contribution.nickel.phase from diffpy.srfit.structure import constrainAsSpaceGroup sgpars = constrainAsSpaceGroup(phase, "Fm-3m") for par in sgpars.latpars: recipe.addVar(par) for par in sgpars.adppars: recipe.addVar(par, 0.005) 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
# Create and prep the magnetic structure mstr = MagStructure() mstr.loadSpecies(mn2p) mstr.makeAll() # Set up the mPDF calculator mc = MPDFcalculator(magstruc=mstr, gaussPeakWidth=0.2) ### DO THE STRUCTURAL FIT USING SRFIT # Construct the atomic PDF contribution MnOPDF = PDFContribution("MnO") # Load the data and set the r-range over which we'll fit MnOPDF.loadData(dataFile) MnOPDF.setCalculationRange(xmin=0.01, xmax=20, dx=0.01) # Add the structure from our cif file to the contribution MnOPDF.addStructure("MnO", mnostructure) # The FitRecipe does the work of calculating the PDF with the fit variable # that we give it. MnOFit = FitRecipe() # give the PDFContribution to the FitRecipe MnOFit.addContribution(MnOPDF) # Configure the fit variables and give them to the recipe. We can use the # srfit function constrainAsSpaceGroup to constrain the lattice and ADP # parameters according to the H-3m space group.
from diffpy.Structure import loadStructure from diffpy.srfit.pdf import PDFContribution from diffpy.srfit.fitbase import FitRecipe, FitResults # Files containing our experimental data and structure file dataFile = "ni-q27r100-neutron.gr" structureFile = "ni.cif" spaceGroup = "Fm-3m" # The first thing to construct is a contribution. Since this is a simple # example, the contribution will simply contain our PDF data and an associated # structure file. We'll give it the name "nickel" niPDF = PDFContribution("nickel") # Load the data and set the r-range over which we'll fit niPDF.loadData(dataFile) niPDF.setCalculationRange(xmin=1, xmax=20, dx=0.01) # Add the structure from our cif file to the contribution niStructure = loadStructure(structureFile) niPDF.addStructure("nickel", niStructure) # The FitRecipe does the work of calculating the PDF with the fit variable # that we give it. niFit = FitRecipe() # give the PDFContribution to the FitRecipe niFit.addContribution(niPDF) # Configure the fit variables and give them to the recipe. We can use the # srfit function constrainAsSpaceGroup to constrain the lattice and ADP
def makeRecipe(niciffile, siciffile, datname): """Create a fitting recipe for crystalline PDF data.""" # Load data and add it to the profile contribution = PDFContribution("nisi") contribution.loadData(datname) contribution.setCalculationRange(xmax=20) stru = CreateCrystalFromCIF(file(niciffile)) contribution.addStructure("ni", stru) stru = CreateCrystalFromCIF(file(siciffile)) contribution.addStructure("si", stru) # Make the FitRecipe and add the FitContribution. recipe = FitRecipe() recipe.addContribution(contribution) ## Configure the fit variables # Start by configuring the scale factor and resolution factors. # We want the sum of the phase scale factors to be 1. recipe.newVar("scale_ni", 0.1) recipe.constrain(contribution.ni.scale, "scale_ni") recipe.constrain(contribution.si.scale, "1 - scale_ni") # We also want the resolution factor to be the same on each. This is done # for free by the PDFContribution. We simply need to add it to the recipe. recipe.addVar(contribution.qdamp, 0.03) # Vary the gloabal scale as well. recipe.addVar(contribution.scale, 1) # Now we can configure the structural parameters. Since we're using # ObjCrystCrystalParSets, the space group constraints are automatically # applied to each phase. We must selectively vary the free parameters. # # First the nickel parameters. # Note that ni is the name of the PDFGenerator that was automatically # created by the PDFContribution. We selected this name in addStructure # above. phase_ni = contribution.ni.phase for par in phase_ni.sgpars: recipe.addVar(par, name=par.name + "_ni") recipe.addVar(contribution.ni.delta2, name="delta2_ni") # Next the silicon parameters phase_si = contribution.si.phase for par in phase_si.sgpars: recipe.addVar(par, name=par.name + "_si") recipe.addVar(contribution.si.delta2, name="delta2_si") # We have prior information from the earlier examples so we'll use it here # in the form of restraints. # # The nickel lattice parameter was measured to be 3.527. The uncertainty # values are invalid for that measurement, since the data from which it is # derived has no uncertainty. Thus, we will tell the recipe to scale the # residual, which means that it will be weighted as much as the average # data point during the fit. recipe.restrain("a_ni", lb=3.527, ub=3.527, scaled=True) # Now we do the same with the delta2 and Biso parameters (remember that # Biso = 8*pi**2*Uiso) recipe.restrain("delta2_ni", lb=2.22, ub=2.22, scaled=True) recipe.restrain("Biso_0_ni", lb=0.454, ub=0.454, scaled=True) # # We can do the same with the silicon values. We haven't done a thorough # job of measuring the uncertainties in the results, so we'll scale these # as well. recipe.restrain("a_si", lb=5.430, ub=5.430, scaled=True) recipe.restrain("delta2_si", lb=3.54, ub=3.54, scaled=True) recipe.restrain("Biso_0_si", lb=0.645, ub=0.645, scaled=True) # Give the recipe away so it can be used! return recipe
def make_recipe(self, structure, sg): """ Construct PDF with diffpy. """ # construct a PDFContribution object pdf = PDFContribution("Contribution") # read experimental data try: pdf.loadData(self.input_file) except: print_failure('Failed to parse ' + self.input_file + '. Exiting...') exit() print('Constructing PDF object for', structure.title) pdf.setCalculationRange(self.xmin, self.xmax, self.dx) pdf.addStructure("Contribution", structure) # create FitRecipe to calculate PDF with chosen fit variable fit = FitRecipe() fit.addContribution(pdf) # configure variables and add to recipe if sg != 'xxx' and sg is not None: print(sg) spacegroup_params = constrainAsSpaceGroup(pdf.Contribution.phase, sg) else: cart_lat = abc2cart([[ structure.lattice.a, structure.lattice.b, structure.lattice.c ], [ structure.lattice.alpha, structure.lattice.beta, structure.lattice.gamma ]]) positions_frac = structure.xyz atomic_numbers = [] for atom in structure.element: atomic_numbers.append(get_atomic_number(atom)) cell = (cart_lat, positions_frac, atomic_numbers) sg = int( spg.get_spacegroup(cell, symprec=1e-2).split(' ')[1].replace( '(', '').replace(')', '')) spacegroup_params = constrainAsSpaceGroup(pdf.Contribution.phase, sg) # print('Space group parameters:') # print(', '.join([param.name for param in spacegroup_params])) # iterate through spacegroup params and activate them for param in spacegroup_params.latpars: fit.addVar(param) for param in spacegroup_params.xyzpars: fit.addVar(param, fixed=True) # these next parameters are taken from Martin's PDFht.py, # though I have a feeling that was not their origin... # set initial ADP parameters for param in spacegroup_params.adppars: fit.addVar(param, value=0.03, fixed=True) # overall scale of PDF and delta2 parameter for correlated motion - from PDFht.py fit.addVar(pdf.scale, 1, fixed=True) fit.restrain(pdf.scale, lb=0, ub=0.1, scaled=True) fit.addVar(pdf.Contribution.delta2, 5, fixed=True) fit.restrain(pdf.Contribution.delta2, lb=1, ub=10, scaled=True) # fix Qdamp based on information about "our beamline": yep, no idea fit.addVar(pdf.qdamp, 0.03, fixed=True) fit.restrain(pdf.qdamp, lb=0, ub=0.1, scaled=True) return fit
# DiffPy-CMI modules for building a fitting recipe from diffpy.Structure import loadStructure from diffpy.srfit.pdf import PDFContribution from diffpy.srfit.fitbase import FitRecipe, FitResults # Files containing our experimental data and structure file dataFile = "cdse.gr" structureFile = "cdse.xyz" # The first thing to construct is a contribution. Since this is a simple # example, the contribution will simply contain our PDF data and an associated # structure file. We'll give it the name "cdse" cdsePDF = PDFContribution("CdSe") # Load the data and set the r-range over which we'll fit cdsePDF.loadData(dataFile) cdsePDF.setCalculationRange(xmin=1, xmax=20, dx=0.01) # Add the structure from our xyz file to the contribution, since the structure # model is non-periodic, we need to specify the periodic=False here to get the # right PDF cdseStructure = loadStructure(structureFile) cdsePDF.addStructure("CdSe", cdseStructure, periodic=False) # The FitRecipe does the work of managing one or more contributions # that are optimized together. In addition, FitRecipe configures # fit variables that are tied to the model parameters and thus # controls the calculated profiles. cdseFit = FitRecipe() # give the PDFContribution to the FitRecipe
def makeRecipe(niciffile, siciffile, datname): """Create a fitting recipe for crystalline PDF data.""" # Load data and add it to the profile contribution = PDFContribution("nisi") contribution.loadData(datname) contribution.setCalculationRange(xmax = 20) stru = CreateCrystalFromCIF(file(niciffile)) contribution.addStructure("ni", stru) stru = CreateCrystalFromCIF(file(siciffile)) contribution.addStructure("si", stru) # Make the FitRecipe and add the FitContribution. recipe = FitRecipe() recipe.addContribution(contribution) ## Configure the fit variables # Start by configuring the scale factor and resolution factors. # We want the sum of the phase scale factors to be 1. recipe.newVar("scale_ni", 0.1) recipe.constrain(contribution.ni.scale, "scale_ni") recipe.constrain(contribution.si.scale, "1 - scale_ni") # We also want the resolution factor to be the same on each. This is done # for free by the PDFContribution. We simply need to add it to the recipe. recipe.addVar(contribution.qdamp, 0.03) # Vary the gloabal scale as well. recipe.addVar(contribution.scale, 1) # Now we can configure the structural parameters. Since we're using # ObjCrystCrystalParSets, the space group constraints are automatically # applied to each phase. We must selectively vary the free parameters. # # First the nickel parameters. # Note that ni is the name of the PDFGenerator that was automatically # created by the PDFContribution. We selected this name in addStructure # above. phase_ni = contribution.ni.phase for par in phase_ni.sgpars: recipe.addVar(par, name = par.name + "_ni") recipe.addVar(contribution.ni.delta2, name = "delta2_ni") # Next the silicon parameters phase_si = contribution.si.phase for par in phase_si.sgpars: recipe.addVar(par, name = par.name + "_si") recipe.addVar(contribution.si.delta2, name = "delta2_si") # We have prior information from the earlier examples so we'll use it here # in the form of restraints. # # The nickel lattice parameter was measured to be 3.527. The uncertainty # values are invalid for that measurement, since the data from which it is # derived has no uncertainty. Thus, we will tell the recipe to scale the # residual, which means that it will be weighted as much as the average # data point during the fit. recipe.restrain("a_ni", lb = 3.527, ub = 3.527, scaled = True) # Now we do the same with the delta2 and Biso parameters (remember that # Biso = 8*pi**2*Uiso) recipe.restrain("delta2_ni", lb = 2.22, ub = 2.22, scaled = True) recipe.restrain("Biso_0_ni", lb = 0.454, ub = 0.454, scaled = True) # # We can do the same with the silicon values. We haven't done a thorough # job of measuring the uncertainties in the results, so we'll scale these # as well. recipe.restrain("a_si", lb = 5.430, ub = 5.430, scaled = True) recipe.restrain("delta2_si", lb = 3.54, ub = 3.54, scaled = True) recipe.restrain("Biso_0_si", lb = 0.645, ub = 0.645, scaled = True) # Give the recipe away so it can be used! return recipe
import numpy as np from pyobjcryst import loadCrystal from diffpy.srfit.pdf import PDFContribution from diffpy.srfit.fitbase import Profile, FitRecipe, FitResults nphcrystal = loadCrystal('naphthalene.cif') pdfcntb = PDFContribution('pdfcntb') pdfcntb.loadData('naphthalene.gr') pdfcntb.qdamp = 0.06 pdfcntb.setCalculationRange(1.1, 25) pdfcntb.addStructure('nph', nphcrystal) nphfit = FitRecipe() nphfit.clearFitHooks() nphfit.addContribution(pdfcntb) nphfit.addVar(pdfcntb.scale, name='scale') nphfit.addVar(pdfcntb.nph.delta2, value=1.0) nphase = pdfcntb.nph.phase # unit cell parameters nphfit.addVar(nphase.a) nphfit.addVar(nphase.b) nphfit.addVar(nphase.c) # cell-angle beta is in radians in ObjCryst Crystal # we will refine angle in degrees. nphfit.newVar('beta', value=np.degrees(nphase.beta.value)) nphfit.constrain(nphase.beta, 'radians(beta)') # all carbon species have the same displacement parameter, # it is sufficient to add constraint for the C1 atom