diff --git a/LICENSE_DANSE.rst b/LICENSE_DANSE.rst index c92ca2d5..9e65c741 100644 --- a/LICENSE_DANSE.rst +++ b/LICENSE_DANSE.rst @@ -6,7 +6,7 @@ the City of New York. All rights reserved. For more information please visit the diffpy web-page at http://www.diffpy.org -or email Prof. Simon Billinge at sb2896@columbia.edu. +or email Prof. Simon Billinge at sbillinge@ucsb.edu. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/docs/examples/coreshellnp.py b/docs/examples/coreshellnp.py index b175ade3..21ff0117 100644 --- a/docs/examples/coreshellnp.py +++ b/docs/examples/coreshellnp.py @@ -54,13 +54,13 @@ def makeRecipe(stru1, stru2, datname): # The generator for the CdS core. We call it "G_CdS" and will use this name # later when we set the fitting equation in the FitContribution. generator_cds = PDFGenerator("G_CdS") - generator_cds.setStructure(stru1) - generator_cds.setQmax(26) + generator_cds.set_structure(stru1) + generator_cds.set_qmax(26) generator_cds.qdamp.value = 0.0396 # The generator for the ZnS shell. We call it "G_ZnS". generator_zns = PDFGenerator("G_ZnS") - generator_zns.setStructure(stru2) - generator_zns.setQmax(26) + generator_zns.set_structure(stru2) + generator_zns.set_qmax(26) generator_zns.qdamp.value = 0.0396 # The FitContribution diff --git a/docs/examples/crystalpdf.py b/docs/examples/crystalpdf.py index c0d26805..f297416d 100644 --- a/docs/examples/crystalpdf.py +++ b/docs/examples/crystalpdf.py @@ -61,15 +61,15 @@ def makeRecipe(ciffile, datname): # The ProfileGenerator # The PDFGenerator is for configuring and calculating a PDF profile. Here, # we want to refine a Structure object from diffpy.structure. We tell the - # PDFGenerator that with the 'setStructure' method. All other configuration - # options will be inferred from the metadata that is read by the - # PDFParser. + # PDFGenerator that with the 'set_structure' method. All other + # configuration options will be inferred from the metadata that is read by + # the PDFParser. # In particular, this will set the scattering type (x-ray or neutron), the # Qmax value, as well as initial values for the non-structural Parameters. generator = PDFGenerator("G") stru = Structure() stru.read(str(ciffile)) - generator.setStructure(stru) + generator.set_structure(stru) # The FitContribution # Here we associate the Profile and ProfileGenerator, as has been done diff --git a/docs/examples/crystalpdfall.py b/docs/examples/crystalpdfall.py index 178e1d33..ef2af79a 100644 --- a/docs/examples/crystalpdfall.py +++ b/docs/examples/crystalpdfall.py @@ -68,22 +68,22 @@ def makeRecipe( # We create one for each phase and share the phases. xgenerator_ni = PDFGenerator("xG_ni") stru = create_crystal_from_cif(str(ciffile_ni)) - xgenerator_ni.setStructure(stru) + xgenerator_ni.set_structure(stru) phase_ni = xgenerator_ni.phase xgenerator_si = PDFGenerator("xG_si") stru = create_crystal_from_cif(str(ciffile_si)) - xgenerator_si.setStructure(stru) + xgenerator_si.set_structure(stru) phase_si = xgenerator_si.phase ngenerator_ni = PDFGenerator("nG_ni") - ngenerator_ni.setPhase(phase_ni) + ngenerator_ni.set_structure_from_parset(phase_ni) xgenerator_sini_ni = PDFGenerator("xG_sini_ni") - xgenerator_sini_ni.setPhase(phase_ni) + xgenerator_sini_ni.set_structure_from_parset(phase_ni) xgenerator_sini_si = PDFGenerator("xG_sini_si") - xgenerator_sini_si.setPhase(phase_si) + xgenerator_sini_si.set_structure_from_parset(phase_si) # The FitContributions # We one of these for each data set. diff --git a/docs/examples/crystalpdfobjcryst.py b/docs/examples/crystalpdfobjcryst.py index 0896a6dd..e661e6ad 100644 --- a/docs/examples/crystalpdfobjcryst.py +++ b/docs/examples/crystalpdfobjcryst.py @@ -57,8 +57,8 @@ def makeRecipe(ciffile, datname): # the previous example. generator = PDFGenerator("G") stru = create_crystal_from_cif(str(ciffile)) - generator.setStructure(stru) - generator.setQmax(40.0) + generator.set_structure(stru) + generator.set_qmax(40.0) # The FitContribution contribution = FitContribution("nickel") @@ -73,7 +73,7 @@ def makeRecipe(ciffile, datname): # As before, we get a handle to the structure parameter set. In this case, # it is a ObjCrystCrystalParSet instance that was created when we called - # 'setStructure' above. The ObjCrystCrystalParSet has different Parameters + # 'set_structure' above. The ObjCrystCrystalParSet has different Parameters # and options than the DiffpyStructureParSet used in the last example. See # its documentation in diffpy.srfit.structure.objcrystparset. phase = generator.phase diff --git a/docs/examples/crystalpdftwodata.py b/docs/examples/crystalpdftwodata.py index 0eb90375..7188dae5 100644 --- a/docs/examples/crystalpdftwodata.py +++ b/docs/examples/crystalpdftwodata.py @@ -60,7 +60,7 @@ def makeRecipe(ciffile, xdatname, ndatname): # We need one of these for the x-ray data. xgenerator = PDFGenerator("G") stru = create_crystal_from_cif(str(ciffile)) - xgenerator.setStructure(stru) + xgenerator.set_structure(stru) # And we need one for the neutron data. We want to refine the same # structure object in each PDFGenerator. This would suggest that we add the @@ -79,7 +79,7 @@ def makeRecipe(ciffile, xdatname, ndatname): # Tell the neutron PDFGenerator to use the phase from the x-ray # PDFGenerator. ngenerator = PDFGenerator("G") - ngenerator.setPhase(xgenerator.phase) + ngenerator.set_structure_from_parset(xgenerator.phase) # The FitContributions # We associate the x-ray PDFGenerator and Profile in one FitContribution... diff --git a/docs/examples/crystalpdftwophase.py b/docs/examples/crystalpdftwophase.py index 161bbf65..afcfc549 100644 --- a/docs/examples/crystalpdftwophase.py +++ b/docs/examples/crystalpdftwophase.py @@ -62,11 +62,11 @@ def makeRecipe(niciffile, siciffile, datname): # name later when we set the fitting equation in the FitContribution. generator_ni = PDFGenerator("G_ni") stru = create_crystal_from_cif(str(niciffile)) - generator_ni.setStructure(stru) + generator_ni.set_structure(stru) # The generator for the silicon phase. We call it "G_si". generator_si = PDFGenerator("G_si") stru = create_crystal_from_cif(str(siciffile)) - generator_si.setStructure(stru) + generator_si.set_structure(stru) # The FitContribution # Add both generators to the FitContribution. Add the Profile. This will diff --git a/docs/examples/nppdfcrystal.py b/docs/examples/nppdfcrystal.py index 0911754d..fbd27d76 100644 --- a/docs/examples/nppdfcrystal.py +++ b/docs/examples/nppdfcrystal.py @@ -52,9 +52,9 @@ def makeRecipe(ciffile, grdata): pdfcontribution.set_profile(pdfprofile, xname="r") pdfgenerator = PDFGenerator("G") - pdfgenerator.setQmax(30.0) + pdfgenerator.set_qmax(30.0) stru = create_crystal_from_cif(str(ciffile)) - pdfgenerator.setStructure(stru) + pdfgenerator.set_structure(stru) pdfcontribution.add_profile_generator(pdfgenerator) # Register the nanoparticle shape factor. diff --git a/docs/examples/nppdfobjcryst.py b/docs/examples/nppdfobjcryst.py index 8367d1ca..82b7413d 100644 --- a/docs/examples/nppdfobjcryst.py +++ b/docs/examples/nppdfobjcryst.py @@ -44,10 +44,10 @@ def makeRecipe(molecule, datname): # The ProfileGenerator # Create a DebyePDFGenerator named "G". generator = DebyePDFGenerator("G") - generator.setStructure(molecule) + generator.set_structure(molecule) # These are metadata needed by the generator - generator.setQmin(0.68) - generator.setQmax(22) + generator.set_qmin(0.68) + generator.set_qmax(22) # The FitContribution contribution = FitContribution("bucky") diff --git a/docs/examples/nppdfsas.py b/docs/examples/nppdfsas.py index ea049ec7..780934f6 100644 --- a/docs/examples/nppdfsas.py +++ b/docs/examples/nppdfsas.py @@ -57,9 +57,9 @@ def makeRecipe(ciffile, grdata, iqdata): pdfcontribution.set_profile(pdfprofile, xname="r") pdfgenerator = PDFGenerator("G") - pdfgenerator.setQmax(30.0) + pdfgenerator.set_qmax(30.0) stru = create_crystal_from_cif(str(ciffile)) - pdfgenerator.setStructure(stru) + pdfgenerator.set_structure(stru) pdfcontribution.add_profile_generator(pdfgenerator) pdfcontribution.set_residual_equation("resv") diff --git a/docs/examples/parallel_refinement.py b/docs/examples/parallel_refinement.py index 08bb31b3..63f0bd30 100644 --- a/docs/examples/parallel_refinement.py +++ b/docs/examples/parallel_refinement.py @@ -45,14 +45,15 @@ def make_recipe(ciffile, datname): # The ProfileGenerator # The PDFGenerator is for configuring and calculating a PDF profile. Here, # we want to refine a Structure object from diffpy.structure. We tell the - # PDFGenerator that with the 'setStructure' method. All other configuration - # options will be inferred from the metadata that is read by the PDFParser. + # PDFGenerator that with the 'set_structure' method. All other + # configuration options will be inferred from the metadata that is read by + # the PDFParser. # In particular, this will set the scattering type (x-ray or neutron), the # Qmax value, as well as initial values for the non-structural Parameters. generator = PDFGenerator("G") stru = Structure() stru.read(ciffile) - generator.setStructure(stru) + generator.set_structure(stru) # The FitContribution # Here we associate the Profile and ProfileGenerator, as has been done diff --git a/docs/examples/simplepdf.py b/docs/examples/simplepdf.py index 9815b2a7..c0477206 100644 --- a/docs/examples/simplepdf.py +++ b/docs/examples/simplepdf.py @@ -34,13 +34,13 @@ 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.load_data(datname) contribution.set_calculation_range(xmin=1, xmax=20, dx=0.1) # and the phase stru = Structure() stru.read(str(ciffile)) - contribution.addStructure("nickel", stru) + contribution.add_structure(stru, "nickel") # Make the FitRecipe and add the FitContribution. recipe = FitRecipe() diff --git a/docs/examples/simplepdftwophase.py b/docs/examples/simplepdftwophase.py index 9889b44f..41561bed 100644 --- a/docs/examples/simplepdftwophase.py +++ b/docs/examples/simplepdftwophase.py @@ -30,14 +30,14 @@ 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.load_data(datname) contribution.set_calculation_range(xmax=20) stru = create_crystal_from_cif(str(niciffile)) - contribution.addStructure("ni", stru) + contribution.add_structure(stru, "ni") stru = create_crystal_from_cif(str(siciffile)) - contribution.addStructure("si", stru) + contribution.add_structure(stru, "si") # Make the FitRecipe and add the FitContribution. recipe = FitRecipe() @@ -62,7 +62,7 @@ def makeRecipe(niciffile, siciffile, datname): # # 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 + # created by the PDFContribution. We selected this name in add_structure # above. phase_ni = contribution.ni.phase for par in phase_ni.sgpars: diff --git a/docs/source/api/diffpy.srfit.pdf.rst b/docs/source/api/diffpy.srfit.pdf.rst index 424c7f16..ca2f4290 100644 --- a/docs/source/api/diffpy.srfit.pdf.rst +++ b/docs/source/api/diffpy.srfit.pdf.rst @@ -3,6 +3,10 @@ diffpy.srfit.pdf package ======================== +.. deprecated:: 3.5.0 + ``diffpy.srfit.pdf`` has moved to ``diffpy.cmipdf`` and will be removed + in version 4.0.0. Please use ``diffpy.cmipdf`` instead. + .. automodule:: diffpy.srfit.pdf :members: :undoc-members: diff --git a/news/pdf-dep.rst b/news/pdf-dep.rst new file mode 100644 index 00000000..fee2b63b --- /dev/null +++ b/news/pdf-dep.rst @@ -0,0 +1,24 @@ +**Added:** + +* ``set_qmax``, ``get_qmax``, ``set_qmin``, ``get_qmin``, ``set_scattering_type``, ``get_scattering_type``, ``set_structure`` and ``set_structure_from_parset`` to the PDF generators, and ``load_data``, ``set_calculation_range``, ``add_structure``, ``add_structure_from_parset``, ``set_qmax``, ``get_qmax``, ``set_qmin``, ``get_qmin``, ``set_scattering_type`` and ``get_scattering_type`` to ``PDFContribution``, which take the names they have in ``diffpy.cmipdf``. + +**Changed:** + +* The deprecation messages of the camelCase characteristic functions (``sphericalCF``, ``shellCF`` and the others) now point to ``diffpy.cmipdf.characteristicfunctions`` instead of ``diffpy.srfit.pdf.characteristicfunctions``. ``lognormalSphericalCF`` now points to ``lognormal_spherical_distribution``, and ``shellCF`` and ``shellCF2`` now point to ``spherical_shell``. + +**Deprecated:** + +* ``diffpy.srfit.pdf``, which moved to ``diffpy.cmipdf``. Importing it now raises a ``DeprecationWarning``. +* The camelCase methods of the PDF generators and ``PDFContribution`` (``setQmax``, ``getQmax``, ``setQmin``, ``getQmin``, ``setScatteringType``, ``getScatteringType``, ``setStructure``, ``setPhase``, ``loadData``, ``setCalculationRange``, ``addStructure`` and ``addPhase``). Please use their snake_case names in ``diffpy.cmipdf`` instead. ``setPhase`` and ``addPhase`` are now ``set_structure_from_parset`` and ``add_structure_from_parset``, and ``add_structure`` and ``add_structure_from_parset`` take the structure or parset before the name. + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/src/diffpy/srfit/pdf/__init__.py b/src/diffpy/srfit/pdf/__init__.py index cde4d163..70a6e16e 100644 --- a/src/diffpy/srfit/pdf/__init__.py +++ b/src/diffpy/srfit/pdf/__init__.py @@ -16,9 +16,26 @@ __all__ = ["PDFGenerator", "DebyePDFGenerator", "PDFContribution", "PDFParser"] +import warnings + from diffpy.srfit.pdf.debyepdfgenerator import DebyePDFGenerator from diffpy.srfit.pdf.pdfcontribution import PDFContribution from diffpy.srfit.pdf.pdfgenerator import PDFGenerator from diffpy.srfit.pdf.pdfparser import PDFParser +from diffpy.utils._deprecator import build_deprecation_message + +removal_version = "4.0.0" + +warnings.warn( + build_deprecation_message( + "diffpy.srfit", + "pdf", + "cmipdf", + removal_version, + new_base="diffpy", + ), + DeprecationWarning, + stacklevel=2, +) # End of file diff --git a/src/diffpy/srfit/pdf/basepdfgenerator.py b/src/diffpy/srfit/pdf/basepdfgenerator.py index 653368a8..79a0f08e 100644 --- a/src/diffpy/srfit/pdf/basepdfgenerator.py +++ b/src/diffpy/srfit/pdf/basepdfgenerator.py @@ -26,6 +26,42 @@ from diffpy.srfit.fitbase import ProfileGenerator from diffpy.srfit.fitbase.parameter import ParameterAdapter from diffpy.srfit.structure import structure_to_parameter_set +from diffpy.utils._deprecator import build_deprecation_message, deprecated + +removal_version = "4.0.0" +generator_base = "diffpy.srfit.pdf.basepdfgenerator.BasePDFGenerator" +generator_new_base = "diffpy.cmipdf.basepdfgenerator.BasePDFGenerator" + + +def _build_generator_dep_msg(old_name, new_name): + message = build_deprecation_message( + generator_base, + old_name, + new_name, + removal_version, + new_base=generator_new_base, + ) + return message + + +setScatteringType_dep_msg = _build_generator_dep_msg( + "setScatteringType", "set_scattering_type" +) +getScatteringType_dep_msg = _build_generator_dep_msg( + "getScatteringType", "get_scattering_type" +) +setQmax_dep_msg = _build_generator_dep_msg("setQmax", "set_qmax") +getQmax_dep_msg = _build_generator_dep_msg("getQmax", "get_qmax") +setQmin_dep_msg = _build_generator_dep_msg("setQmin", "set_qmin") +getQmin_dep_msg = _build_generator_dep_msg("getQmin", "get_qmin") +setStructure_dep_msg = ( + _build_generator_dep_msg("setStructure", "set_structure") + + " Additionally, the signature has changed. Please pass the parameter " + "'stru' as 'structure'." +) +setPhase_dep_msg = _build_generator_dep_msg( + "setPhase", "set_structure_from_parset" +) # FIXME - Parameter creation will have to be smarter once deeper calculator # configuration is enabled. @@ -73,13 +109,13 @@ class BasePDFGenerator(ProfileGenerator): --------------- stype The scattering type "X" for x-ray, "N" for neutron (see - 'setScatteringType'). + 'set_scattering_type'). qmax The maximum scattering vector used to generate the PDF (see - setQmax). + set_qmax). qmin The minimum scattering vector used to generate the PDF (see - setQmin). + set_qmin). scale See Managed Parameters. delta1 @@ -165,15 +201,15 @@ def _process_metadata(self): stype = self.meta.get("stype") if stype is not None: - self.setScatteringType(stype) + self.set_scattering_type(stype) qmax = self.meta.get("qmax") if qmax is not None: - self.setQmax(qmax) + self.set_qmax(qmax) qmin = self.meta.get("qmin") if qmin is not None: - self.setQmin(qmin) + self.set_qmin(qmin) for name in self.__class__._parnames: val = self.meta.get(name) @@ -183,7 +219,7 @@ def _process_metadata(self): return - def setScatteringType(self, stype="X"): + def set_scattering_type(self, stype="X"): """Set the scattering type. Parameters @@ -200,22 +236,45 @@ def setScatteringType(self, stype="X"): """ self._calc.scatteringfactortable = stype # update the meta dictionary only if there was no exception - self.meta["stype"] = self.getScatteringType() + self.meta["stype"] = self.get_scattering_type() return - def getScatteringType(self): + @deprecated(setScatteringType_dep_msg) + def setScatteringType(self, stype="X"): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.basepdfgenerator.BasePDFGenerator.set_scattering_type + instead. + """ + return self.set_scattering_type(stype) + + def get_scattering_type(self): """Get the scattering type. - See ``setScatteringType``. + See ``set_scattering_type``. Returns ------- str The scattering type used to calculate the PDF. """ - return self._calc.getRadiationType() + scattering_type = self._calc.getRadiationType() + return scattering_type - def setQmax(self, qmax): + @deprecated(getScatteringType_dep_msg) + def getScatteringType(self): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.basepdfgenerator.BasePDFGenerator.get_scattering_type + instead. + """ + return self.get_scattering_type() + + def set_qmax(self, qmax): """Set the qmax value. Parameters @@ -224,10 +283,21 @@ def setQmax(self, qmax): The maximum scattering vector used to generate the PDF. """ self._calc.qmax = qmax - self.meta["qmax"] = self.getQmax() + self.meta["qmax"] = self.get_qmax() return - def getQmax(self): + @deprecated(setQmax_dep_msg) + def setQmax(self, qmax): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.basepdfgenerator.BasePDFGenerator.set_qmax + instead. + """ + return self.set_qmax(qmax) + + def get_qmax(self): """Get the qmax value. Returns @@ -235,9 +305,21 @@ def getQmax(self): float The maximum scattering vector used to generate the PDF. """ - return self._calc.qmax + qmax = self._calc.qmax + return qmax - def setQmin(self, qmin): + @deprecated(getQmax_dep_msg) + def getQmax(self): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.basepdfgenerator.BasePDFGenerator.get_qmax + instead. + """ + return self.get_qmax() + + def set_qmin(self, qmin): """Set the qmin value. Parameters @@ -246,10 +328,21 @@ def setQmin(self, qmin): The minimum scattering vector used to generate the PDF. """ self._calc.qmin = qmin - self.meta["qmin"] = self.getQmin() + self.meta["qmin"] = self.get_qmin() return - def getQmin(self): + @deprecated(setQmin_dep_msg) + def setQmin(self, qmin): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.basepdfgenerator.BasePDFGenerator.set_qmin + instead. + """ + return self.set_qmin(qmin) + + def get_qmin(self): """Get the qmin value. Returns @@ -257,38 +350,59 @@ def getQmin(self): float The minimum scattering vector used to generate the PDF. """ - return self._calc.qmin + qmin = self._calc.qmin + return qmin - def setStructure(self, stru, name="phase", periodic=True): + @deprecated(getQmin_dep_msg) + def getQmin(self): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.basepdfgenerator.BasePDFGenerator.get_qmin + instead. + """ + return self.get_qmin() + + def set_structure(self, structure, name="phase", periodic=True): """Set the structure that will be used to calculate the PDF. This creates a DiffpyStructureParSet, ObjCrystCrystalParSet or - ObjCrystMoleculeParSet that adapts stru to a ParameterSet interface. - See those classes (located in diffpy.srfit.structure) for how they are - used. The resulting ParameterSet will be managed by this generator. + ObjCrystMoleculeParSet that adapts the structure to a ParameterSet + interface. See those classes (located in diffpy.srfit.structure) for + how they are used. The resulting ParameterSet will be managed by this + generator. Parameters ---------- - stru + structure The diffpy.structure.Structure, pyobjcryst.crystal.Crystal or - pyobjcryst.molecule.Molecule instance to adapt (default None). + pyobjcryst.molecule.Molecule instance to adapt. name : str, optional - The name to give to the managed ParameterSet that adapts stru - (default "phase"). + The name to give to the managed ParameterSet that adapts the + structure (default "phase"). periodic : bool, optional The structure should be treated as periodic (default True). Note that some structures do not support periodicity, in which case this will have no effect on the PDF calculation. """ - # Create the ParameterSet - parset = structure_to_parameter_set(name, stru) - - # Set the phase - self.setPhase(parset, periodic) + parset = structure_to_parameter_set(name, structure) + self.set_structure_from_parset(parset, periodic) return - def setPhase(self, parset, periodic=True): + @deprecated(setStructure_dep_msg) + def setStructure(self, stru, name="phase", periodic=True): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.basepdfgenerator.BasePDFGenerator.set_structure + instead. + """ + return self.set_structure(stru, name, periodic) + + def set_structure_from_parset(self, parset, periodic=True): """Set the phase that will be used to calculate the PDF. Set the phase directly with a DiffpyStructureParSet, @@ -319,6 +433,17 @@ def setPhase(self, parset, periodic=True): self._phase.useSymmetry(periodic) return + @deprecated(setPhase_dep_msg) + def setPhase(self, parset, periodic=True): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.basepdfgenerator.BasePDFGenerator.set_structure_from_parset + instead. + """ + return self.set_structure_from_parset(parset, periodic) + def _prepare(self, r): """Prepare the calculator when a new r-value is passed.""" self._lastr = r.copy() diff --git a/src/diffpy/srfit/pdf/characteristicfunctions.py b/src/diffpy/srfit/pdf/characteristicfunctions.py index 7d5a2cf9..fd028df7 100644 --- a/src/diffpy/srfit/pdf/characteristicfunctions.py +++ b/src/diffpy/srfit/pdf/characteristicfunctions.py @@ -54,6 +54,7 @@ removal_version = "4.0.0" cf_base = "diffpy.srfit.pdf.characteristicfunctions" +cf_new_base = "diffpy.cmipdf.characteristicfunctions" def _build_dep_msg(old_name, new_name, signature_note=None): @@ -63,7 +64,7 @@ def _build_dep_msg(old_name, new_name, signature_note=None): appended to the standard message from `build_deprecation_message`. """ message = build_deprecation_message( - cf_base, old_name, new_name, removal_version + cf_base, old_name, new_name, removal_version, new_base=cf_new_base ) if signature_note is None: return message @@ -96,7 +97,7 @@ def _build_dep_msg(old_name, new_name, signature_note=None): lognormalSphericalCF_dep_msg = _build_dep_msg( "lognormalSphericalCF", - "lognormal_spherical_particle", + "lognormal_spherical_distribution", "Additionally, the signature has changed. Please pass the parameters " "'psize' and 'psig' as 'particle_diameter' and " "'particle_diameter_sigma', respectively.", @@ -109,14 +110,14 @@ def _build_dep_msg(old_name, new_name, signature_note=None): "'sthick' as 'sheet_thickness'.", ) -shellCF_dep_msg = _build_dep_msg("shellCF", "shell_particle") +shellCF_dep_msg = _build_dep_msg("shellCF", "spherical_shell") shellCF2_dep_msg = _build_dep_msg( "shellCF2", - "shell_particle", + "spherical_shell", "Additionally, the parameterization has changed. 'shellCF2' took the " "central radius 'a' and the shell thickness 'delta', while " - "'shell_particle' takes the inner radius. Please pass " + "'spherical_shell' takes the inner radius. Please pass " "radius = a - delta / 2 and thickness = delta.", ) @@ -544,7 +545,7 @@ def sphericalCF(r, psize): """This function has been deprecated and will be removed in version 4.0.0. - Please use diffpy.srfit.pdf.characteristicfunctions.spherical_particle + Please use diffpy.cmipdf.characteristicfunctions.spherical_particle instead. """ return spherical_particle(r, psize) @@ -555,7 +556,7 @@ def spheroidalCF(r, erad, prad): """This function has been deprecated and will be removed in version 4.0.0. - Please use diffpy.srfit.pdf.characteristicfunctions.spheroidal_particle + Please use diffpy.cmipdf.characteristicfunctions.spheroidal_particle instead. """ return spheroidal_particle(r, erad, prad) @@ -566,7 +567,7 @@ def spheroidalCF2(r, psize, axrat): """This function has been deprecated and will be removed in version 4.0.0. - Please use diffpy.srfit.pdf.characteristicfunctions.spheroidal_particle + Please use diffpy.cmipdf.characteristicfunctions.spheroidal_particle instead. """ return spheroidal_particle(r, psize / 2, axrat * psize / 2) @@ -578,7 +579,7 @@ def lognormalSphericalCF(r, psize, psig): 4.0.0. Please use - diffpy.srfit.pdf.characteristicfunctions.lognormal_spherical_particle + diffpy.cmipdf.characteristicfunctions.lognormal_spherical_distribution instead. """ return lognormal_spherical_particle(r, psize, psig) @@ -589,7 +590,7 @@ def sheetCF(r, sthick): """This function has been deprecated and will be removed in version 4.0.0. - Please use diffpy.srfit.pdf.characteristicfunctions.sheet_particle + Please use diffpy.cmipdf.characteristicfunctions.sheet_particle instead. """ return sheet_particle(r, sthick) @@ -600,7 +601,7 @@ def shellCF(r, radius, thickness): """This function has been deprecated and will be removed in version 4.0.0. - Please use diffpy.srfit.pdf.characteristicfunctions.shell_particle + Please use diffpy.cmipdf.characteristicfunctions.spherical_shell instead. """ return shell_particle(r, radius, thickness) @@ -611,7 +612,7 @@ def shellCF2(r, a, delta): """This function has been deprecated and will be removed in version 4.0.0. - Please use diffpy.srfit.pdf.characteristicfunctions.shell_particle + Please use diffpy.cmipdf.characteristicfunctions.spherical_shell instead. """ return shell_particle(r, a - delta / 2, delta) diff --git a/src/diffpy/srfit/pdf/debyepdfgenerator.py b/src/diffpy/srfit/pdf/debyepdfgenerator.py index 7861bcd4..7b32ff5d 100644 --- a/src/diffpy/srfit/pdf/debyepdfgenerator.py +++ b/src/diffpy/srfit/pdf/debyepdfgenerator.py @@ -23,6 +23,30 @@ __all__ = ["DebyePDFGenerator"] from diffpy.srfit.pdf.basepdfgenerator import BasePDFGenerator +from diffpy.utils._deprecator import build_deprecation_message, deprecated + +removal_version = "4.0.0" +debye_base = "diffpy.srfit.pdf.debyepdfgenerator.DebyePDFGenerator" +debye_new_base = "diffpy.cmipdf.debyepdfgenerator.DebyePDFGenerator" + +debye_setStructure_dep_msg = ( + build_deprecation_message( + debye_base, + "setStructure", + "set_structure", + removal_version, + new_base=debye_new_base, + ) + + " Additionally, the signature has changed. Please pass the parameter " + "'stru' as 'structure'." +) +debye_setPhase_dep_msg = build_deprecation_message( + debye_base, + "setPhase", + "set_structure_from_parset", + removal_version, + new_base=debye_new_base, +) class DebyePDFGenerator(BasePDFGenerator): @@ -84,31 +108,43 @@ class DebyePDFGenerator(BasePDFGenerator): See Managed Parameters. """ - def setStructure(self, stru, name="phase", periodic=False): + def set_structure(self, structure, name="phase", periodic=False): """Set the structure that will be used to calculate the PDF. This creates a DiffpyStructureParSet, ObjCrystCrystalParSet or - ObjCrystMoleculeParSet that adapts stru to a ParameterSet interface. - See those classes (located in diffpy.srfit.structure) for how they are - used. The resulting ParameterSet will be managed by this generator. + ObjCrystMoleculeParSet that adapts the structure to a ParameterSet + interface. See those classes (located in diffpy.srfit.structure) for + how they are used. The resulting ParameterSet will be managed by this + generator. Parameters ---------- - stru + structure The diffpy.structure.Structure, pyobjcryst.crystal.Crystal or - pyobjcryst.molecule.Molecule instance to adapt (default None). + pyobjcryst.molecule.Molecule instance to adapt. name : str, optional - The name to give to the managed ParameterSet that adapts stru - (default "phase"). + The name to give to the managed ParameterSet that adapts the + structure (default "phase"). periodic : bool, optional The structure should be treated as periodic (default False). Note that some structures do not support periodicity, in which case this will have no effect on the PDF calculation. """ - return BasePDFGenerator.setStructure(self, stru, name, periodic) + return BasePDFGenerator.set_structure(self, structure, name, periodic) - def setPhase(self, parset, periodic=False): + @deprecated(debye_setStructure_dep_msg) + def setStructure(self, stru, name="phase", periodic=False): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.debyepdfgenerator.DebyePDFGenerator.set_structure + instead. + """ + return self.set_structure(stru, name, periodic) + + def set_structure_from_parset(self, parset, periodic=False): """Set the phase that will be used to calculate the PDF. Set the phase directly with a DiffpyStructureParSet, @@ -124,11 +160,24 @@ def setPhase(self, parset, periodic=False): BasePDFGenerators, and have the changes in one reflect in another. periodic : bool, optional - The structure should be treated as periodic (default True). + The structure should be treated as periodic (default False). Note that some structures do not support periodicity, in which case this will be ignored. """ - return BasePDFGenerator.setPhase(self, parset, periodic) + return BasePDFGenerator.set_structure_from_parset( + self, parset, periodic + ) + + @deprecated(debye_setPhase_dep_msg) + def setPhase(self, parset, periodic=False): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.debyepdfgenerator.DebyePDFGenerator.set_structure_from_parset + instead. + """ + return self.set_structure_from_parset(parset, periodic) def __init__(self, name="pdf"): """Initialize the generator. diff --git a/src/diffpy/srfit/pdf/pdfcontribution.py b/src/diffpy/srfit/pdf/pdfcontribution.py index dc54adb3..c1379fcf 100644 --- a/src/diffpy/srfit/pdf/pdfcontribution.py +++ b/src/diffpy/srfit/pdf/pdfcontribution.py @@ -21,6 +21,48 @@ __all__ = ["PDFContribution"] from diffpy.srfit.fitbase import FitContribution, Profile +from diffpy.utils._deprecator import build_deprecation_message, deprecated + +removal_version = "4.0.0" +contribution_base = "diffpy.srfit.pdf.pdfcontribution.PDFContribution" +contribution_new_base = "diffpy.cmipdf.pdfcontribution.PDFContribution" + + +def _build_contribution_dep_msg(old_name, new_name): + message = build_deprecation_message( + contribution_base, + old_name, + new_name, + removal_version, + new_base=contribution_new_base, + ) + return message + + +loadData_dep_msg = _build_contribution_dep_msg("loadData", "load_data") +setCalculationRange_dep_msg = _build_contribution_dep_msg( + "setCalculationRange", "set_calculation_range" +) +addStructure_dep_msg = ( + _build_contribution_dep_msg("addStructure", "add_structure") + + " Additionally, the signature has changed. Please pass the structure " + "before the name, as add_structure(structure, name)." +) +addPhase_dep_msg = ( + _build_contribution_dep_msg("addPhase", "add_structure_from_parset") + + " Additionally, the signature has changed. Please pass the parset " + "before the name, as add_structure_from_parset(parset, name)." +) +setScatteringType_dep_msg = _build_contribution_dep_msg( + "setScatteringType", "set_scattering_type" +) +getScatteringType_dep_msg = _build_contribution_dep_msg( + "getScatteringType", "get_scattering_type" +) +setQmax_dep_msg = _build_contribution_dep_msg("setQmax", "set_qmax") +getQmax_dep_msg = _build_contribution_dep_msg("getQmax", "get_qmax") +setQmin_dep_msg = _build_contribution_dep_msg("setQmin", "set_qmin") +getQmin_dep_msg = _build_contribution_dep_msg("getQmin", "get_qmin") class PDFContribution(FitContribution): @@ -28,7 +70,7 @@ class PDFContribution(FitContribution): Data and phases can be added directly to the PDFContribution. Setup of constraints and restraints requires direct interaction with the generator - attributes (see setPhase). + attributes (see add_structure_from_parset). Attributes ---------- @@ -104,7 +146,7 @@ def __init__(self, name): # Data methods - def loadData(self, datafile): + def load_data(self, datafile): """Load the data from a data file. This uses the PDFParser to load the data and then passes it to @@ -124,7 +166,18 @@ def loadData(self, datafile): self.profile.load_parsed_data(parser) return - def setCalculationRange(self, xmin=None, xmax=None, dx=None): + @deprecated(loadData_dep_msg) + def loadData(self, datafile): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.pdfcontribution.PDFContribution.load_data + instead. + """ + return self.load_data(datafile) + + def set_calculation_range(self, xmin=None, xmax=None, dx=None): """Set epsilon-inclusive calculation range. Adhere to the observed ``xobs`` points when ``dx`` is the same @@ -157,6 +210,17 @@ def setCalculationRange(self, xmin=None, xmax=None, dx=None): """ return self.profile.set_calculation_range(xmin, xmax, dx) + @deprecated(setCalculationRange_dep_msg) + def setCalculationRange(self, xmin=None, xmax=None, dx=None): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.pdfcontribution.PDFContribution.set_calculation_range + instead. + """ + return self.set_calculation_range(xmin, xmax, dx) + def savetxt(self, fname, **kwargs): """Call numpy.savetxt with x, ycalc, y, dy. @@ -173,22 +237,21 @@ def savetxt(self, fname, **kwargs): # Phase methods - def addStructure(self, name, stru, periodic=True): + def add_structure(self, structure, name="phase", periodic=True): """Add a phase that goes into the PDF calculation. Parameters ---------- - name : str + structure + The diffpy.structure.Structure, pyobjcryst.crystal.Crystal or + pyobjcryst.molecule.Molecule instance to adapt. + name : str, optional A name to give the generator that will manage the PDF calculation from the passed structure. The adapted structure will be accessible via the name "phase" as an attribute of the generator, e.g. contribution.name.phase, where 'contribution' is this - contribution and 'name' is passed name. - (default), then the name will be set as "phase". - stru - The diffpy.structure.Structure, pyobjcryst.crystal.Crystal or - pyobjcryst.molecule.Molecule instance to adapt (default None). + contribution and 'name' is passed name (default "phase"). periodic : bool, optional The structure should be treated as periodic. If this is True (default), then a PDFGenerator will be used to @@ -201,7 +264,7 @@ def addStructure(self, name, stru, periodic=True): ------- ParameterSet The new phase, of the type appropriate for what was passed - in stru. + in structure. """ # Based on periodic, create the proper generator. if periodic: @@ -214,16 +277,32 @@ def addStructure(self, name, stru, periodic=True): gen = DebyePDFGenerator(name) # Set up the generator - gen.setStructure(stru, "phase", periodic) + gen.set_structure(structure, "phase", periodic) self._setup_generator(gen) return gen.phase - def addPhase(self, name, parset, periodic=True): + @deprecated(addStructure_dep_msg) + def addStructure(self, name, stru, periodic=True): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.pdfcontribution.PDFContribution.add_structure + instead. + """ + return self.add_structure(stru, name, periodic) + + def add_structure_from_parset(self, parset, name, periodic=True): """Add a phase that goes into the PDF calculation. Parameters ---------- + parset + The SrRealParSet that holds the structural information. + This can be used to share the phase between multiple + BasePDFGenerators, and have the changes in one reflect in + another. name : str A name to give the generator that will manage the PDF calculation from the passed parameter phase. The parset @@ -231,11 +310,6 @@ def addPhase(self, name, parset, periodic=True): of the generator, e.g., contribution.name.phase, where 'contribution' is this contribution and 'name' is passed name. - parset - The SrRealParSet that holds the structural information. - This can be used to share the phase between multiple - BasePDFGenerators, and have the changes in one reflect in - another. periodic : bool, optional The structure should be treated as periodic. If this is True (default), then a PDFGenerator will be used to @@ -261,16 +335,27 @@ def addPhase(self, name, parset, periodic=True): gen = DebyePDFGenerator(name) # Set up the generator - gen.setPhase(parset, periodic) + gen.set_structure_from_parset(parset, periodic) self._setup_generator(gen) return gen.phase + @deprecated(addPhase_dep_msg) + def addPhase(self, name, parset, periodic=True): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.pdfcontribution.PDFContribution.add_structure_from_parset + instead. + """ + return self.add_structure_from_parset(parset, name, periodic) + def _setup_generator(self, gen): """Setup a generator. The generator must already have a managed SrRealParSet, added - with setStructure or setPhase. + with set_structure or set_structure_from_parset. """ # Add the generator to this FitContribution self.add_profile_generator(gen) @@ -304,7 +389,7 @@ def _get_meta_value(self, kwd): val = self.profile.meta.get(kwd) return val - def setScatteringType(self, type="X"): + def set_scattering_type(self, type="X"): """Set the scattering type. Parameters @@ -319,22 +404,45 @@ def setScatteringType(self, type="X"): """ self._meta["stype"] = type for gen in self._generators.values(): - gen.setScatteringType(type) + gen.set_scattering_type(type) return - def getScatteringType(self): + @deprecated(setScatteringType_dep_msg) + def setScatteringType(self, type="X"): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.pdfcontribution.PDFContribution.set_scattering_type + instead. + """ + return self.set_scattering_type(type) + + def get_scattering_type(self): """Get the scattering type. - See ``setScatteringType``. + See ``set_scattering_type``. Returns ------- str The scattering type used to calculate the PDF. """ - return self._get_meta_value("stype") + scattering_type = self._get_meta_value("stype") + return scattering_type - def setQmax(self, qmax): + @deprecated(getScatteringType_dep_msg) + def getScatteringType(self): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.pdfcontribution.PDFContribution.get_scattering_type + instead. + """ + return self.get_scattering_type() + + def set_qmax(self, qmax): """Set the qmax value. Parameters @@ -344,10 +452,21 @@ def setQmax(self, qmax): """ self._meta["qmax"] = qmax for gen in self._generators.values(): - gen.setQmax(qmax) + gen.set_qmax(qmax) return - def getQmax(self): + @deprecated(setQmax_dep_msg) + def setQmax(self, qmax): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.pdfcontribution.PDFContribution.set_qmax + instead. + """ + return self.set_qmax(qmax) + + def get_qmax(self): """Get the qmax value. Returns @@ -355,9 +474,21 @@ def getQmax(self): float The maximum scattering vector used to generate the PDF. """ - return self._get_meta_value("qmax") + qmax = self._get_meta_value("qmax") + return qmax - def setQmin(self, qmin): + @deprecated(getQmax_dep_msg) + def getQmax(self): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.pdfcontribution.PDFContribution.get_qmax + instead. + """ + return self.get_qmax() + + def set_qmin(self, qmin): """Set the qmin value. Parameters @@ -367,10 +498,21 @@ def setQmin(self, qmin): """ self._meta["qmin"] = qmin for gen in self._generators.values(): - gen.setQmin(qmin) + gen.set_qmin(qmin) return - def getQmin(self): + @deprecated(setQmin_dep_msg) + def setQmin(self, qmin): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.pdfcontribution.PDFContribution.set_qmin + instead. + """ + return self.set_qmin(qmin) + + def get_qmin(self): """Get the qmin value. Returns @@ -378,7 +520,19 @@ def getQmin(self): float The minimum scattering vector used to generate the PDF. """ - return self._get_meta_value("qmin") + qmin = self._get_meta_value("qmin") + return qmin + + @deprecated(getQmin_dep_msg) + def getQmin(self): + """This function has been deprecated and will be removed in version + 4.0.0. + + Please use + diffpy.cmipdf.pdfcontribution.PDFContribution.get_qmin + instead. + """ + return self.get_qmin() # End of file diff --git a/src/diffpy/srfit/pdf/pdfgenerator.py b/src/diffpy/srfit/pdf/pdfgenerator.py index 7dea458f..cc83a778 100644 --- a/src/diffpy/srfit/pdf/pdfgenerator.py +++ b/src/diffpy/srfit/pdf/pdfgenerator.py @@ -64,13 +64,13 @@ class PDFGenerator(BasePDFGenerator): --------------- stype The scattering type "X" for x-ray, "N" for neutron (see - 'setScatteringType'). + 'set_scattering_type'). qmax The maximum scattering vector used to generate the PDF (see - setQmax). + set_qmax). qmin The minimum scattering vector used to generate the PDF (see - setQmin). + set_qmin). scale See Managed Parameters. delta1 diff --git a/tests/deprecated/test_pdf_deprecations.py b/tests/deprecated/test_pdf_deprecations.py new file mode 100644 index 00000000..08d5f896 --- /dev/null +++ b/tests/deprecated/test_pdf_deprecations.py @@ -0,0 +1,459 @@ +"""Tests for the deprecation of diffpy.srfit.pdf, which moved to +diffpy.cmipdf. + +Remove this file in version 4.0.0, together with diffpy.srfit.pdf. +""" + +import importlib + +import pytest + +import diffpy.srfit.pdf +from diffpy.srfit.pdf import DebyePDFGenerator, PDFContribution, PDFGenerator +from diffpy.srfit.structure.diffpyparset import DiffpyStructureParSet +from diffpy.structure import Atom, Lattice, Structure + + +@pytest.fixture +def nacl_structure(): + lattice = Lattice(5.6, 5.6, 5.6, 90, 90, 90) + atoms = [Atom("Na", [0, 0, 0]), Atom("Cl", [0.5, 0.5, 0.5])] + structure = Structure(atoms, lattice=lattice) + return structure + + +def test_pdf_package_import_warns(): + # Case: diffpy.srfit.pdf is imported. + # Expected: A DeprecationWarning points to diffpy.cmipdf. + expected_msg = ( + "'diffpy.srfit.pdf' is deprecated and will be removed in version " + "4.0.0. Please use 'diffpy.cmipdf' instead." + ) + with pytest.warns(DeprecationWarning) as record: + importlib.reload(diffpy.srfit.pdf) + actual_msg = str(record[0].message) + assert actual_msg == expected_msg + + +@pytest.mark.parametrize( + "old_setter, new_getter, input_value, expected_msg", + [ + # Test the deprecated setters of BasePDFGenerator. + # C1: setQmax sets qmax to 21. + # Expected: Warns that set_qmax in diffpy.cmipdf replaces it, and + # get_qmax returns 21. + ( + "setQmax", + "get_qmax", + 21.0, + "'diffpy.srfit.pdf.basepdfgenerator.BasePDFGenerator.setQmax' is " + "deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmipdf.basepdfgenerator.BasePDFGenerator.set_qmax' " + "instead.", + ), + # C2: setQmin sets qmin to 0.5. + # Expected: Warns that set_qmin in diffpy.cmipdf replaces it, and + # get_qmin returns 0.5. + ( + "setQmin", + "get_qmin", + 0.5, + "'diffpy.srfit.pdf.basepdfgenerator.BasePDFGenerator.setQmin' is " + "deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmipdf.basepdfgenerator.BasePDFGenerator.set_qmin' " + "instead.", + ), + # C3: setScatteringType sets the scattering type to neutron. + # Expected: Warns that set_scattering_type in diffpy.cmipdf + # replaces it, and get_scattering_type returns "N". + ( + "setScatteringType", + "get_scattering_type", + "N", + "'diffpy.srfit.pdf.basepdfgenerator.BasePDFGenerator." + "setScatteringType' is deprecated and will be removed in version " + "4.0.0. Please use 'diffpy.cmipdf.basepdfgenerator." + "BasePDFGenerator.set_scattering_type' instead.", + ), + ], +) +def test_generator_setters( + diffpy_srreal_available, old_setter, new_getter, input_value, expected_msg +): + if not diffpy_srreal_available: + pytest.skip("diffpy.srreal package not available") + generator = PDFGenerator() + with pytest.warns(DeprecationWarning) as record: + getattr(generator, old_setter)(input_value) + actual_msg = str(record[0].message) + assert actual_msg == expected_msg + actual_value = getattr(generator, new_getter)() + expected_value = input_value + assert actual_value == expected_value + + +@pytest.mark.parametrize( + "old_getter, new_getter, expected_msg", + [ + # Test the deprecated getters of BasePDFGenerator. + # C1: getQmax is called on a new generator. + # Expected: Warns that get_qmax in diffpy.cmipdf replaces it, and + # returns the same value as get_qmax. + ( + "getQmax", + "get_qmax", + "'diffpy.srfit.pdf.basepdfgenerator.BasePDFGenerator.getQmax' is " + "deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmipdf.basepdfgenerator.BasePDFGenerator.get_qmax' " + "instead.", + ), + # C2: getQmin is called on a new generator. + # Expected: Warns that get_qmin in diffpy.cmipdf replaces it, and + # returns the same value as get_qmin. + ( + "getQmin", + "get_qmin", + "'diffpy.srfit.pdf.basepdfgenerator.BasePDFGenerator.getQmin' is " + "deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmipdf.basepdfgenerator.BasePDFGenerator.get_qmin' " + "instead.", + ), + # C3: getScatteringType is called on a new generator. + # Expected: Warns that get_scattering_type in diffpy.cmipdf + # replaces it, and returns the same value as get_scattering_type. + ( + "getScatteringType", + "get_scattering_type", + "'diffpy.srfit.pdf.basepdfgenerator.BasePDFGenerator." + "getScatteringType' is deprecated and will be removed in version " + "4.0.0. Please use 'diffpy.cmipdf.basepdfgenerator." + "BasePDFGenerator.get_scattering_type' instead.", + ), + ], +) +def test_generator_getters( + diffpy_srreal_available, old_getter, new_getter, expected_msg +): + if not diffpy_srreal_available: + pytest.skip("diffpy.srreal package not available") + generator = PDFGenerator() + with pytest.warns(DeprecationWarning) as record: + actual_value = getattr(generator, old_getter)() + actual_msg = str(record[0].message) + assert actual_msg == expected_msg + expected_value = getattr(generator, new_getter)() + assert actual_value == expected_value + + +@pytest.mark.parametrize( + "generator_class, expected_periodic, expected_msg", + [ + # Test the deprecated setStructure of each PDF generator. + # C1: setStructure is called on a PDFGenerator. + # Expected: Warns that set_structure in diffpy.cmipdf replaces it + # and that 'stru' is now 'structure', and adapts the structure as + # periodic. + ( + PDFGenerator, + True, + "'diffpy.srfit.pdf.basepdfgenerator.BasePDFGenerator." + "setStructure' is deprecated and will be removed in version " + "4.0.0. Please use " + "'diffpy.cmipdf.basepdfgenerator.BasePDFGenerator.set_structure' " + "instead. Additionally, the signature has changed. Please pass " + "the parameter 'stru' as 'structure'.", + ), + # C2: setStructure is called on a DebyePDFGenerator. + # Expected: Warns that set_structure in diffpy.cmipdf replaces it + # and that 'stru' is now 'structure', and adapts the structure as + # non-periodic. + ( + DebyePDFGenerator, + False, + "'diffpy.srfit.pdf.debyepdfgenerator.DebyePDFGenerator." + "setStructure' is deprecated and will be removed in version " + "4.0.0. Please use 'diffpy.cmipdf.debyepdfgenerator." + "DebyePDFGenerator.set_structure' instead. Additionally, the " + "signature has changed. Please pass the parameter 'stru' as " + "'structure'.", + ), + ], +) +def test_setStructure( + diffpy_srreal_available, + nacl_structure, + generator_class, + expected_periodic, + expected_msg, +): + if not diffpy_srreal_available: + pytest.skip("diffpy.srreal package not available") + generator = generator_class() + with pytest.warns(DeprecationWarning) as record: + generator.setStructure(nacl_structure) + actual_msg = str(record[0].message) + assert actual_msg == expected_msg + actual_structure = generator.stru + expected_structure = nacl_structure + assert actual_structure == expected_structure + actual_periodic = generator.phase.usingSymmetry() + assert actual_periodic == expected_periodic + + +@pytest.mark.parametrize( + "generator_class, expected_periodic, expected_msg", + [ + # Test the deprecated setPhase of each PDF generator. + # C1: setPhase is called on a PDFGenerator. + # Expected: Warns that set_structure_from_parset in diffpy.cmipdf + # replaces it, and manages the parset as periodic. + ( + PDFGenerator, + True, + "'diffpy.srfit.pdf.basepdfgenerator.BasePDFGenerator.setPhase' is " + "deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmipdf.basepdfgenerator.BasePDFGenerator." + "set_structure_from_parset' instead.", + ), + # C2: setPhase is called on a DebyePDFGenerator. + # Expected: Warns that set_structure_from_parset in diffpy.cmipdf + # replaces it, and manages the parset as non-periodic. + ( + DebyePDFGenerator, + False, + "'diffpy.srfit.pdf.debyepdfgenerator.DebyePDFGenerator.setPhase' " + "is deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmipdf.debyepdfgenerator.DebyePDFGenerator." + "set_structure_from_parset' instead.", + ), + ], +) +def test_setPhase( + diffpy_srreal_available, + nacl_structure, + generator_class, + expected_periodic, + expected_msg, +): + if not diffpy_srreal_available: + pytest.skip("diffpy.srreal package not available") + generator = generator_class() + parameter_set = DiffpyStructureParSet("phase", nacl_structure) + with pytest.warns(DeprecationWarning) as record: + generator.setPhase(parameter_set) + actual_msg = str(record[0].message) + assert actual_msg == expected_msg + actual_phase = generator.phase + expected_phase = parameter_set + assert actual_phase == expected_phase + actual_periodic = generator.phase.usingSymmetry() + assert actual_periodic == expected_periodic + + +@pytest.mark.parametrize( + "old_setter, new_getter, input_value, expected_msg", + [ + # Test the deprecated setters of PDFContribution. + # C1: setQmax sets qmax to 21. + # Expected: Warns that set_qmax in diffpy.cmipdf replaces it, and + # get_qmax returns 21. + ( + "setQmax", + "get_qmax", + 21.0, + "'diffpy.srfit.pdf.pdfcontribution.PDFContribution.setQmax' is " + "deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmipdf.pdfcontribution.PDFContribution.set_qmax' " + "instead.", + ), + # C2: setQmin sets qmin to 0.5. + # Expected: Warns that set_qmin in diffpy.cmipdf replaces it, and + # get_qmin returns 0.5. + ( + "setQmin", + "get_qmin", + 0.5, + "'diffpy.srfit.pdf.pdfcontribution.PDFContribution.setQmin' is " + "deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmipdf.pdfcontribution.PDFContribution.set_qmin' " + "instead.", + ), + # C3: setScatteringType sets the scattering type to neutron. + # Expected: Warns that set_scattering_type in diffpy.cmipdf + # replaces it, and get_scattering_type returns "N". + ( + "setScatteringType", + "get_scattering_type", + "N", + "'diffpy.srfit.pdf.pdfcontribution.PDFContribution." + "setScatteringType' is deprecated and will be removed in version " + "4.0.0. Please use 'diffpy.cmipdf.pdfcontribution." + "PDFContribution.set_scattering_type' instead.", + ), + ], +) +def test_contribution_setters( + old_setter, new_getter, input_value, expected_msg +): + contribution = PDFContribution("pdf") + with pytest.warns(DeprecationWarning) as record: + getattr(contribution, old_setter)(input_value) + actual_msg = str(record[0].message) + assert actual_msg == expected_msg + actual_value = getattr(contribution, new_getter)() + expected_value = input_value + assert actual_value == expected_value + + +@pytest.mark.parametrize( + "old_getter, new_getter, expected_msg", + [ + # Test the deprecated getters of PDFContribution. + # C1: getQmax is called after qmax is set to 21. + # Expected: Warns that get_qmax in diffpy.cmipdf replaces it, and + # returns the same value as get_qmax. + ( + "getQmax", + "get_qmax", + "'diffpy.srfit.pdf.pdfcontribution.PDFContribution.getQmax' is " + "deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmipdf.pdfcontribution.PDFContribution.get_qmax' " + "instead.", + ), + # C2: getQmin is called after qmin is set to 0.5. + # Expected: Warns that get_qmin in diffpy.cmipdf replaces it, and + # returns the same value as get_qmin. + ( + "getQmin", + "get_qmin", + "'diffpy.srfit.pdf.pdfcontribution.PDFContribution.getQmin' is " + "deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmipdf.pdfcontribution.PDFContribution.get_qmin' " + "instead.", + ), + # C3: getScatteringType is called after the type is set to "N". + # Expected: Warns that get_scattering_type in diffpy.cmipdf + # replaces it, and returns the same value as get_scattering_type. + ( + "getScatteringType", + "get_scattering_type", + "'diffpy.srfit.pdf.pdfcontribution.PDFContribution." + "getScatteringType' is deprecated and will be removed in version " + "4.0.0. Please use 'diffpy.cmipdf.pdfcontribution." + "PDFContribution.get_scattering_type' instead.", + ), + ], +) +def test_contribution_getters(old_getter, new_getter, expected_msg): + contribution = PDFContribution("pdf") + contribution._meta.update({"qmax": 21.0, "qmin": 0.5, "stype": "N"}) + with pytest.warns(DeprecationWarning) as record: + actual_value = getattr(contribution, old_getter)() + actual_msg = str(record[0].message) + assert actual_msg == expected_msg + expected_value = getattr(contribution, new_getter)() + assert actual_value == expected_value + + +def test_loadData(datafile): + # Case: loadData loads a PDF data file into a PDFContribution. + # Expected: Warns that load_data in diffpy.cmipdf replaces it, and + # loads the same profile as load_data. + expected_msg = ( + "'diffpy.srfit.pdf.pdfcontribution.PDFContribution.loadData' is " + "deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmipdf.pdfcontribution.PDFContribution.load_data' instead." + ) + old_contribution = PDFContribution("pdf") + with pytest.warns(DeprecationWarning) as record: + old_contribution.loadData(datafile("si-q27r60-xray.gr")) + actual_msg = str(record[0].message) + assert actual_msg == expected_msg + new_contribution = PDFContribution("pdf") + new_contribution.load_data(datafile("si-q27r60-xray.gr")) + actual_metadata = old_contribution.profile.meta + expected_metadata = new_contribution.profile.meta + assert actual_metadata == expected_metadata + actual_xobs = old_contribution.profile.xobs.tolist() + expected_xobs = new_contribution.profile.xobs.tolist() + assert actual_xobs == expected_xobs + + +def test_setCalculationRange(datafile): + # Case: setCalculationRange limits a loaded profile to r = 0 to 10. + # Expected: Warns that set_calculation_range in diffpy.cmipdf replaces + # it, and sets the same calculation points as set_calculation_range. + expected_msg = ( + "'diffpy.srfit.pdf.pdfcontribution.PDFContribution." + "setCalculationRange' is deprecated and will be removed in version " + "4.0.0. Please use 'diffpy.cmipdf.pdfcontribution.PDFContribution." + "set_calculation_range' instead." + ) + old_contribution = PDFContribution("pdf") + old_contribution.load_data(datafile("si-q27r60-xray.gr")) + with pytest.warns(DeprecationWarning) as record: + old_contribution.setCalculationRange(0, 10) + actual_msg = str(record[0].message) + assert actual_msg == expected_msg + new_contribution = PDFContribution("pdf") + new_contribution.load_data(datafile("si-q27r60-xray.gr")) + new_contribution.set_calculation_range(0, 10) + actual_x = old_contribution.profile.x.tolist() + expected_x = new_contribution.profile.x.tolist() + assert actual_x == expected_x + + +def test_addStructure(diffpy_srreal_available, nacl_structure): + # Case: addStructure adds the structure under the name "nacl". + # Expected: Warns that add_structure in diffpy.cmipdf replaces it and + # takes the structure before the name, and adds a generator named + # "nacl" that adapts the structure. + if not diffpy_srreal_available: + pytest.skip("diffpy.srreal package not available") + expected_msg = ( + "'diffpy.srfit.pdf.pdfcontribution.PDFContribution.addStructure' is " + "deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmipdf.pdfcontribution.PDFContribution.add_structure' " + "instead. Additionally, the signature has changed. Please pass the " + "structure before the name, as add_structure(structure, name)." + ) + contribution = PDFContribution("pdf") + with pytest.warns(DeprecationWarning) as record: + contribution.addStructure("nacl", nacl_structure) + actual_msg = str(record[0].message) + assert actual_msg == expected_msg + actual_generator_names = list(contribution._generators) + expected_generator_names = ["nacl"] + assert actual_generator_names == expected_generator_names + actual_structure = contribution.nacl.stru + expected_structure = nacl_structure + assert actual_structure == expected_structure + + +def test_addPhase(diffpy_srreal_available, nacl_structure): + # Case: addPhase adds a parameter set under the name "nacl". + # Expected: Warns that add_structure_from_parset in diffpy.cmipdf + # replaces it and takes the parset before the name, and adds a + # generator named "nacl" that manages the parameter set. + if not diffpy_srreal_available: + pytest.skip("diffpy.srreal package not available") + expected_msg = ( + "'diffpy.srfit.pdf.pdfcontribution.PDFContribution.addPhase' is " + "deprecated and will be removed in version 4.0.0. Please use " + "'diffpy.cmipdf.pdfcontribution.PDFContribution." + "add_structure_from_parset' instead. Additionally, the signature has " + "changed. Please pass the parset before the name, as " + "add_structure_from_parset(parset, name)." + ) + contribution = PDFContribution("pdf") + parameter_set = DiffpyStructureParSet("phase", nacl_structure) + with pytest.warns(DeprecationWarning) as record: + contribution.addPhase("nacl", parameter_set) + actual_msg = str(record[0].message) + assert actual_msg == expected_msg + actual_generator_names = list(contribution._generators) + expected_generator_names = ["nacl"] + assert actual_generator_names == expected_generator_names + actual_phase = contribution.nacl.phase + expected_phase = parameter_set + assert actual_phase == expected_phase diff --git a/tests/test_characteristicfunctions.py b/tests/test_characteristicfunctions.py index 3654b953..ce7ef374 100644 --- a/tests/test_characteristicfunctions.py +++ b/tests/test_characteristicfunctions.py @@ -608,13 +608,15 @@ def test_non_physical_input_warns_only_once( @pytest.mark.parametrize( - "old_name, new_name, expected_signature_note, old_args, new_args", + "old_name, new_name, expected_cmipdf_name, expected_signature_note, " + "old_args, new_args", [ # C1: sphericalCF forwards its arguments unchanged, only renamed. # Expected: The note names the renamed parameter. ( "sphericalCF", "spherical_particle", + "spherical_particle", "Additionally, the signature has changed. Please pass the " "parameter 'psize' as 'particle_diameter'.", (numpy.array([0.0, 5.0, 10.0]), 10.0), @@ -625,6 +627,7 @@ def test_non_physical_input_warns_only_once( ( "spheroidalCF", "spheroidal_particle", + "spheroidal_particle", "Additionally, the signature has changed. Please pass the " "parameters 'erad' and 'prad' as 'equatorial_radius' and " "'polar_radius', respectively.", @@ -638,6 +641,7 @@ def test_non_physical_input_warns_only_once( ( "spheroidalCF2", "spheroidal_particle", + "spheroidal_particle", "Additionally, the parameterization has changed. 'spheroidalCF2' " "took the equatorial diameter 'psize' and the axis ratio " "'axrat', while 'spheroidal_particle' takes radii. Please pass " @@ -652,6 +656,7 @@ def test_non_physical_input_warns_only_once( ( "lognormalSphericalCF", "lognormal_spherical_particle", + "lognormal_spherical_distribution", "Additionally, the signature has changed. Please pass the " "parameters 'psize' and 'psig' as 'particle_diameter' and " "'particle_diameter_sigma', respectively.", @@ -663,6 +668,7 @@ def test_non_physical_input_warns_only_once( ( "sheetCF", "sheet_particle", + "sheet_particle", "Additionally, the signature has changed. Please pass the " "parameter 'sthick' as 'sheet_thickness'.", (numpy.array([0.0, 2.0, 4.0]), 4.0), @@ -673,6 +679,7 @@ def test_non_physical_input_warns_only_once( ( "shellCF", "shell_particle", + "spherical_shell", "", (numpy.array([0.0, 5.0, 12.5]), 10.0, 5.0), (numpy.array([0.0, 5.0, 12.5]), 10.0, 5.0), @@ -684,9 +691,10 @@ def test_non_physical_input_warns_only_once( ( "shellCF2", "shell_particle", + "spherical_shell", "Additionally, the parameterization has changed. 'shellCF2' took " "the central radius 'a' and the shell thickness 'delta', while " - "'shell_particle' takes the inner radius. Please pass " + "'spherical_shell' takes the inner radius. Please pass " "radius = a - delta / 2 and thickness = delta.", (numpy.array([0.0, 5.0, 12.5]), 12.5, 5.0), (numpy.array([0.0, 5.0, 12.5]), 10.0, 5.0), @@ -696,17 +704,18 @@ def test_non_physical_input_warns_only_once( def test_deprecated_functions_warn_and_forward( old_name, new_name, + expected_cmipdf_name, expected_signature_note, old_args, new_args, ): old_function = getattr(cf, old_name) new_function = getattr(cf, new_name) - module_path = "diffpy.srfit.pdf.characteristicfunctions" expected_characteristic_function = new_function(*new_args) expected_msg = ( - f"'{module_path}.{old_name}' is deprecated and will be removed " - f"in version 4.0.0. Please use '{module_path}.{new_name}' " + f"'diffpy.srfit.pdf.characteristicfunctions.{old_name}' is " + f"deprecated and will be removed in version 4.0.0. Please use " + f"'diffpy.cmipdf.characteristicfunctions.{expected_cmipdf_name}' " "instead." ) if expected_signature_note: diff --git a/tests/test_pdfcontribution.py b/tests/test_pdfcontribution.py index 509d2b8b..d2bb624e 100644 --- a/tests/test_pdfcontribution.py +++ b/tests/test_pdfcontribution.py @@ -27,10 +27,10 @@ # ---------------------------------------------------------------------------- -def test_pdfcontribution_loadData(datafile): - """LoadData passes the PDF metadata on to the built-in profile.""" +def test_pdfcontribution_load_data(datafile): + """load_data passes the PDF metadata on to the built-in profile.""" contribution = PDFContribution("pdf") - contribution.loadData(datafile("si-q27r60-xray.gr")) + contribution.load_data(datafile("si-q27r60-xray.gr")) expected_metadata = { "version": "diffpy.pdfgetx-2.4.0", @@ -58,25 +58,25 @@ def test_pdfcontribution_loadData(datafile): assert actual_point_count == expected_point_count -def test_setQmax(diffpy_srreal_available): - """Check PDFContribution.setQmax()""" +def test_set_qmax(diffpy_srreal_available): + """Check PDFContribution.set_qmax()""" from diffpy.structure import Structure if not diffpy_srreal_available: pytest.skip("diffpy.srreal package not available") pc = PDFContribution("pdf") - pc.setQmax(21) - pc.addStructure("empty", Structure()) - assert 21 == pc.empty.getQmax() - pc.setQmax(22) - assert 22 == pc.getQmax() - assert 22 == pc.empty.getQmax() + pc.set_qmax(21) + pc.add_structure(Structure(), "empty") + assert 21 == pc.empty.get_qmax() + pc.set_qmax(22) + assert 22 == pc.get_qmax() + assert 22 == pc.empty.get_qmax() return -def test_getQmax(diffpy_srreal_available): - """Check PDFContribution.getQmax()""" +def test_get_qmax(diffpy_srreal_available): + """Check PDFContribution.get_qmax()""" from diffpy.structure import Structure if not diffpy_srreal_available: @@ -85,18 +85,18 @@ def test_getQmax(diffpy_srreal_available): # cover all code branches in PDFContribution._get_meta_value # (1) contribution metadata pc1 = PDFContribution("pdf") - assert pc1.getQmax() is None - pc1.setQmax(17) - assert 17 == pc1.getQmax() + assert pc1.get_qmax() is None + pc1.set_qmax(17) + assert 17 == pc1.get_qmax() # (2) contribution metadata pc2 = PDFContribution("pdf") - pc2.addStructure("empty", Structure()) - pc2.empty.setQmax(18) - assert 18 == pc2.getQmax() + pc2.add_structure(Structure(), "empty") + pc2.empty.set_qmax(18) + assert 18 == pc2.get_qmax() # (3) profile metadata pc3 = PDFContribution("pdf") pc3.profile.meta["qmax"] = 19 - assert 19 == pc3.getQmax() + assert 19 == pc3.get_qmax() return @@ -108,9 +108,9 @@ def test_savetxt(diffpy_srreal_available, datafile): pytest.skip("diffpy.srreal package not available") pc = PDFContribution("pdf") - pc.loadData(datafile("si-q27r60-xray.gr")) - pc.setCalculationRange(0, 10) - pc.addStructure("empty", Structure()) + pc.load_data(datafile("si-q27r60-xray.gr")) + pc.set_calculation_range(0, 10) + pc.add_structure(Structure(), "empty") fp = io.BytesIO() with pytest.raises(SrFitError): pc.savetxt(fp) @@ -130,13 +130,13 @@ def test_pickling(diffpy_srreal_available, datafile): pytest.skip("diffpy.srreal package not available") pc = PDFContribution("pdf") - pc.loadData(datafile("ni-q27r100-neutron.gr")) + pc.load_data(datafile("ni-q27r100-neutron.gr")) ciffile = datafile("ni.cif") cif_path = str(ciffile) ni = load_structure(cif_path) ni.Uisoequiv = 0.003 - pc.addStructure("ni", ni) - pc.setCalculationRange(0, 10) + pc.add_structure(ni, "ni") + pc.set_calculation_range(0, 10) pc2 = pickle.loads(pickle.dumps(pc)) res0 = pc.residual() assert numpy.array_equal(res0, pc2.residual()) diff --git a/tests/test_pdfgenerator.py b/tests/test_pdfgenerator.py index cabbe6e2..d9e3355a 100644 --- a/tests/test_pdfgenerator.py +++ b/tests/test_pdfgenerator.py @@ -31,10 +31,10 @@ def testGenerator(diffpy_srreal_available, datafile): qmax = 27.0 gen = PDFGenerator() - gen.setScatteringType("N") - assert "N" == gen.getScatteringType() - gen.setQmax(qmax) - assert qmax == pytest.approx(gen.getQmax()) + gen.set_scattering_type("N") + assert "N" == gen.get_scattering_type() + gen.set_qmax(qmax) + assert qmax == pytest.approx(gen.get_qmax()) stru = PDFFitStructure() ciffile = datafile("ni.cif") @@ -42,7 +42,7 @@ def testGenerator(diffpy_srreal_available, datafile): stru.read(cif_path) for i in range(4): stru[i].Bisoequiv = 1 - gen.setStructure(stru) + gen.set_structure(stru) calc = gen._calc # Test parameters @@ -78,15 +78,15 @@ def testGenerator(diffpy_srreal_available, datafile): return -def test_setQmin(diffpy_srreal_available): +def test_set_qmin(diffpy_srreal_available): """Verify qmin is propagated to the calculator object.""" if not diffpy_srreal_available: pytest.skip("diffpy.srreal package not available") gen = PDFGenerator() - assert 0 == gen.getQmin() + assert 0 == gen.get_qmin() assert 0 == gen._calc.qmin - gen.setQmin(0.93) - assert 0.93 == gen.getQmin() + gen.set_qmin(0.93) + assert 0.93 == gen.get_qmin() assert 0.93 == gen._calc.qmin return