diff --git a/news/deprecate-structure-function.rst b/news/deprecate-structure-function.rst new file mode 100644 index 0000000..73071f4 --- /dev/null +++ b/news/deprecate-structure-function.rst @@ -0,0 +1,27 @@ +**Added:** + +* Added ``place_in_lattice`` method to ``Structure`` +* Added ``read_structure`` method to ``Structure`` +* Added ``write_structure`` method to ``Structure`` + +**Changed:** + +* Changed private method ``__emptySharedStructure`` to ``__empty_shared_structure`` + +**Deprecated:** + +* Deprecated ``placeInLattice`` method of ``Structure`` for removal in version 4.0.0 +* Deprecated ``readStr`` method of ``Structure`` for removal in version 4.0.0 +* Deprecated ``writeStr`` method of ``Structure`` for removal in version 4.0.0 + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/src/diffpy/structure/apps/transtru.py b/src/diffpy/structure/apps/transtru.py index 963ebcf..7155a86 100755 --- a/src/diffpy/structure/apps/transtru.py +++ b/src/diffpy/structure/apps/transtru.py @@ -109,10 +109,10 @@ def main(): strufile = args[1] stru = Structure() if args[1] == "-": - stru.readStr(sys.stdin.read(), infmt) + stru.read_structure(sys.stdin.read(), infmt) else: stru.read(strufile, infmt) - sys.stdout.write(stru.writeStr(outfmt)) + sys.stdout.write(stru.write_structure(outfmt)) except IndexError: print("strufile not specified", file=sys.stderr) sys.exit(2) diff --git a/src/diffpy/structure/parsers/p_discus.py b/src/diffpy/structure/parsers/p_discus.py index 35b868e..7dba1e9 100644 --- a/src/diffpy/structure/parsers/p_discus.py +++ b/src/diffpy/structure/parsers/p_discus.py @@ -125,7 +125,7 @@ def parseLines(self, lines): latpars = list(self.stru.lattice.abcABG()) superlatpars = [latpars[i] * self.stru.pdffit["ncell"][i] for i in range(3)] + latpars[3:] superlattice = Lattice(*superlatpars) - self.stru.placeInLattice(superlattice) + self.stru.place_in_lattice(superlattice) self.stru.pdffit["ncell"] = [1, 1, 1, exp_natoms] except (ValueError, IndexError): exc_type, exc_value, exc_traceback = sys.exc_info() diff --git a/src/diffpy/structure/parsers/p_pdffit.py b/src/diffpy/structure/parsers/p_pdffit.py index 93646ac..822a8e2 100644 --- a/src/diffpy/structure/parsers/p_pdffit.py +++ b/src/diffpy/structure/parsers/p_pdffit.py @@ -169,7 +169,7 @@ def parseLines(self, lines): if stru.pdffit["ncell"][:3] != [1, 1, 1]: superlatpars = [latpars[i] * stru.pdffit["ncell"][i] for i in range(3)] + latpars[3:] superlattice = Lattice(*superlatpars) - stru.placeInLattice(superlattice) + stru.place_in_lattice(superlattice) stru.pdffit["ncell"] = [1, 1, 1, p_natoms] except (ValueError, IndexError): emsg = "%d: file is not in PDFfit format" % p_nl diff --git a/src/diffpy/structure/pdffitstructure.py b/src/diffpy/structure/pdffitstructure.py index 73115db..9cad2d2 100644 --- a/src/diffpy/structure/pdffitstructure.py +++ b/src/diffpy/structure/pdffitstructure.py @@ -97,7 +97,7 @@ def readStr(self, s, format="auto"): StructureParser Instance of `StructureParser` used to load the data. """ - p = Structure.readStr(self, s, format) + p = Structure.read_structure(self, s, format) sg = getattr(p, "spacegroup", None) if sg: self.pdffit["spcgr"] = sg.short_name diff --git a/src/diffpy/structure/structure.py b/src/diffpy/structure/structure.py index 784a11a..6f0ecd0 100644 --- a/src/diffpy/structure/structure.py +++ b/src/diffpy/structure/structure.py @@ -40,6 +40,24 @@ "get_last_atom", removal_version, ) +placeInLattice_deprecation_msg = build_deprecation_message( + base, + "placeInLattice", + "place_in_lattice", + removal_version, +) +readStr_deprecation_msg = build_deprecation_message( + base, + "readStr", + "read_structure", + removal_version, +) +writeStr_deprecation_msg = build_deprecation_message( + base, + "writeStr", + "write_structure", + removal_version, +) class Structure(list): @@ -282,7 +300,16 @@ def angle(self, aid0, aid1, aid2): u12 = a2.xyz - a1.xyz return self.lattice.angle(u10, u12) + @deprecated(placeInLattice_deprecation_msg) def placeInLattice(self, new_lattice): + """This function has been deprecated and will be removed in + version 4.0.0. + + Please use diffpy.structure.Structure.place_in_lattice instead. + """ + return self.place_in_lattice(new_lattice) + + def place_in_lattice(self, new_lattice): """Place structure into `new_lattice` coordinate system. Sets `lattice` to `new_lattice` and recalculate fractional coordinates @@ -345,7 +372,16 @@ def read(self, filename, format="auto"): self.title = tailbase return p + @deprecated(readStr_deprecation_msg) def readStr(self, s, format="auto"): + """This function has been deprecated and will be removed in + version 4.0.0. + + Please use diffpy.structure.Structure.read_structure instead. + """ + return self.read_structure(s, format) + + def read_structure(self, s, format="auto"): """Read structure from a string. Parameters @@ -399,7 +435,16 @@ def write(self, filename, format): fp.write(s) return + @deprecated(writeStr_deprecation_msg) def writeStr(self, format): + """This function has been deprecated and will be removed in + version 4.0.0. + + Please use diffpy.structure.Structure.write_structure instead. + """ + return self.write_structure(format) + + def write_structure(self, format): """Return string representation of the structure in specified format. @@ -537,7 +582,7 @@ def __getitem__(self, idx): >>> stru['Na3', 2, 'Cl2'] """ if isinstance(idx, slice): - rv = self.__emptySharedStructure() + rv = self.__empty_shared_structure() lst = super(Structure, self).__getitem__(idx) rv.extend(lst, copy=False) return rv @@ -556,7 +601,7 @@ def __getitem__(self, idx): idx1 = numpy.r_[idx] indices = numpy.arange(len(self))[idx1] rhs = [list.__getitem__(self, i) for i in indices] - rv = self.__emptySharedStructure() + rv = self.__empty_shared_structure() rv.extend(rhs, copy=False) return rv # here we need to resolve at least one string label @@ -917,7 +962,7 @@ def _get_composition(self): # Private Methods -------------------------------------------------------- - def __emptySharedStructure(self): + def __empty_shared_structure(self): """Return empty `Structure` with standard attributes same as in self.""" rv = Structure() diff --git a/tests/test_p_cif.py b/tests/test_p_cif.py index 5676120..4558c39 100644 --- a/tests/test_p_cif.py +++ b/tests/test_p_cif.py @@ -224,6 +224,33 @@ def test_write_and_read(self): self.assertAlmostEqual(0.046164, a3.U[2, 2]) return + def test_write_structure_and_read_structure(self): + """High-level check of P_cif.tostring()""" + # high-level check + stru_check = Structure() + stru_check.read(self.cdsebulkpdffitfile) + s_s = stru_check.write_structure("cif") + stru = Structure() + stru.read_structure(s_s, "cif") + self.assertAlmostEqual(4.2352, stru.lattice.a, self.places) + self.assertAlmostEqual(4.2352, stru.lattice.b, self.places) + self.assertAlmostEqual(6.90603, stru.lattice.c, self.places) + self.assertEqual(4, len(stru)) + a0 = stru[0] + self.assertEqual("Cd", a0.element) + self.assertTrue(numpy.allclose([0.3334, 0.6667, 0.0], a0.xyz)) + self.assertTrue(a0.anisotropy) + self.assertAlmostEqual(0.01303, a0.U[0, 0]) + self.assertAlmostEqual(0.01303, a0.U[1, 1]) + self.assertAlmostEqual(0.01402, a0.U[2, 2]) + a3 = stru[3] + self.assertEqual("Se", a3.element) + self.assertTrue(numpy.allclose([0.6666, 0.333300, 0.87667], a3.xyz)) + self.assertAlmostEqual(0.015673, a3.U[0, 0]) + self.assertAlmostEqual(0.015673, a3.U[1, 1]) + self.assertAlmostEqual(0.046164, a3.U[2, 2]) + return + def test_eps(self): """Test the P_cif.eps coordinates resolution.""" pcif = P_cif() diff --git a/tests/test_p_discus.py b/tests/test_p_discus.py index 71f0d69..1bfd759 100644 --- a/tests/test_p_discus.py +++ b/tests/test_p_discus.py @@ -91,11 +91,11 @@ def test_ignored_lines(self): ni_lines.insert(2, r1) ni_lines.insert(4, r2) s_s1 = "".join(ni_lines) - p = self.stru.readStr(s_s1, self.format) + p = self.stru.read_structure(s_s1, self.format) self.assertEqual([r1.rstrip(), r2.rstrip()], p.ignored_lines) ni_lines.append(r1) s_s2 = "".join(ni_lines) - self.assertRaises(StructureFormatError, self.stru.readStr, s_s2, self.format) + self.assertRaises(StructureFormatError, self.stru.read_structure, s_s2, self.format) return def test_spdiameter_parsing(self): @@ -103,20 +103,20 @@ def test_spdiameter_parsing(self): stru = self.stru stru.read(self.datafile("Ni-discus.stru"), self.format) self.assertEqual(0, stru.pdffit["spdiameter"]) - snoshape = stru.writeStr(format=self.format) + snoshape = stru.write_structure(format=self.format) self.assertTrue(not re.search("(?m)^shape", snoshape)) # produce a string with non-zero spdiameter stru.pdffit["spdiameter"] = 13 - s13 = stru.writeStr(format=self.format) + s13 = stru.write_structure(format=self.format) self.assertTrue(re.search("(?m)^shape +sphere, ", s13)) stru13 = Structure() - stru13.readStr(s13) + stru13.read_structure(s13) self.assertEqual(13, stru13.pdffit["spdiameter"]) with open(self.datafile("Ni.stru")) as fp: ni_lines = fp.readlines() ni_lines.insert(3, "shape invalid, 7\n") sbad = "".join(ni_lines) - self.assertRaises(StructureFormatError, self.stru.readStr, sbad, format=self.format) + self.assertRaises(StructureFormatError, self.stru.read_structure, sbad, format=self.format) return def test_stepcut_parsing(self): @@ -124,20 +124,20 @@ def test_stepcut_parsing(self): stru = self.stru stru.read(self.datafile("Ni-discus.stru"), self.format) self.assertEqual(0, stru.pdffit["stepcut"]) - snoshape = stru.writeStr(format=self.format) + snoshape = stru.write_structure(format=self.format) self.assertTrue(not re.search("(?m)^shape", snoshape)) # produce a string with non-zero stepcut stru.pdffit["stepcut"] = 13 - s13 = stru.writeStr(format=self.format) + s13 = stru.write_structure(format=self.format) self.assertTrue(re.search("(?m)^shape +stepcut, ", s13)) stru13 = Structure() - stru13.readStr(s13) + stru13.read_structure(s13) self.assertEqual(13, stru13.pdffit["stepcut"]) with open(self.datafile("Ni.stru")) as fp: ni_lines = fp.readlines() ni_lines.insert(3, "shape invalid, 7\n") sbad = "".join(ni_lines) - self.assertRaises(StructureFormatError, self.stru.readStr, sbad, format=self.format) + self.assertRaises(StructureFormatError, self.stru.read_structure, sbad, format=self.format) return diff --git a/tests/test_p_pdffit.py b/tests/test_p_pdffit.py index 989dd54..07bc6ca 100644 --- a/tests/test_p_pdffit.py +++ b/tests/test_p_pdffit.py @@ -172,7 +172,7 @@ def test_writeStr_pdffit(self): f_s = fp.read() f_s = re.sub("[ \t]+", " ", f_s) f_s = re.sub("[ \t]+\n", "\n", f_s) - s_s = stru.writeStr(self.format) + s_s = stru.write_structure(self.format) s_s = re.sub("[ \t]+", " ", s_s) self.assertEqual(f_s, s_s) return @@ -181,9 +181,9 @@ def test_huge_occupancy(self): """Check structure with huge occupancy can be read.""" self.stru.read(self.datafile("Ni.stru"), self.format) self.stru[0].occupancy = 16e16 - s_s = self.stru.writeStr(self.format) + s_s = self.stru.write_structure(self.format) stru1 = Structure() - stru1.readStr(s_s, self.format) + stru1.read_structure(s_s, self.format) self.assertEqual(16e16, stru1[0].occupancy) return @@ -196,11 +196,11 @@ def test_ignored_lines(self): ni_lines.insert(2, r1 + "\n") ni_lines.insert(4, r2 + "\n") s_s1 = "".join(ni_lines) - p = self.stru.readStr(s_s1, self.format) + p = self.stru.read_structure(s_s1, self.format) self.assertEqual([r1, r2], p.ignored_lines) ni_lines.insert(-3, r1 + "\n") s_s2 = "".join(ni_lines) - self.assertRaises(StructureFormatError, self.stru.readStr, s_s2, self.format) + self.assertRaises(StructureFormatError, self.stru.read_structure, s_s2, self.format) return def test_spdiameter_parsing(self): @@ -208,20 +208,20 @@ def test_spdiameter_parsing(self): stru = self.stru stru.read(self.datafile("Ni.stru"), self.format) self.assertEqual(0, stru.pdffit["spdiameter"]) - snoshape = stru.writeStr(format=self.format) + snoshape = stru.write_structure(format=self.format) self.assertTrue(not re.search("(?m)^shape", snoshape)) # produce a string with non-zero spdiameter stru.pdffit["spdiameter"] = 13 - s13 = stru.writeStr(format=self.format) + s13 = stru.write_structure(format=self.format) self.assertTrue(re.search("(?m)^shape +sphere, ", s13)) stru13 = Structure() - stru13.readStr(s13) + stru13.read_structure(s13) self.assertEqual(13, stru13.pdffit["spdiameter"]) with open(self.datafile("Ni.stru")) as fp: ni_lines = fp.readlines() ni_lines.insert(3, "shape invalid, 7\n") sbad = "".join(ni_lines) - self.assertRaises(StructureFormatError, self.stru.readStr, sbad, format=self.format) + self.assertRaises(StructureFormatError, self.stru.read_structure, sbad, format=self.format) return def test_stepcut_parsing(self): @@ -229,20 +229,20 @@ def test_stepcut_parsing(self): stru = self.stru stru.read(self.datafile("Ni.stru"), self.format) self.assertEqual(0, stru.pdffit["stepcut"]) - snoshape = stru.writeStr(format=self.format) + snoshape = stru.write_structure(format=self.format) self.assertTrue(not re.search("(?m)^shape", snoshape)) # produce a string with non-zero stepcut stru.pdffit["stepcut"] = 13 - s13 = stru.writeStr(format=self.format) + s13 = stru.write_structure(format=self.format) self.assertTrue(re.search("(?m)^shape +stepcut, ", s13)) stru13 = Structure() - stru13.readStr(s13) + stru13.read_structure(s13) self.assertEqual(13, stru13.pdffit["stepcut"]) with open(self.datafile("Ni.stru")) as fp: ni_lines = fp.readlines() ni_lines.insert(3, "shape invalid, 7\n") sbad = "".join(ni_lines) - self.assertRaises(StructureFormatError, self.stru.readStr, sbad, format=self.format) + self.assertRaises(StructureFormatError, self.stru.read_structure, sbad, format=self.format) return diff --git a/tests/test_parsers.py b/tests/test_parsers.py index 7723a2a..548fbb7 100644 --- a/tests/test_parsers.py +++ b/tests/test_parsers.py @@ -95,7 +95,7 @@ def test_writeStr_xyz(self): stru.title = "test of writeStr" stru.lattice = Lattice(1.0, 2.0, 3.0, 90.0, 90.0, 90.0) stru[:] = [Atom("H", [1.0, 1.0, 1.0]), Atom("Cl", [3.0, 2.0, 1.0])] - s1 = stru.writeStr(self.format) + s1 = stru.write_structure(self.format) s1 = re.sub("[ \t]+", " ", s1) s0 = "2\n%s\nH 1 2 3\nCl 3 4 3\n" % stru.title self.assertEqual(s1, s0) @@ -190,12 +190,12 @@ def test_writeStr_rawxyz(self): stru.lattice = Lattice(1.0, 2.0, 3.0, 90.0, 90.0, 90.0) # plain version stru[:] = [Atom("H", [1.0, 1.0, 1.0])] - s1 = stru.writeStr(self.format) + s1 = stru.write_structure(self.format) s1 = re.sub("[ \t]+", " ", s1) s0 = "H 1 2 3\n" # brutal raw version stru[0].element = "" - s1 = stru.writeStr(self.format) + s1 = stru.write_structure(self.format) s0 = "1 2 3\n" self.assertEqual(s1, s0) return @@ -270,13 +270,13 @@ def test_rwStr_pdb_CdSe(self): """Check conversion to PDB file format.""" stru = self.stru stru.read(self.datafile("CdSe_bulk.stru"), "pdffit") - s = stru.writeStr(self.format) + s = stru.write_structure(self.format) # all lines should be 80 characters long linelens = [len(line) for line in s.split("\n") if line != ""] self.assertEqual(linelens, len(linelens) * [80]) # now clean and re-read structure stru = Structure() - stru.readStr(s, self.format) + stru.read_structure(s, self.format) s_els = [a.element for a in stru] f_els = ["Cd", "Cd", "Se", "Se"] self.assertEqual(s_els, f_els) @@ -343,9 +343,9 @@ def test_rwStr_xcfg_CdSe(self): """Check conversion to XCFG file format.""" stru = self.stru stru.read(self.datafile("CdSe_bulk.stru"), "pdffit") - s = stru.writeStr(self.format) + s = stru.write_structure(self.format) stru = Structure() - stru.readStr(s, self.format) + stru.read_structure(s, self.format) s_els = [a.element for a in stru] f_els = ["Cd", "Cd", "Se", "Se"] self.assertEqual(s_els, f_els) diff --git a/tests/test_structure.py b/tests/test_structure.py index 6528365..c5b17ce 100644 --- a/tests/test_structure.py +++ b/tests/test_structure.py @@ -100,9 +100,9 @@ def __copy__(self): def test___copy__(self): """Check Structure.__copy__()""" cdse = Structure(filename=self.cdsefile) - cdse_str = cdse.writeStr("pdffit") + cdse_str = cdse.write_structure("pdffit") cdse2 = copy.copy(cdse) - self.assertEqual(cdse_str, cdse2.writeStr("pdffit")) + self.assertEqual(cdse_str, cdse2.write_structure("pdffit")) self.assertFalse(cdse.lattice is cdse2.lattice) sameatoms = set(cdse).intersection(cdse2) self.assertFalse(sameatoms) @@ -193,6 +193,17 @@ def test_placeInLattice(self): a1 = stru[1] self.assertTrue(numpy.allclose(a1.xyz, [2.0, 0.0, 2.0])) + def test_place_in_lattice(self): + """Check Structure.placeInLattice() -- conversion of + coordinates.""" + stru = self.stru + new_lattice = Lattice(0.5, 0.5, 0.5, 90, 90, 60) + stru.place_in_lattice(new_lattice) + a0 = stru[0] + self.assertTrue(numpy.allclose(a0.xyz, [0.0, 0.0, 0.0])) + a1 = stru[1] + self.assertTrue(numpy.allclose(a1.xyz, [2.0, 0.0, 2.0])) + # def test_read(self): # """check Structure.read()""" # return