diff --git a/src/diffpy/srreal/structureconverters.py b/src/diffpy/srreal/structureconverters.py index 35254d3e..e504587d 100644 --- a/src/diffpy/srreal/structureconverters.py +++ b/src/diffpy/srreal/structureconverters.py @@ -142,7 +142,7 @@ def _fetchDiffPyStructureData(adpt, stru): aa = AdapterAtom() for a0 in stru: aa.atomtype = a0.element - aa.occupancy = float(a0.occupancy) + aa.occupancy = a0.occupancy aa.anisotropy = a0.anisotropy # copy fractional coordinates aa.xyz_cartn = a0.xyz diff --git a/src/diffpy/srreal/tests/teststructureadapter.py b/src/diffpy/srreal/tests/teststructureadapter.py index 66165391..9224ace9 100644 --- a/src/diffpy/srreal/tests/teststructureadapter.py +++ b/src/diffpy/srreal/tests/teststructureadapter.py @@ -599,6 +599,42 @@ def test_uij_cartn(self): self.assertEqual(0.023, a.uc23) return + def test_xc_yc_zc(self): + 'check Atom properties xc, yc, zc.' + a = self.a + a.xc, a.yc, a.zc = numpy.arange(1, 4) + self.assertEqual(1.0, a.xc) + self.assertEqual(2.0, a.yc) + self.assertEqual(3.0, a.zc) + return + + def test_occupancy(self): + 'check Atom.occupancy' + a = self.a + a.occupancy, = numpy.arange(1) + self.assertEqual(0.0, a.occupancy) + a.occupancy = numpy.float32(0.5) + self.assertEqual(0.5, a.occupancy) + return + + def test_anisotropy(self): + 'check Atom.anisotropy' + a = self.a + nptrue, npfalse = (numpy.arange(2) < 1) + a.anisotropy = nptrue + self.assertTrue(a.anisotropy) + a.anisotropy = npfalse + self.assertFalse(a.anisotropy) + return + + def test_ucij(self): + 'check Atom attributes u11, u22, etc.' + a = self.a + a.uc11, a.uc22, a.uc33, a.uc12, a.uc13, a.uc23 = numpy.arange(1, 7) + uijexp = [[1, 4, 5], [4, 2, 6], [5, 6, 3]] + self.assertTrue(numpy.array_equal(uijexp, a.uij_cartn)) + return + # End of class TestAtom # ---------------------------------------------------------------------------- diff --git a/src/extensions/srreal_converters.cpp b/src/extensions/srreal_converters.cpp index 49dc183e..37532c91 100644 --- a/src/extensions/srreal_converters.cpp +++ b/src/extensions/srreal_converters.cpp @@ -294,6 +294,25 @@ NumPyArray_DoublePtr extractNumPyDoubleArray(::boost::python::object& obj) } +/// extract double with a support for numpy.int types +double extractdouble(boost::python::object obj) +{ + using namespace boost; + python::extract getx(obj); + if (getx.check()) return getx(); + PyObject* pobj = obj.ptr(); + if (PyArray_CheckScalar(pobj)) + { + double x; + PyArray_CastScalarToCtype(pobj, &x, + PyArray_DescrFromType(NPY_DOUBLE)); + return x; + } + // nothing worked, call getx which will raise an exception + return getx(); +} + + /// extract integer with a support for numpy.int types int extractint(boost::python::object obj) { diff --git a/src/extensions/srreal_converters.hpp b/src/extensions/srreal_converters.hpp index 65da46b8..79f10c3c 100644 --- a/src/extensions/srreal_converters.hpp +++ b/src/extensions/srreal_converters.hpp @@ -395,6 +395,10 @@ extractQuantityType(::boost::python::object obj, NumPyArray_DoublePtr extractNumPyDoubleArray(::boost::python::object& obj); +/// extract double with a support for numpy numeric types +double extractdouble(::boost::python::object obj); + + /// extract integer with a support for numpy.int types int extractint(::boost::python::object obj); diff --git a/src/extensions/wrap_AtomicStructureAdapter.cpp b/src/extensions/wrap_AtomicStructureAdapter.cpp index 09cf0aa9..e3ce6b39 100644 --- a/src/extensions/wrap_AtomicStructureAdapter.cpp +++ b/src/extensions/wrap_AtomicStructureAdapter.cpp @@ -67,8 +67,11 @@ view to the data in C++ class. Do not resize or reshape.\n\ const char* doc_Atom_init_copy = "\ Make a deep copy of an existing Atom.\n\ "; -const char* doc_Atom_xic = "Vector element in xyz_cartn"; -const char* doc_Atom_uijc = "Matrix element in uij_cartn"; +const char* doc_Atom_xic = "Vector element in xyz_cartn."; +const char* doc_Atom_occ = "Fractional occupancy of this atom."; +const char* doc_Atom_anisotropy = + "Boolean flag for anisotropic displacements."; +const char* doc_Atom_uijc = "Matrix element in uij_cartn."; // class AtomicStructureAdapter @@ -270,28 +273,55 @@ void set_uij_cartn(Atom& a, object& value) } -double get_xc(const Atom& a) { return a.xyz_cartn[0]; } -void set_xc(Atom& a, double value) { a.xyz_cartn[0] = value; } -double get_yc(const Atom& a) { return a.xyz_cartn[1]; } -void set_yc(Atom& a, double value) { a.xyz_cartn[1] = value; } -double get_zc(const Atom& a) { return a.xyz_cartn[2]; } -void set_zc(Atom& a, double value) { a.xyz_cartn[2] = value; } - -double get_uc11(const Atom& a) { return a.uij_cartn(0, 0); } -void set_uc11(Atom& a, double value) { a.uij_cartn(0, 0) = value; } -double get_uc22(const Atom& a) { return a.uij_cartn(1, 1); } -void set_uc22(Atom& a, double value) { a.uij_cartn(1, 1) = value; } -double get_uc33(const Atom& a) { return a.uij_cartn(2, 2); } -void set_uc33(Atom& a, double value) { a.uij_cartn(2, 2) = value; } -double get_uc12(const Atom& a) { return a.uij_cartn(0, 1); } -void set_uc12(Atom& a, double value) { - a.uij_cartn(0, 1) = a.uij_cartn(1, 0) = value; } -double get_uc13(const Atom& a) { return a.uij_cartn(0, 2); } -void set_uc13(Atom& a, double value) { - a.uij_cartn(0, 2) = a.uij_cartn(2, 0) = value; } -double get_uc23(const Atom& a) { return a.uij_cartn(1, 2); } -void set_uc23(Atom& a, double value) { - a.uij_cartn(1, 2) = a.uij_cartn(2, 1) = value; } +template +double get_xyz(const Atom& a) +{ + return a.xyz_cartn[i]; +} + +template +void set_xyz(Atom& a, object value) +{ + a.xyz_cartn[i] = extractdouble(value); +} + + +double get_occ(const Atom& a) +{ + return a.occupancy; +} + +void set_occ(Atom& a, object value) +{ + a.occupancy = extractdouble(value); +} + + +bool get_anisotropy(const Atom& a) +{ + return a.anisotropy; +} + +void set_anisotropy(Atom& a, object value) +{ + a.anisotropy = bool(value); +} + + +template +double get_uc(const Atom& a) +{ + assert(i <= j); + return a.uij_cartn(i, j); +} + +template +void set_uc(Atom& a, object value) +{ + assert(i <= j); + a.uij_cartn(i, j) = extractdouble(value); + if (i != j) a.uij_cartn(j, i) = a.uij_cartn(i, j); +} // template wrapper class for overloading of clone and _customPQConfig @@ -524,20 +554,21 @@ void wrap_AtomicStructureAdapter() .add_property("xyz_cartn", atom_class.attr("_get_xyz_cartn"), set_xyz_cartn) - .add_property("xc", get_xc, set_xc, doc_Atom_xic) - .add_property("yc", get_yc, set_yc, doc_Atom_xic) - .add_property("zc", get_zc, set_zc, doc_Atom_xic) - .def_readwrite("occupancy", &Atom::occupancy) - .def_readwrite("anisotropy", &Atom::anisotropy) + .add_property("xc", get_xyz<0>, set_xyz<0>, doc_Atom_xic) + .add_property("yc", get_xyz<1>, set_xyz<1>, doc_Atom_xic) + .add_property("zc", get_xyz<2>, set_xyz<2>, doc_Atom_xic) + .add_property("occupancy", get_occ, set_occ, doc_Atom_occ) + .add_property("anisotropy", get_anisotropy, set_anisotropy, + doc_Atom_anisotropy) .add_property("uij_cartn", atom_class.attr("_get_uij_cartn"), set_uij_cartn) - .add_property("uc11", get_uc11, set_uc11, doc_Atom_uijc) - .add_property("uc22", get_uc22, set_uc22, doc_Atom_uijc) - .add_property("uc33", get_uc33, set_uc33, doc_Atom_uijc) - .add_property("uc12", get_uc12, set_uc12, doc_Atom_uijc) - .add_property("uc13", get_uc13, set_uc13, doc_Atom_uijc) - .add_property("uc23", get_uc23, set_uc23, doc_Atom_uijc) + .add_property("uc11", get_uc<0, 0>, set_uc<0, 0>, doc_Atom_uijc) + .add_property("uc22", get_uc<1, 1>, set_uc<1, 1>, doc_Atom_uijc) + .add_property("uc33", get_uc<2, 2>, set_uc<2, 2>, doc_Atom_uijc) + .add_property("uc12", get_uc<0, 1>, set_uc<0, 1>, doc_Atom_uijc) + .add_property("uc13", get_uc<0, 2>, set_uc<0, 2>, doc_Atom_uijc) + .add_property("uc23", get_uc<1, 2>, set_uc<1, 2>, doc_Atom_uijc) .def_pickle(SerializationPickleSuite()) ;