diff --git a/docs/examples/coreshellnp.py b/docs/examples/coreshellnp.py index 8030a34..488b6e6 100644 --- a/docs/examples/coreshellnp.py +++ b/docs/examples/coreshellnp.py @@ -66,9 +66,9 @@ def makeRecipe(stru1, stru2, datname): # The FitContribution # Add both generators and the profile to the FitContribution. contribution = FitContribution("cdszns") - contribution.addProfileGenerator(generator_cds) - contribution.addProfileGenerator(generator_zns) - contribution.setProfile(profile, xname="r") + contribution.add_profile_generator(generator_cds) + contribution.add_profile_generator(generator_zns) + contribution.set_profile(profile, xname="r") # Set up the characteristic functions. We use a spherical CF for the core # and a spherical shell CF for the shell. Since this is set up as two @@ -81,7 +81,7 @@ def makeRecipe(stru1, stru2, datname): # Write the fitting equation. We want to sum the PDFs from each phase and # multiply it by a scaling factor. - contribution.setEquation("scale * (f_CdS * G_CdS + f_ZnS * G_ZnS)") + contribution.set_equation("scale * (f_CdS * G_CdS + f_ZnS * G_ZnS)") # Make the FitRecipe and add the FitContribution. recipe = FitRecipe() diff --git a/docs/examples/crystalpdf.py b/docs/examples/crystalpdf.py index 41dbca6..c3f1122 100644 --- a/docs/examples/crystalpdf.py +++ b/docs/examples/crystalpdf.py @@ -74,8 +74,8 @@ def makeRecipe(ciffile, datname): # Here we associate the Profile and ProfileGenerator, as has been done # before. contribution = FitContribution("nickel") - contribution.addProfileGenerator(generator) - contribution.setProfile(profile, xname="r") + contribution.add_profile_generator(generator) + contribution.set_profile(profile, xname="r") # Make the FitRecipe and add the FitContribution. recipe = FitRecipe() diff --git a/docs/examples/crystalpdfall.py b/docs/examples/crystalpdfall.py index 056f8a8..f5e4112 100644 --- a/docs/examples/crystalpdfall.py +++ b/docs/examples/crystalpdfall.py @@ -47,8 +47,8 @@ def makeProfile(datafile): def makeContribution(name, generator, profile): """Make a FitContribution and add a generator and profile.""" contribution = FitContribution(name) - contribution.addProfileGenerator(generator) - contribution.setProfile(profile, xname="r") + contribution.add_profile_generator(generator) + contribution.set_profile(profile, xname="r") return contribution @@ -93,14 +93,14 @@ def makeRecipe( xcontribution_sini = makeContribution( "xsini", xgenerator_sini_ni, xprofile_sini ) - xcontribution_sini.addProfileGenerator(xgenerator_sini_si) - xcontribution_sini.setEquation("scale * (xG_sini_ni + xG_sini_si)") + xcontribution_sini.add_profile_generator(xgenerator_sini_si) + xcontribution_sini.set_equation("scale * (xG_sini_ni + xG_sini_si)") # As explained in another example, we want to minimize using Rw^2. - xcontribution_ni.setResidualEquation("resv") - xcontribution_si.setResidualEquation("resv") - ncontribution_ni.setResidualEquation("resv") - xcontribution_sini.setResidualEquation("resv") + xcontribution_ni.set_residual_equation("resv") + xcontribution_si.set_residual_equation("resv") + ncontribution_ni.set_residual_equation("resv") + xcontribution_sini.set_residual_equation("resv") # Make the FitRecipe and add the FitContributions. recipe = FitRecipe() diff --git a/docs/examples/crystalpdfobjcryst.py b/docs/examples/crystalpdfobjcryst.py index 4919543..f7236bc 100644 --- a/docs/examples/crystalpdfobjcryst.py +++ b/docs/examples/crystalpdfobjcryst.py @@ -62,8 +62,8 @@ def makeRecipe(ciffile, datname): # The FitContribution contribution = FitContribution("nickel") - contribution.addProfileGenerator(generator) - contribution.setProfile(profile, xname="r") + contribution.add_profile_generator(generator) + contribution.set_profile(profile, xname="r") # Make the FitRecipe and add the FitContribution. recipe = FitRecipe() diff --git a/docs/examples/crystalpdftwodata.py b/docs/examples/crystalpdftwodata.py index debefc0..4f306aa 100644 --- a/docs/examples/crystalpdftwodata.py +++ b/docs/examples/crystalpdftwodata.py @@ -84,12 +84,12 @@ def makeRecipe(ciffile, xdatname, ndatname): # The FitContributions # We associate the x-ray PDFGenerator and Profile in one FitContribution... xcontribution = FitContribution("xnickel") - xcontribution.addProfileGenerator(xgenerator) - xcontribution.setProfile(xprofile, xname="r") + xcontribution.add_profile_generator(xgenerator) + xcontribution.set_profile(xprofile, xname="r") # and the neutron objects in another. ncontribution = FitContribution("nnickel") - ncontribution.addProfileGenerator(ngenerator) - ncontribution.setProfile(nprofile, xname="r") + ncontribution.add_profile_generator(ngenerator) + ncontribution.set_profile(nprofile, xname="r") # This example is different than the previous ones in that we are composing # a residual function from other residuals (one for the x-ray contribution @@ -105,8 +105,8 @@ def makeRecipe(ciffile, xdatname, ndatname): # The contribution's residual can be either chi^2, Rw^2, or custom crafted. # In this case, we should minimize Rw^2 of each contribution so that each # one can contribute roughly equally to the fit. - xcontribution.setResidualEquation("resv") - ncontribution.setResidualEquation("resv") + xcontribution.set_residual_equation("resv") + ncontribution.set_residual_equation("resv") # Make the FitRecipe and add the FitContributions. recipe = FitRecipe() diff --git a/docs/examples/crystalpdftwophase.py b/docs/examples/crystalpdftwophase.py index 98a8790..93ad39d 100644 --- a/docs/examples/crystalpdftwophase.py +++ b/docs/examples/crystalpdftwophase.py @@ -72,15 +72,15 @@ def makeRecipe(niciffile, siciffile, datname): # Add both generators to the FitContribution. Add the Profile. This will # send the metadata to the generators. contribution = FitContribution("nisi") - contribution.addProfileGenerator(generator_ni) - contribution.addProfileGenerator(generator_si) - contribution.setProfile(profile, xname="r") + contribution.add_profile_generator(generator_ni) + contribution.add_profile_generator(generator_si) + contribution.set_profile(profile, xname="r") # Write the fitting equation. We want to sum the PDFs from each phase and # multiply it by a scaling factor. We also want a certain phase scaling # relationship between the PDFs which we will enforce with constraints in # the FitRecipe. - contribution.setEquation("scale * (G_ni + G_si)") + contribution.set_equation("scale * (G_ni + G_si)") # Make the FitRecipe and add the FitContribution. recipe = FitRecipe() diff --git a/docs/examples/debyemodel.py b/docs/examples/debyemodel.py index 3fb42c7..b093d1f 100644 --- a/docs/examples/debyemodel.py +++ b/docs/examples/debyemodel.py @@ -102,7 +102,7 @@ def makeRecipe(): # independent variable (the temperature) from the data to calculate the # theoretical signal, so give it an informative name ('T') that we can use # later. - contribution.setProfile(profile, xname="T") + contribution.set_profile(profile, xname="T") # We now need to create the fitting equation. We tell the FitContribution # to use the 'debye' function defined below. The 'registerFunction' method @@ -126,7 +126,7 @@ def makeRecipe(): # the debye equation to be positive, so we specify the input as abs(thetaD) # in the equation below. Furthermore, we know 'm', the mass of lead, so we # can specify that as well. - contribution.setEquation("debye(T, 207.2, abs(thetaD)) + offset") + contribution.set_equation("debye(T, 207.2, abs(thetaD)) + offset") # The FitRecipe # The FitRecipe lets us define what we want to fit. It is where we can diff --git a/docs/examples/ellipsoidsas.py b/docs/examples/ellipsoidsas.py index 23ee5f0..77b21b8 100644 --- a/docs/examples/ellipsoidsas.py +++ b/docs/examples/ellipsoidsas.py @@ -57,14 +57,14 @@ def makeRecipe(datname): # Here we associate the Profile and ProfileGenerator, as has been done # before. contribution = FitContribution("ellipsoid") - contribution.addProfileGenerator(generator) - contribution.setProfile(profile, xname="q") + contribution.add_profile_generator(generator) + contribution.set_profile(profile, xname="q") # We want to fit the log of the signal to the log of the data so that the # higher-Q information remains significant. There are no I(Q) uncertainty # values with the data, so we do not need to worry about the effect this # will have on the estimated parameter uncertainties. - contribution.setResidualEquation("log(eq) - log(y)") + contribution.set_residual_equation("log(eq) - log(y)") # Make the FitRecipe and add the FitContribution. recipe = FitRecipe() diff --git a/docs/examples/gaussiangenerator.py b/docs/examples/gaussiangenerator.py index ff65fb9..2831a54 100644 --- a/docs/examples/gaussiangenerator.py +++ b/docs/examples/gaussiangenerator.py @@ -33,9 +33,10 @@ Extensions -- Remove the amplitude from GaussianGenerator and instead use the 'setEquation' - method of the FitContribution to account for it. Note that the - GaussianGenerator will be accessible by its name, "g". +- Remove the amplitude from GaussianGenerator and instead use the + 'set_equation' method of the FitContribution to account for it. + Note that the GaussianGenerator will be accessible by + its name, "g". """ from numpy import exp @@ -144,8 +145,8 @@ def makeRecipe(): # attribute of the FitContribution by its name ("g"). Note that this will # set the fitting equation to "g", which calls the GaussianGenerator. contribution = FitContribution("g1") - contribution.addProfileGenerator(generator) - contribution.setProfile(profile) + contribution.add_profile_generator(generator) + contribution.set_profile(profile) # The FitRecipe # Now we create the FitRecipe and add the FitContribution. diff --git a/docs/examples/gaussianrecipe.py b/docs/examples/gaussianrecipe.py index 646afc7..1dfc583 100644 --- a/docs/examples/gaussianrecipe.py +++ b/docs/examples/gaussianrecipe.py @@ -114,7 +114,7 @@ def makeRecipe(): # us access to the data held within the Profile. Here, we can tell it what # name we want to use for the independent variable. We tell it to use the # name "x". - contribution.setProfile(profile, xname="x") + contribution.set_profile(profile, xname="x") # Now we need to create a fitting equation. We do that by writing out the # equation as a string. The FitContribution will turn this into a callable @@ -124,7 +124,7 @@ def makeRecipe(): # contribution by name. Since we told the contribution that our # independent variable is named "x", this value will be substituted into # the fitting equation whenever it is called. - contribution.setEquation("A * exp(-0.5*(x-x0)**2/sigma**2)") + contribution.set_equation("A * exp(-0.5*(x-x0)**2/sigma**2)") # To demonstrate how these parameters are used, we will give "A" an initial # value. Note that Parameters are not numbers, but are containers for diff --git a/docs/examples/interface.py b/docs/examples/interface.py index 6b0daca..640aebc 100644 --- a/docs/examples/interface.py +++ b/docs/examples/interface.py @@ -37,8 +37,8 @@ def main(): # FitContribution operations # "<<" - Inject a parameter value c = FitContribution("g1") - c.setProfile(p) - c.setEquation("A * exp(-0.5*(x-x0)**2/sigma**2)") + c.set_profile(p) + c.set_equation("A * exp(-0.5*(x-x0)**2/sigma**2)") c.A << 0.5 c.x0 << 5 c.sigma << 1 diff --git a/docs/examples/npintensity.py b/docs/examples/npintensity.py index 210aa4c..377a890 100644 --- a/docs/examples/npintensity.py +++ b/docs/examples/npintensity.py @@ -203,8 +203,8 @@ def makeRecipe(strufile, datname): # the FitContribution to name the x-variable of the profile "q", so we can # use it in equations with this name. contribution = FitContribution("bucky") - contribution.addProfileGenerator(generator) - contribution.setProfile(profile, xname="q") + contribution.add_profile_generator(generator) + contribution.set_profile(profile, xname="q") # Now we're ready to define the fitting equation for the FitContribution. # We need to modify the intensity calculation, and we'll do that from @@ -256,7 +256,7 @@ def gaussian(q, q0, width): # convolve the signal with the Gaussian to broaden it. Recall that we don't # need to supply arguments to the registered functions unless we want to # make changes to their input values. - contribution.setEquation("scale * convolve(I, gaussian) + bkgd") + contribution.set_equation("scale * convolve(I, gaussian) + bkgd") # Make the FitRecipe and add the FitContribution. recipe = FitRecipe() diff --git a/docs/examples/npintensityII.py b/docs/examples/npintensityII.py index 45751d4..54cb222 100644 --- a/docs/examples/npintensityII.py +++ b/docs/examples/npintensityII.py @@ -88,11 +88,11 @@ def makeRecipe(strufile, datname1, datname2): # The FitContributions # Create the FitContributions. contribution1 = FitContribution("bucky1") - contribution1.addProfileGenerator(generator1) - contribution1.setProfile(profile1, xname="q") + contribution1.add_profile_generator(generator1) + contribution1.set_profile(profile1, xname="q") contribution2 = FitContribution("bucky2") - contribution2.addProfileGenerator(generator2) - contribution2.setProfile(profile2, xname="q") + contribution2.add_profile_generator(generator2) + contribution2.set_profile(profile2, xname="q") # Now we're ready to define the fitting equation for each FitContribution. # The functions registered below will be independent, even though they take @@ -125,8 +125,8 @@ def gaussian(q, q0, width): # Now we can incorporate the scale and bkgd into our calculation. We also # convolve the signal with the gaussian to broaden it. - contribution1.setEquation("scale * convolve(I, gaussian) + bkgd") - contribution2.setEquation("scale * convolve(I, gaussian) + bkgd") + contribution1.set_equation("scale * convolve(I, gaussian) + bkgd") + contribution2.set_equation("scale * convolve(I, gaussian) + bkgd") # Make a FitRecipe and associate the FitContributions. recipe = FitRecipe() diff --git a/docs/examples/nppdfcrystal.py b/docs/examples/nppdfcrystal.py index 0c098ef..55ac049 100644 --- a/docs/examples/nppdfcrystal.py +++ b/docs/examples/nppdfcrystal.py @@ -48,13 +48,13 @@ def makeRecipe(ciffile, grdata): pdfprofile.setCalculationRange(xmin=0.1, xmax=20) pdfcontribution = FitContribution("pdf") - pdfcontribution.setProfile(pdfprofile, xname="r") + pdfcontribution.set_profile(pdfprofile, xname="r") pdfgenerator = PDFGenerator("G") pdfgenerator.setQmax(30.0) stru = loadCrystal(ciffile) pdfgenerator.setStructure(stru) - pdfcontribution.addProfileGenerator(pdfgenerator) + pdfcontribution.add_profile_generator(pdfgenerator) # Register the nanoparticle shape factor. from diffpy.srfit.pdf.characteristicfunctions import sphericalCF @@ -62,7 +62,7 @@ def makeRecipe(ciffile, grdata): pdfcontribution.registerFunction(sphericalCF, name="f") # Now we set up the fitting equation. - pdfcontribution.setEquation("f * G") + pdfcontribution.set_equation("f * G") # Now make the recipe. Make sure we fit the characteristic function shape # parameters, in this case 'psize', which is the diameter of the particle. diff --git a/docs/examples/nppdfobjcryst.py b/docs/examples/nppdfobjcryst.py index a05dbaa..25a9444 100644 --- a/docs/examples/nppdfobjcryst.py +++ b/docs/examples/nppdfobjcryst.py @@ -52,8 +52,8 @@ def makeRecipe(molecule, datname): # The FitContribution contribution = FitContribution("bucky") - contribution.addProfileGenerator(generator) - contribution.setProfile(profile, xname="r") + contribution.add_profile_generator(generator) + contribution.set_profile(profile, xname="r") # Make a FitRecipe. recipe = FitRecipe() diff --git a/docs/examples/nppdfsas.py b/docs/examples/nppdfsas.py index 0a9b820..8e26fdc 100644 --- a/docs/examples/nppdfsas.py +++ b/docs/examples/nppdfsas.py @@ -52,14 +52,14 @@ def makeRecipe(ciffile, grdata, iqdata): pdfprofile.setCalculationRange(xmin=0.1, xmax=20) pdfcontribution = FitContribution("pdf") - pdfcontribution.setProfile(pdfprofile, xname="r") + pdfcontribution.set_profile(pdfprofile, xname="r") pdfgenerator = PDFGenerator("G") pdfgenerator.setQmax(30.0) stru = loadCrystal(ciffile) pdfgenerator.setStructure(stru) - pdfcontribution.addProfileGenerator(pdfgenerator) - pdfcontribution.setResidualEquation("resv") + pdfcontribution.add_profile_generator(pdfgenerator) + pdfcontribution.set_residual_equation("resv") # Create a SAS contribution as well. We assume the nanoparticle is roughly # elliptical. @@ -71,14 +71,14 @@ def makeRecipe(ciffile, grdata, iqdata): sasprofile.dy[:] = 1 sascontribution = FitContribution("sas") - sascontribution.setProfile(sasprofile) + sascontribution.set_profile(sasprofile) from sas.models.EllipsoidModel import EllipsoidModel model = EllipsoidModel() sasgenerator = SASGenerator("generator", model) - sascontribution.addProfileGenerator(sasgenerator) - sascontribution.setResidualEquation("resv") + sascontribution.add_profile_generator(sasgenerator) + sascontribution.set_residual_equation("resv") # Now we set up a characteristic function calculator that depends on the # sas model. @@ -89,7 +89,7 @@ def makeRecipe(ciffile, grdata, iqdata): pdfcontribution.registerCalculator(cfcalculator) # The PDF for a nanoscale crystalline is approximated by # Gnano = f * Gcryst - pdfcontribution.setEquation("f * G") + pdfcontribution.set_equation("f * G") # Moving on recipe = FitRecipe() diff --git a/docs/examples/simplerecipe.py b/docs/examples/simplerecipe.py index 0ec297a..ef1f9a5 100644 --- a/docs/examples/simplerecipe.py +++ b/docs/examples/simplerecipe.py @@ -38,7 +38,7 @@ def main(): # Set the equation. The variable "x" is taken from the data that was just # loaded. The other variables, "A", "x0" and "sigma" are turned into # attributes with an initial value of 0. - recipe.setEquation("A * exp(-0.5*(x-x0)**2/sigma**2)") + recipe.set_equation("A * exp(-0.5*(x-x0)**2/sigma**2)") # We can give them other values here. recipe.A = 1 diff --git a/docs/examples/threedoublepeaks.py b/docs/examples/threedoublepeaks.py index c0c9140..fa45e2d 100644 --- a/docs/examples/threedoublepeaks.py +++ b/docs/examples/threedoublepeaks.py @@ -50,7 +50,7 @@ def makeRecipe(): # Create the contribution contribution = FitContribution("peaks") - contribution.setProfile(profile, xname="t") + contribution.set_profile(profile, xname="t") pi = numpy.pi exp = numpy.exp @@ -77,7 +77,7 @@ def delta(t, mu): contribution.registerStringFunction(bkgdstr, "bkgd") # Now define our fitting equation. We will hardcode the peak ratios. - contribution.setEquation( + contribution.set_equation( "A1 * ( convolve( delta(t, mu11), peakshape(t, c, sig11) ) \ + 0.23*convolve( delta(t, mu12), peakshape(t, c, sig12) ) ) + \ A2 * ( convolve( delta(t, mu21), peakshape(t, c, sig21) ) \ diff --git a/news/fitcontribution-dep.rst b/news/fitcontribution-dep.rst new file mode 100644 index 0000000..73ef304 --- /dev/null +++ b/news/fitcontribution-dep.rst @@ -0,0 +1,23 @@ +**Added:** + +* + +**Changed:** + +* + +**Deprecated:** + +* Deprecate camel case naming convention in ``FitContribution`` and replace it with snake case. The following changes are, ``setProfile``-> ``set_profile``, ``addProfileGenerator`` -> ``add_profile_generator``, ``setEquation`` -> ``set_equation``, ``setResidualEquation`` -> ``set_residual_equation``, and ``getResidualEquation`` -> ``get_residual_equation``. + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/requirements/conda.txt b/requirements/conda.txt index 5306b5d..133da8b 100644 --- a/requirements/conda.txt +++ b/requirements/conda.txt @@ -1,3 +1,4 @@ matplotlib-base numpy scipy +diffpy.utils diff --git a/requirements/pip.txt b/requirements/pip.txt index 74fa65e..7e849b4 100644 --- a/requirements/pip.txt +++ b/requirements/pip.txt @@ -1,3 +1,4 @@ matplotlib numpy scipy +diffpy.utils diff --git a/src/diffpy/srfit/__init__.py b/src/diffpy/srfit/__init__.py index 0374fdc..faa4d40 100644 --- a/src/diffpy/srfit/__init__.py +++ b/src/diffpy/srfit/__init__.py @@ -38,4 +38,7 @@ # silence the pyflakes syntax checker assert __version__ or True +# the version at which deprecated features will be removed. +_REMOVAL_VERSION = "4.0.0" + # End of file diff --git a/src/diffpy/srfit/equation/builder.py b/src/diffpy/srfit/equation/builder.py index 4485087..a0e0fb8 100644 --- a/src/diffpy/srfit/equation/builder.py +++ b/src/diffpy/srfit/equation/builder.py @@ -53,12 +53,12 @@ > # sin is defined in this module as an OperatorBuilder > sin = getBuilder("sin") > beq = A*sin(a*x) -> eq = beq.getEquation() +> eq = beq.get_equation() The equation builder can also handle scalar constants. Staring with the above setup: > beq2 = A*sin(a*x) + 3 -> eq2 = beq2.getEquation() +> eq2 = beq2.get_equation() Here, we didn't have to wrap '3' in an ArgumentBuilder. Non scalars, constant or otherwise, must be wrapped as ArgumentBuilders in order to be used in this way. @@ -172,7 +172,7 @@ def makeEquation( lit = literals.Argument(value=beq, const=True) eq = Equation(name="", root=lit) else: - eq = beq.getEquation() + eq = beq.get_equation() self.equations.add(eq) return eq @@ -430,7 +430,7 @@ def __call__(self, *args): ) raise TypeError(m) - def getEquation(self): + def get_equation(self): """Get the equation built by this object. The equation will given the name "_eq_" where "" is diff --git a/src/diffpy/srfit/fitbase/fitcontribution.py b/src/diffpy/srfit/fitbase/fitcontribution.py index 5db6799..53134c6 100644 --- a/src/diffpy/srfit/fitbase/fitcontribution.py +++ b/src/diffpy/srfit/fitbase/fitcontribution.py @@ -24,11 +24,15 @@ __all__ = ["FitContribution"] +from diffpy.srfit import _REMOVAL_VERSION from diffpy.srfit.exceptions import SrFitError from diffpy.srfit.fitbase.parameter import ParameterProxy from diffpy.srfit.fitbase.parameterset import ParameterSet from diffpy.srfit.fitbase.profile import Profile from diffpy.srfit.fitbase.recipeorganizer import equationFromString +from diffpy.utils._deprecator import deprecated, deprecation_message + +_BASE_FITCONTRIBUTION = __name__ + ".FitContribution" class FitContribution(ParameterSet): @@ -97,7 +101,24 @@ def __init__(self, name): self._manage(self._generators) return + @deprecated( + deprecation_message( + _BASE_FITCONTRIBUTION, + "setProfile", + "set_profile", + _REMOVAL_VERSION, + ) + ) def setProfile(self, profile, xname=None, yname=None, dyname=None): + """Deprecated. + + Use set_profile instead. + """ + return self.set_profile( + profile, xname=xname, yname=yname, dyname=dyname + ) + + def set_profile(self, profile, xname=None, yname=None, dyname=None): """Assign the Profile for this FitContribution. Attributes @@ -149,24 +170,39 @@ def setProfile(self, profile, xname=None, yname=None, dyname=None): # If we have ProfileGenerators, set their Profiles. for gen in self._generators.values(): - gen.setProfile(profile) + gen.set_profile(profile) # If we have _eq, but not _reseq, set the residual if self._eq is not None and self._reseq is None: - self.setResidualEquation("chiv") + self.set_residual_equation("chiv") return + @deprecated( + deprecation_message( + _BASE_FITCONTRIBUTION, + "addProfileGenerator", + "add_profile_generator", + _REMOVAL_VERSION, + ) + ) def addProfileGenerator(self, gen, name=None): + """Deprecated. + + Use add_profile_generator instead. + """ + return self.add_profile_generator(gen, name=name) + + def add_profile_generator(self, gen, name=None): """Add a ProfileGenerator to be used by this FitContribution. The ProfileGenerator is given a name so that it can be used as part of - the profile equation (see setEquation). This can be different from the + the profile equation (see set_equation). This can be different from the name of the ProfileGenerator used for attribute access. FitContributions should not share ProfileGenerator instances. Different ProfileGenerators can share Parameters and ParameterSets, however. - Calling addProfileGenerator sets the profile equation to call the + Calling add_profile_generator sets the profile equation to call the calculator and if there is not a profile equation already. Attributes @@ -192,27 +228,42 @@ def addProfileGenerator(self, gen, name=None): # If we have a profile, set the profile of the generator. if self.profile is not None: - gen.setProfile(self.profile) + gen.set_profile(self.profile) # Make this our equation if we don't have one. This will set the # residual equation if necessary. if self._eq is None: - self.setEquation(name) + self.set_equation(name) return + @deprecated( + deprecation_message( + _BASE_FITCONTRIBUTION, + "setEquation", + "set_equation", + _REMOVAL_VERSION, + ) + ) def setEquation(self, eqstr, ns={}): + """Deprecated. + + Use set_equation instead. + """ + return self.set_equation(eqstr, ns=ns) + + def set_equation(self, eqstr, ns={}): """Set the profile equation for the FitContribution. This sets the equation that will be used when generating the residual for this FitContribution. The equation will be usable within - setResidualEquation as "eq", and it takes no arguments. + set_residual_equation as "eq", and it takes no arguments. Attributes ---------- eqstr A string representation of the equation. Any Parameter - registered by addParameter or setProfile, or function + registered by addParameter or set_profile, or function registered by setCalculator, registerFunction or registerStringFunction can be can be used in the equation by name. Other names will be turned into Parameters of this @@ -240,11 +291,26 @@ def setEquation(self, eqstr, ns={}): # Set the residual if we need to if self.profile is not None and self._reseq is None: - self.setResidualEquation("chiv") + self.set_residual_equation("chiv") return + @deprecated( + deprecation_message( + _BASE_FITCONTRIBUTION, + "getEquation", + "get_equation", + _REMOVAL_VERSION, + ) + ) def getEquation(self): + """Deprecated. + + Use get_equation instead. + """ + return self.get_equation() + + def get_equation(self): """Get math expression string for the active profile equation. Return normalized math expression or an empty string if profile @@ -257,7 +323,22 @@ def getEquation(self): rv = getExpression(self._eq) return rv + @deprecated( + deprecation_message( + _BASE_FITCONTRIBUTION, + "setResidualEquation", + "set_residual_equation", + _REMOVAL_VERSION, + ) + ) def setResidualEquation(self, eqstr): + """Deprecated. + + Use set_residual_equation instead. + """ + return self.set_residual_equation(eqstr) + + def set_residual_equation(self, eqstr): """Set the residual equation for the FitContribution. Attributes @@ -301,7 +382,22 @@ def setResidualEquation(self, eqstr): return + @deprecated( + deprecation_message( + _BASE_FITCONTRIBUTION, + "getResidualEquation", + "get_residual_equation", + _REMOVAL_VERSION, + ) + ) def getResidualEquation(self): + """Deprecated. + + Use get_residual_equation instead. + """ + return self.get_residual_equation() + + def get_residual_equation(self): """Get math expression string for the active residual equation. Return normalized math formula or an empty string if residual @@ -325,7 +421,7 @@ def residual(self): chiv = (eq() - self.profile.y) / self.profile.dy The value that is optimized is dot(chiv, chiv). - The residual equation can be changed with the setResidualEquation + The residual equation can be changed with the set_residual_equation method. """ # Assign the calculated profile diff --git a/src/diffpy/srfit/fitbase/profilegenerator.py b/src/diffpy/srfit/fitbase/profilegenerator.py index e2b840c..c6adabb 100644 --- a/src/diffpy/srfit/fitbase/profilegenerator.py +++ b/src/diffpy/srfit/fitbase/profilegenerator.py @@ -153,7 +153,7 @@ def operation(self): y = self.__call__(self.profile.x) return y - def setProfile(self, profile): + def set_profile(self, profile): """Assign the profile. Attributes diff --git a/src/diffpy/srfit/fitbase/simplerecipe.py b/src/diffpy/srfit/fitbase/simplerecipe.py index 29029f1..e3cbda0 100644 --- a/src/diffpy/srfit/fitbase/simplerecipe.py +++ b/src/diffpy/srfit/fitbase/simplerecipe.py @@ -93,7 +93,7 @@ def __init__(self, name="fit", conclass=FitContribution): self.fithooks[0].verbose = 3 contribution = conclass("contribution") self.profile = Profile() - contribution.setProfile(self.profile) + contribution.set_profile(self.profile) self.addContribution(contribution) self.results = FitResults(self, update=False) @@ -201,12 +201,12 @@ def loadtxt(self, *args, **kw): return self.profile.loadtxt(*args, **kw) # FitContribution - def setEquation(self, eqstr, ns={}): + def set_equation(self, eqstr, ns={}): """Set the profile equation for the FitContribution. This sets the equation that will be used when generating the residual. - The equation will be usable within setResidualEquation as "eq", and it - takes no arguments. + The equation will be usable within set_residual_equation as "eq", + and it takes no arguments. Attributes ---------- @@ -222,7 +222,7 @@ def setEquation(self, eqstr, ns={}): Raises ValueError if ns uses a name that is already used for a variable. """ - self.contribution.setEquation(eqstr, ns={}) + self.contribution.set_equation(eqstr, ns={}) # Extract variables for par in self.contribution: # Skip Profile Parameters diff --git a/src/diffpy/srfit/pdf/pdfcontribution.py b/src/diffpy/srfit/pdf/pdfcontribution.py index 2679a3f..3f487a9 100644 --- a/src/diffpy/srfit/pdf/pdfcontribution.py +++ b/src/diffpy/srfit/pdf/pdfcontribution.py @@ -93,7 +93,7 @@ def __init__(self, name): self._meta = {} # Add the profile profile = Profile() - self.setProfile(profile, xname="r") + self.set_profile(profile, xname="r") # Need a parameter for the overall scale, in the case that this is a # multi-phase fit. @@ -273,14 +273,14 @@ def _setup_generator(self, gen): with setStructure or setPhase. """ # Add the generator to this FitContribution - self.addProfileGenerator(gen) + self.add_profile_generator(gen) # Set the proper equation for the fit, depending on the number of # phases we have. gnames = self._generators.keys() eqstr = " + ".join(gnames) eqstr = "scale * (%s)" % eqstr - self.setEquation(eqstr) + self.set_equation(eqstr) # Update with our metadata gen.meta.update(self._meta) diff --git a/tests/test_builder.py b/tests/test_builder.py index 4045dd6..dbb53d4 100644 --- a/tests/test_builder.py +++ b/tests/test_builder.py @@ -214,7 +214,7 @@ def testBuildEquation(noObserversInGlobalBuilders): x = numpy.arange(0, numpy.pi, 0.1) beq = A * sin(a * x) - eq = beq.getEquation() + eq = beq.get_equation() assert "a" in eq.argdict assert "A" in eq.argdict @@ -235,7 +235,7 @@ def _f(a, b): b = builder.ArgumentBuilder(name="b", value=1) beq = sin(f(a, b)) - eq = beq.getEquation() + eq = beq.get_equation() assert eq() == numpy.sin(_f(2, 1)) # complex function @@ -245,28 +245,28 @@ def _f(a, b): x = builder.ArgumentBuilder(name="x", value=_x, const=True) sigma = builder.ArgumentBuilder(name="sigma", value=0.1) beq = sqrt(e ** (-0.5 * (x / sigma) ** 2)) - eq = beq.getEquation() + eq = beq.get_equation() assert numpy.allclose(eq(), numpy.sqrt(numpy.exp(-0.5 * (_x / 0.1) ** 2))) # Equation with Equation A = builder.ArgumentBuilder(name="A", value=2) B = builder.ArgumentBuilder(name="B", value=4) beq = A + B - eq = beq.getEquation() + eq = beq.get_equation() E = builder.wrapOperator("eq", eq) - eq2 = (2 * E).getEquation() + eq2 = (2 * E).get_equation() # Make sure these evaluate to the same thing assert eq.args == [A.literal, B.literal] assert 2 * eq() == eq2() # Pass new arguments to the equation C = builder.ArgumentBuilder(name="C", value=5) D = builder.ArgumentBuilder(name="D", value=6) - eq3 = (E(C, D) + 1).getEquation() + eq3 = (E(C, D) + 1).get_equation() assert 12 == eq3() # Pass old and new arguments to the equation # If things work right, A has been given the value of C in the last # evaluation (5) - eq4 = (3 * E(A, D) - 1).getEquation() + eq4 = (3 * E(A, D) - 1).get_equation() assert 32 == eq4() # Try to pass the wrong number of arguments with pytest.raises(ValueError): diff --git a/tests/test_contribution.py b/tests/test_contribution.py index 48863e4..e305d27 100644 --- a/tests/test_contribution.py +++ b/tests/test_contribution.py @@ -34,6 +34,7 @@ def setUp(self): self.fitcontribution = FitContribution("test") return + # Duplicate test due to name change of setProfile to set_profile def testSetProfile(self): fc = self.fitcontribution profile = self.profile @@ -50,15 +51,36 @@ def testSetProfile(self): self.assertRaises(TypeError, fc1.setProfile, "invalid") # check if residual equation is set up when possible fc2 = FitContribution("test2") - fc2.setEquation("A * x") + fc2.set_equation("A * x") fc2.setProfile(profile) self.assertFalse(fc2._reseq is None) return + def test_set_profile(self): + fc = self.fitcontribution + profile = self.profile + fc.set_profile(self.profile) + # verify standard profile setup + self.assertTrue(fc.profile is profile) + self.assertTrue(fc.x.par is profile.xpar) + self.assertTrue(fc.y.par is profile.ypar) + self.assertTrue(fc.dy.par is profile.dypar) + self.assertTrue(fc._eq is None) + self.assertTrue(fc._reseq is None) + # check type checking + fc1 = FitContribution("test1") + self.assertRaises(TypeError, fc1.set_profile, "invalid") + # check if residual equation is set up when possible + fc2 = FitContribution("test2") + fc2.set_equation("A * x") + fc2.set_profile(profile) + self.assertFalse(fc2._reseq is None) + return + def testAddProfileGenerator(self): fc = self.fitcontribution gen = self.gen - fc.addProfileGenerator(gen, "gen") + fc.add_profile_generator(gen, "gen") xobs = arange(0, 10, 0.5) self.assertTrue(array_equal(xobs, gen(xobs))) @@ -74,8 +96,8 @@ def testInteraction(self): gen = self.gen # Add the calculator and profile - fc.setProfile(profile) - fc.addProfileGenerator(gen, "I") + fc.set_profile(profile) + fc.add_profile_generator(gen, "I") # Check attributes are created self.assertTrue(fc.profile is profile) @@ -119,8 +141,8 @@ def testReplacements(self): gen = self.gen # Validate equations - fc.setProfile(profile) - fc.addProfileGenerator(gen, "I") + fc.set_profile(profile) + fc.add_profile_generator(gen, "I") self.assertTrue(array_equal(gen.value, xobs)) self.assertTrue(array_equal(fc._eq(), xobs)) self.assertAlmostEqual(0, sum(fc._reseq())) @@ -129,7 +151,7 @@ def testReplacements(self): reseq = fc._reseq # Now set a different profile - fc.setProfile(profile2) + fc.set_profile(profile2) self.assertTrue(fc.profile is profile2) self.assertTrue(gen.profile is profile2) self.assertTrue(fc._eq is eq) @@ -143,15 +165,15 @@ def testReplacements(self): self.assertEqual(len(xobs2), len(fc.residual())) return - def test_getResidualEquation(self): + def test_get_residual_equation(self): """Check getting the current formula for residual equation.""" fc = self.fitcontribution - self.assertEqual("", fc.getResidualEquation()) - fc.setProfile(self.profile) - fc.setEquation("A * x + B") - self.assertEqual("((eq - y) / dy)", fc.getResidualEquation()) - fc.setResidualEquation("2 * (eq - y)") - self.assertEqual("(2 * (eq - y))", fc.getResidualEquation()) + self.assertEqual("", fc.get_residual_equation()) + fc.set_profile(self.profile) + fc.set_equation("A * x + B") + self.assertEqual("((eq - y) / dy)", fc.get_residual_equation()) + fc.set_residual_equation("2 * (eq - y)") + self.assertEqual("(2 * (eq - y))", fc.get_residual_equation()) return def test_releaseOldEquations(self): @@ -159,24 +181,24 @@ def test_releaseOldEquations(self): fc = self.fitcontribution self.assertEqual(0, len(fc._eqfactory.equations)) for i in range(5): - fc.setEquation("A * x + B") + fc.set_equation("A * x + B") self.assertEqual(1, len(fc._eqfactory.equations)) - fc.setProfile(self.profile) + fc.set_profile(self.profile) for i in range(5): - fc.setResidualEquation("chiv") + fc.set_residual_equation("chiv") self.assertEqual(2, len(fc._eqfactory.equations)) return def test_registerFunction(self): - """Ensure registered function works after second setEquation call.""" + """Ensure registered function works after second set_equation call.""" fc = self.fitcontribution fc.registerFunction(_fsquare, name="fsquare") - fc.setEquation("fsquare") + fc.set_equation("fsquare") fc.x.setValue(5) self.assertEqual(25, fc.evaluate()) fc.x << 6 self.assertEqual(36, fc.evaluate()) - fc.setEquation("fsquare + 5") + fc.set_equation("fsquare + 5") self.assertEqual(41, fc.evaluate()) fc.x << -1 self.assertEqual(6, fc.evaluate()) @@ -194,9 +216,9 @@ def testResidual(noObserversInGlobalBuilders): fc = FitContribution("test") # Add the calculator and profile - fc.setProfile(profile) + fc.set_profile(profile) assert fc.profile is profile - fc.addProfileGenerator(gen, "I") + fc.add_profile_generator(gen, "I") assert fc._eq._value is None assert fc._reseq._value is None assert 1 == len(fc._generators) @@ -215,7 +237,7 @@ def testResidual(noObserversInGlobalBuilders): assert dot(chiv, chiv) == pytest.approx(0) # Now change the equation - fc.setEquation("2*I") + fc.set_equation("2*I") assert fc._eq._value is None assert fc._reseq._value is None chiv = fc.residual() @@ -224,7 +246,7 @@ def testResidual(noObserversInGlobalBuilders): # Try to add a parameter c = Parameter("c", 2) fc._add_parameter(c) - fc.setEquation("c*I") + fc.set_equation("c*I") assert fc._eq._value is None assert fc._reseq._value is None chiv = fc.residual() @@ -232,7 +254,7 @@ def testResidual(noObserversInGlobalBuilders): # Try something more complex c.setValue(3) - fc.setEquation("c**2*sin(I)") + fc.set_equation("c**2*sin(I)") assert fc._eq._value is None assert fc._reseq._value is None xobs = arange(0, 10, 0.5) @@ -245,35 +267,35 @@ def testResidual(noObserversInGlobalBuilders): assert dot(chiv, chiv) == pytest.approx(0) # Choose a new residual. - fc.setEquation("2*I") - fc.setResidualEquation("resv") + fc.set_equation("2*I") + fc.set_residual_equation("resv") chiv = fc.residual() assert dot(chiv, chiv) == pytest.approx( sum((2 * xobs - yobs) ** 2) / sum(yobs**2) ) # Make a custom residual. - fc.setResidualEquation("abs(eq-y)**0.5") + fc.set_residual_equation("abs(eq-y)**0.5") chiv = fc.residual() assert dot(chiv, chiv) == pytest.approx(sum(abs(2 * xobs - yobs))) # Test configuration checks fc1 = FitContribution("test1") with pytest.raises(SrFitError): - fc1.setResidualEquation("chiv") - fc1.setProfile(profile) + fc1.set_residual_equation("chiv") + fc1.set_profile(profile) with pytest.raises(SrFitError): - fc1.setResidualEquation("chiv") - fc1.setEquation("A * x") - fc1.setResidualEquation("chiv") + fc1.set_residual_equation("chiv") + fc1.set_equation("A * x") + fc1.set_residual_equation("chiv") assert noObserversInGlobalBuilders return -def test_setEquation(noObserversInGlobalBuilders): +def test_set_equation(noObserversInGlobalBuilders): """Check replacement of removed parameters.""" fc = FitContribution("test") - fc.setEquation("x + 5") + fc.set_equation("x + 5") fc.x.setValue(2) assert 7 == fc.evaluate() fc.removeParameter(fc.x) @@ -284,12 +306,12 @@ def test_setEquation(noObserversInGlobalBuilders): return -def test_getEquation(noObserversInGlobalBuilders): +def test_get_equation(noObserversInGlobalBuilders): """Check getting the current profile simulation formula.""" fc = FitContribution("test") - assert "" == fc.getEquation() - fc.setEquation("A * sin(x + 5)") - assert "(A * sin((x + 5)))" == fc.getEquation() + assert "" == fc.get_equation() + fc.set_equation("A * sin(x + 5)") + assert "(A * sin((x + 5)))" == fc.get_equation() assert noObserversInGlobalBuilders return diff --git a/tests/test_fitrecipe.py b/tests/test_fitrecipe.py index 1a2b236..cebe381 100644 --- a/tests/test_fitrecipe.py +++ b/tests/test_fitrecipe.py @@ -38,8 +38,8 @@ def setUp(self): # Set up the FitContribution self.fitcontribution = FitContribution("cont") - self.fitcontribution.setProfile(self.profile) - self.fitcontribution.setEquation("A*sin(k*x + c)") + self.fitcontribution.set_profile(self.profile) + self.fitcontribution.set_equation("A*sin(k*x + c)") self.fitcontribution.A.setValue(1) self.fitcontribution.k.setValue(1) self.fitcontribution.c.setValue(0) @@ -226,12 +226,12 @@ def testResidual(self): # Now try to use the observed profile inside of the equation # Set the equation equal to the data - self.fitcontribution.setEquation("y") + self.fitcontribution.set_equation("y") res = self.recipe.residual() self.assertAlmostEqual(0, dot(res, res)) # Now add the uncertainty. This should give dy/dy = 1 for the residual - self.fitcontribution.setEquation("y+dy") + self.fitcontribution.set_equation("y+dy") res = self.recipe.residual() self.assertAlmostEqual(len(res), dot(res, res)) @@ -255,8 +255,8 @@ def testPrintFitHook(capturestdout): # Set up the FitContribution fitcontribution = FitContribution("cont") - fitcontribution.setProfile(profile) - fitcontribution.setEquation("A*sin(k*x + c)") + fitcontribution.set_profile(profile) + fitcontribution.set_equation("A*sin(k*x + c)") fitcontribution.A.setValue(1) fitcontribution.k.setValue(1) fitcontribution.c.setValue(0) diff --git a/tests/test_profilegenerator.py b/tests/test_profilegenerator.py index 6e42e39..14612a9 100644 --- a/tests/test_profilegenerator.py +++ b/tests/test_profilegenerator.py @@ -30,7 +30,7 @@ def setUp(self): self.profile = Profile() x = arange(0, 10, 0.1) self.profile.setCalculationPoints(x) - self.gen.setProfile(self.profile) + self.gen.set_profile(self.profile) return def testOperation(self): @@ -69,7 +69,7 @@ def testUpdate(self): x = arange(0, 8, 0.1) prof = Profile() prof.setCalculationPoints(x) - gen.setProfile(prof) + gen.set_profile(prof) self.assertTrue(gen._value is None) self.assertTrue(array_equal(x, gen.value)) return diff --git a/tests/test_sas.py b/tests/test_sas.py index ced9a82..59cb14c 100644 --- a/tests/test_sas.py +++ b/tests/test_sas.py @@ -158,7 +158,7 @@ def testGenerator2(sas_available, datafile): datainfo = loader.load(str(data)) profile = SASProfile(datainfo) - gen.setProfile(profile) + gen.set_profile(profile) gen.scale.value = 1.0 gen.radius_polar.value = 20 gen.radius_equatorial.value = 400 diff --git a/tests/test_weakrefcallable.py b/tests/test_weakrefcallable.py index 5d44d18..fd3488a 100644 --- a/tests/test_weakrefcallable.py +++ b/tests/test_weakrefcallable.py @@ -29,7 +29,7 @@ class TestWeakBoundMethod(unittest.TestCase): def setUp(self): self.f = FitContribution("f") - self.f.setEquation("7") + self.f.set_equation("7") self.w = weak_ref(self.f._eq._flush, fallback=_fallback_example) return @@ -112,7 +112,7 @@ def test_observable_deregistration(self): """Check if Observable drops dead Observer.""" f = self.f x = f.newParameter("x", 5) - f.setEquation("3 * x") + f.set_equation("3 * x") self.assertEqual(15, f.evaluate()) self.assertEqual(15, f._eq._value) # get one of the observer callables that are associated with f