Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions news/remove-custompqconfig.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
**Changed:**

* Structure conversion now returns ordinary atomic or periodic adapters,
without reading ``pdffit`` metadata. Configure PDF parameters explicitly
through the existing calculator interfaces.
* ``nometa()`` returns or converts the source adapter without a proxy.
``None`` returns the empty adapter.

**Deprecated:**

* ``NoMetaStructureAdapter``, retained for saved objects and subclasses.
Its Python constructor now emits ``DeprecationWarning``. Historical
metadata adapter classes remain importable for pickle compatibility.

**Removed:**

* The ``_customPQConfig`` bindings and Python callback dispatch, including
automatic application of structure metadata to PDF calculators.
7 changes: 2 additions & 5 deletions src/diffpy/srreal/pdfcalculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ def _defineCommonInterface(cls):
def _call_kwargs(self, structure=None, **kwargs):
"""Calculate PDF for the given structure as an (r, G) tuple.
Keyword arguments can be used to configure calculator
attributes, these override any properties that may be passed
from the structure, such as spdiameter.
attributes. Structure pdffit metadata is ignored; pass any
desired settings explicitly.

Attributes
----------
Expand All @@ -180,9 +180,6 @@ def _call_kwargs(self, structure=None, **kwargs):
"""
setattrFromKeywordArguments(self, **kwargs)
self.eval(structure)
# apply kwargs again if structure contained any attribute
# that may affect the result.
setattrFromKeywordArguments(self, **kwargs)
rv = (self.rgrid, self.pdf)
return rv

Expand Down
5 changes: 2 additions & 3 deletions src/diffpy/srreal/structureadapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@
Routines:

createStructureAdapter -- create StructureAdapter from a Python object
nometa -- create StructureAdapter with disabled _customPQConfig method
this prevents copying of diffpy.structure pdffit metadata
to PDFCalculator object
nometa -- return or convert a StructureAdapter without a proxy;
structure metadata no longer configures calculators
nosymmetry -- create StructureAdapter with disabled symmetry expansion.

Constants:
Expand Down
97 changes: 7 additions & 90 deletions src/diffpy/srreal/structureconverters.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,107 +43,24 @@ def convertDiffPyStructure(stru):
"""Adapt Structure class from diffpy.structure package."""
haslattice = (1, 1, 1, 90, 90, 90) != stru.lattice.abcABG()
isperiodic = haslattice
hasmeta = _DiffPyStructureMetadata.hasMetadata(stru)
if hasmeta:
if isperiodic:
adpt = DiffPyStructurePeriodicAdapter()
else:
adpt = DiffPyStructureAtomicAdapter()
adpt._fetchMetadata(stru)
else:
if isperiodic:
adpt = PeriodicStructureAdapter()
else:
adpt = AtomicStructureAdapter()
adpt = (
PeriodicStructureAdapter() if isperiodic else AtomicStructureAdapter()
)
_fetchDiffPyStructureData(adpt, stru)
return adpt


# Adapter classes and helpers for diffpy.structure class ---------------------


class _DiffPyStructureMetadata(object):
"""Base class for handling metadata information in the pdffit
attribute."""

pdffit = None

@staticmethod
def hasMetadata(stru):
"""True if Structure object carries data in its pdffit
attribute."""
rv = hasattr(stru, "pdffit") and bool(stru.pdffit)
return rv

def _customPQConfig(self, pqobj):
"""Apply PDF-related metadata if defined in PDFFit structure
format."""
pqname = type(pqobj).__name__
if pqname not in ("PDFCalculator", "DebyePDFCalculator"):
return
if not self.pdffit:
return
# scale
envtps = pqobj.usedenvelopetypes
if "scale" not in envtps:
pqobj.addEnvelope("scale")
pqobj.scale = self.pdffit["scale"]
# spdiameter
if "spdiameter" in self.pdffit:
if "sphericalshape" not in envtps:
pqobj.addEnvelope("sphericalshape")
pqobj.spdiameter = self.pdffit["spdiameter"]
# stepcut
if "stepcut" in self.pdffit:
if "stepcut" not in envtps:
pqobj.addEnvelope("stepcut")
pqobj.stepcut = self.pdffit["stepcut"]
# delta1, delta2 - set these only when using JeongPeakWidth model
if pqobj.peakwidthmodel.type() == "jeong":
pqobj.delta1 = self.pdffit["delta1"]
pqobj.delta2 = self.pdffit["delta2"]
return

def _fetchMetadata(self, stru):
"""Copy data from the pdffit attribute of diffpy Structure
object.

Attributes
----------
stru
instance of Structure class from diffpy.structure

No return value.
"""
# get PDF-related metadata
self.pdffit = {}
if self.hasMetadata(stru):
self.pdffit.update(scale=1.0, delta1=0.0, delta2=0.0)
self.pdffit.update(stru.pdffit)
return


# end of class _DiffPyStructureMetadata


def _installDiffPyStructureMetadata(cls):
"""Install diffpy.structure metadata hooks without multiple
inheritance."""
cls.pdffit = _DiffPyStructureMetadata.pdffit
cls.hasMetadata = staticmethod(_DiffPyStructureMetadata.hasMetadata)
cls._customPQConfig = _DiffPyStructureMetadata._customPQConfig
cls._fetchMetadata = _DiffPyStructureMetadata._fetchMetadata
return cls


@_installDiffPyStructureMetadata
# Keep the historical class paths so saved adapters can still be restored.
# Their pdffit state, if present in a pickle, is inert.
class DiffPyStructureAtomicAdapter(AtomicStructureAdapter):
pass
"""Legacy adapter retained for pickle compatibility."""


@_installDiffPyStructureMetadata
class DiffPyStructurePeriodicAdapter(PeriodicStructureAdapter):
pass
"""Legacy adapter retained for pickle compatibility."""


def _fetchDiffPyStructureData(adpt, stru):
Expand Down
34 changes: 1 addition & 33 deletions src/extensions/wrap_AtomicStructureAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ class AtomPickleSuite : public SerializationPickleSuite<Atom>
}
};

// template wrapper class for overloading of clone and _customPQConfig
// template wrapper class for overloading of clone and diff

template <class T>
class MakeWrapper :
Expand All @@ -368,17 +368,6 @@ class MakeWrapper :
}


void customPQConfig(PairQuantity* pq) const override
{
NB_OVERRIDE_NAME("_customPQConfig", customPQConfig, pq);
}

void default_customPQConfig(PairQuantity* pq) const
{
this->T::customPQConfig(pq);
}


StructureDifference diff(StructureAdapterConstPtr other) const override
{
nb::gil_scoped_acquire gil;
Expand Down Expand Up @@ -428,14 +417,6 @@ StructureAdapterPtr atomadapter_clone(const T& self)
return wrapper ? wrapper->default_clone() : self.clone();
}

template <class T>
void atomadapter_customPQConfig(const T& self, PairQuantity* pq)
{
auto* wrapper = dynamic_cast<const MakeWrapper<T>*>(&self);
if (wrapper) wrapper->default_customPQConfig(pq);
else self.customPQConfig(pq);
}

// Wrapper helpers for class AtomicStructureAdapter

typedef MakeWrapper<AtomicStructureAdapter> AtomicStructureAdapterWrap;
Expand Down Expand Up @@ -730,7 +711,6 @@ void prepare_structure_load(diffpy::srreal::StructureAdapter& adapter)
// declare shared docstrings from wrap_StructureAdapter.cpp

extern const char* doc_StructureAdapter___init__fromstring;
extern const char* doc_StructureAdapter__customPQConfig;
extern const char* doc_StructureAdapter_diff;

// Wrapper definitions -------------------------------------------------------
Expand Down Expand Up @@ -823,10 +803,6 @@ void wrap_AtomicStructureAdapter(nb::module_& m)
.def("clone",
atomadapter_clone<AtomicStructureAdapter>,
doc_AtomicStructureAdapter_clone)
.def("_customPQConfig",
atomadapter_customPQConfig<AtomicStructureAdapter>,
nb::arg("pqobj"),
doc_StructureAdapter__customPQConfig)
.def("diff",
atomadapter_diff<AtomicStructureAdapter>,
nb::arg("other").none(),
Expand Down Expand Up @@ -873,10 +849,6 @@ void wrap_AtomicStructureAdapter(nb::module_& m)
.def("clone",
atomadapter_clone<PeriodicStructureAdapter>,
doc_PeriodicStructureAdapter_clone)
.def("_customPQConfig",
atomadapter_customPQConfig<PeriodicStructureAdapter>,
nb::arg("pqobj"),
doc_StructureAdapter__customPQConfig)
.def("diff",
atomadapter_diff<PeriodicStructureAdapter>,
nb::arg("other").none(),
Expand Down Expand Up @@ -916,10 +888,6 @@ void wrap_AtomicStructureAdapter(nb::module_& m)
.def("clone",
atomadapter_clone<CrystalStructureAdapter>,
doc_CrystalStructureAdapter_clone)
.def("_customPQConfig",
atomadapter_customPQConfig<CrystalStructureAdapter>,
nb::arg("pqobj"),
doc_StructureAdapter__customPQConfig)
.def("diff",
atomadapter_diff<CrystalStructureAdapter>,
nb::arg("other").none(),
Expand Down
66 changes: 16 additions & 50 deletions src/extensions/wrap_StructureAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*****************************************************************************/

#include <nanobind/nanobind.h>
#include <new>
#include "srreal_trampoline.hpp"
#include <nanobind/stl/shared_ptr.h>

Expand Down Expand Up @@ -129,18 +130,6 @@ i -- zero-based atom site index.\n\
Return a 3 by 3 array.\n\
";

const char* doc_StructureAdapter__customPQConfig = "\
Support for optional custom configuration of the PairQuantity object.\n\
This method is called from the setStructure and eval methods of the owner\n\
PairQuantity object.\n\
\n\
pqobj -- the owner PairQuantity object. The function should check for the\n\
exact type of pqobj and apply configuration accordingly.\n\
\n\
No return value. This method can be overloaded in a derived class.\n\
No action by default.\n\
";

const char* doc_StructureAdapter_diff = "\
Evaluate difference between this and other StructureAdapter.\n\
\n\
Expand All @@ -153,14 +142,14 @@ This method can be overloaded in a derived class.\n\
";

const char* doc_NoMetaStructureAdapter = "\
StructureAdapter proxy which disables _customPQConfig method.\n\
Deprecated structure proxy retained for compatibility with saved objects.\n\
Structure metadata no longer configures calculators.\n\
";

const char* doc_NoMetaStructureAdapter_init = "\
Create proxy to StructureAdapter that disables _customPQConfig.\n\
Create a deprecated proxy. Use the source adapter directly instead.\n\
\n\
adapter -- StructureAdapter object to be proxied. The new adapter\n\
will avoid calling of adapter._customPQConfig method.\n\
adapter -- source StructureAdapter, or None for an empty structure.\n\
";

const char* doc_NoSymmetryStructureAdapter = "\
Expand All @@ -176,13 +165,10 @@ adapter -- StructureAdapter object to be proxied. Any iteration over\n\
";

const char* doc_nometa = "\
Return a proxy to StructureAdapter with _customPQConfig method disabled.\n\
This creates a thin wrapper over a source StructureAdapter object that\n\
disables _customPQConfig.\n\
Return the structure adapter without creating a metadata proxy.\n\
\n\
stru -- StructureAdapter object or an object convertible to StructureAdapter.\n\
\n\
Return a proxy StructureAdapter with disabled _customPQConfig.\n\
Existing adapters are returned unchanged. Other supported structures are\n\
converted normally; None returns EMPTY. Structure metadata is not applied.\n\
";

const char* doc_nosymmetry = "\
Expand Down Expand Up @@ -482,19 +468,6 @@ class StructureAdapterWrap :
}


void customPQConfig(PairQuantity* pq) const override
{
if (mserialized) return mserialized->customPQConfig(pq);
NB_OVERRIDE_NAME("_customPQConfig", customPQConfig, pq);
}

void default_customPQConfig(PairQuantity* pq) const
{
if (mserialized) return mserialized->customPQConfig(pq);
this->StructureAdapter::customPQConfig(pq);
}


StructureDifference diff(StructureAdapterConstPtr other) const override
{
nb::gil_scoped_acquire gil;
Expand Down Expand Up @@ -573,13 +546,6 @@ BaseBondGeneratorPtr createBondGenerator_shared(StructureAdapterPtr adpt)
return adpt->createBondGenerator();
}

void customPQConfig_dispatch(const StructureAdapter& adpt, PairQuantity* pq)
{
auto* wrap = dynamic_cast<const StructureAdapterWrap*>(&adpt);
if (wrap) wrap->default_customPQConfig(pq);
else adpt.customPQConfig(pq);
}


template <class T>
class StructureProxyPickleSuite
Expand Down Expand Up @@ -681,10 +647,6 @@ void wrap_StructureAdapter(nb::module_& m)
.def("siteCartesianUij",
siteCartesianUij_safe,
doc_StructureAdapter_siteCartesianUij)
.def("_customPQConfig",
customPQConfig_dispatch,
nb::arg("pqobj"),
doc_StructureAdapter__customPQConfig)
.def("diff",
structure_diff_shared,
nb::arg("other").none(),
Expand All @@ -698,8 +660,14 @@ void wrap_StructureAdapter(nb::module_& m)
nb::class_<NoMetaStructureAdapter, StructureAdapter> nometastructureadapter(m,
"NoMetaStructureAdapter", doc_NoMetaStructureAdapter);
nometastructureadapter
.def(nb::init<StructureAdapterPtr>(), nb::arg("adapter").none(),
doc_NoMetaStructureAdapter_init)
.def("__init__", [](NoMetaStructureAdapter* self, StructureAdapterPtr source) {
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"NoMetaStructureAdapter is deprecated; use the source "
"adapter directly. Structure metadata no longer "
"configures calculators.", 1) < 0)
nb::raise_python_error();
new (self) NoMetaStructureAdapter(source);
}, nb::arg("adapter").none(), doc_NoMetaStructureAdapter_init)
;
StructureProxyPickleSuite<NoMetaStructureAdapter>::bind(nometastructureadapter);

Expand Down Expand Up @@ -734,8 +702,6 @@ void wrap_StructureAdapter(nb::module_& m)

const char* doc_StructureAdapter___init__fromstring =
nswrap_StructureAdapter::doc_StructureAdapter___init__fromstring;
const char* doc_StructureAdapter__customPQConfig =
nswrap_StructureAdapter::doc_StructureAdapter__customPQConfig;
const char* doc_StructureAdapter_diff =
nswrap_StructureAdapter::doc_StructureAdapter_diff;

Expand Down
Loading
Loading