예제 #1
0
 def toLines(self, stru):
     """Convert Structure stru to a list of lines in DISCUS format.
     Return list of strings.
     """
     self.stru = stru
     # if necessary, convert self.stru to PDFFitStructure
     if not isinstance(stru, PDFFitStructure):
         self.stru = PDFFitStructure(stru)
     # build the stru_pdffit dictionary initialized from the defaults
     # in PDFFitStructure
     stru_pdffit = PDFFitStructure().pdffit
     if stru.pdffit:
         stru_pdffit.update(stru.pdffit)
     # here we can start
     self.lines = lines = []
     lines.append( "title   " + self.stru.title.strip() )
     lines.append( "spcgr   " + stru_pdffit["spcgr"] )
     if stru_pdffit.get('spdiameter', 0.0) > 0.0:
         line = 'shape   sphere, %g' % stru_pdffit['spdiameter']
         lines.append(line)
     if stru_pdffit.get('stepcut', 0.0) > 0.0:
         line = 'shape   stepcut, %g' % stru_pdffit['stepcut']
         lines.append(line)
     lines.append( "cell   %9.6f, %9.6f, %9.6f, %9.6f, %9.6f, %9.6f" %
             self.stru.lattice.abcABG() )
     lines.append( "ncell  %9i, %9i, %9i, %9i" % (1, 1, 1, len(self.stru)) )
     lines.append( "atoms" )
     for a in self.stru:
         lines.append( "%-4s %17.8f %17.8f %17.8f %12.4f" % (
             a.element.upper(), a.xyz[0], a.xyz[1], a.xyz[2], a.Bisoequiv))
     return lines
예제 #2
0
    def parseLines(self, lines):
        """Parse list of lines in DISCUS format.

        Return PDFFitStructure instance or raise StructureFormatError.
        """
        self.lines = lines
        ilines = self._linesIterator()
        self.stru = PDFFitStructure()
        record_parsers = {
            "cell": self._parse_cell,
            "format": self._parse_format,
            "generator": self._parse_not_implemented,
            "molecule": self._parse_not_implemented,
            "ncell": self._parse_ncell,
            "spcgr": self._parse_spcgr,
            "symmetry": self._parse_not_implemented,
            "title": self._parse_title,
            "shape": self._parse_shape,
        }
        try:
            # parse header
            for self.line in ilines:
                words = self.line.split()
                if not words or words[0][0] == '#': continue
                if words[0] == 'atoms': break
                rp = record_parsers.get(words[0], self._parse_unknown_record)
                rp(words)
            # check if cell has been defined
            if not self.cell_read:
                emsg = "%d: unit cell not defined" % self.nl
                raise StructureFormatError(emsg)
            # parse atoms
            for self.line in ilines:
                words = self.line.split()
                if not words or words[0][0] == '#': continue
                self._parse_atom(words)
            # self consistency check
            exp_natoms = reduce(lambda x, y: x * y, self.stru.pdffit['ncell'])
            # only check if ncell record exists
            if self.ncell_read and exp_natoms != len(self.stru):
                emsg = 'Expected %d atoms, read %d.' % \
                    (exp_natoms, len(self.stru))
                raise StructureFormatError(emsg)
            # take care of superlattice
            if self.stru.pdffit['ncell'][:3] != [1, 1, 1]:
                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.pdffit['ncell'] = [1, 1, 1, exp_natoms]
        except (ValueError, IndexError):
            exc_type, exc_value, exc_traceback = sys.exc_info()
            emsg = "%d: file is not in DISCUS format" % self.nl
            raise StructureFormatError, emsg, exc_traceback
        return self.stru
예제 #3
0
    def toLines(self, stru):
        """Convert Structure stru to a list of lines in PDFfit format.

        Return list of strings.
        """
        # build the stru_pdffit dictionary initialized from the defaults
        # in PDFFitStructure
        stru_pdffit = PDFFitStructure().pdffit
        if stru.pdffit:
            stru_pdffit.update(stru.pdffit)
        lines = []
        # default values of standard deviations
        d_sigxyz = numpy.zeros(3, dtype=float)
        d_sigo = 0.0
        d_sigU = numpy.zeros((3, 3), dtype=float)
        # here we can start
        l = "title  " + stru.title
        lines.append(l.strip())
        lines.append("format pdffit")
        lines.append("scale  %9.6f" % stru_pdffit["scale"])
        lines.append("sharp  %9.6f, %9.6f, %9.6f, %9.6f" %
                     (stru_pdffit["delta2"], stru_pdffit["delta1"],
                      stru_pdffit["sratio"], stru_pdffit["rcut"]))
        lines.append("spcgr   " + stru_pdffit["spcgr"])
        if stru_pdffit.get('spdiameter', 0.0) > 0.0:
            line = 'shape   sphere, %g' % stru_pdffit['spdiameter']
            lines.append(line)
        if stru_pdffit.get('stepcut', 0.0) > 0.0:
            line = 'shape   stepcut, %g' % stru_pdffit['stepcut']
            lines.append(line)
        lat = stru.lattice
        lines.append("cell   %9.6f, %9.6f, %9.6f, %9.6f, %9.6f, %9.6f" %
                     (lat.a, lat.b, lat.c, lat.alpha, lat.beta, lat.gamma))
        lines.append("dcell  %9.6f, %9.6f, %9.6f, %9.6f, %9.6f, %9.6f" %
                     tuple(stru_pdffit["dcell"]))
        lines.append("ncell  %9i, %9i, %9i, %9i" % (1, 1, 1, len(stru)))
        lines.append("atoms")
        for a in stru:
            ad = a.__dict__
            lines.append(
                "%-4s %17.8f %17.8f %17.8f %12.4f" %
                (a.element.upper(), a.xyz[0], a.xyz[1], a.xyz[2], a.occupancy))
            sigmas = numpy.concatenate(
                (ad.get("sigxyz", d_sigxyz), [ad.get("sigo", d_sigo)]))
            lines.append("    %18.8f %17.8f %17.8f %12.4f" % tuple(sigmas))
            sigU = ad.get("sigU", d_sigU)
            Uii = (a.U[0][0], a.U[1][1], a.U[2][2])
            Uij = (a.U[0][1], a.U[0][2], a.U[1][2])
            sigUii = (sigU[0][0], sigU[1][1], sigU[2][2])
            sigUij = (sigU[0][1], sigU[0][2], sigU[1][2])
            lines.append("    %18.8f %17.8f %17.8f" % Uii)
            lines.append("    %18.8f %17.8f %17.8f" % sigUii)
            lines.append("    %18.8f %17.8f %17.8f" % Uij)
            lines.append("    %18.8f %17.8f %17.8f" % sigUij)
        return lines
예제 #4
0
    def copy(self, other=None):
        """copy self to other. if other is None, create an instance

        other -- ref to other object

        returns reference to copied object
        """
        if other is None:
            other = PDFStructure(self.name)
        for a in PDFFitStructure().__dict__:
            setattr(other, a, copy.deepcopy(getattr(self, a)))
        other[:] = copy.deepcopy(self[:])
        return other
예제 #5
0
    def testGenerator(self):
        qmax = 27.0
        gen = self.gen
        gen.setScatteringType('N')
        self.assertEqual('N', gen.getScatteringType())
        gen.setQmax(qmax)
        self.assertAlmostEqual(qmax, gen.getQmax())
        from diffpy.Structure import PDFFitStructure
        stru = PDFFitStructure()
        ciffile = datafile("ni.cif")
        stru.read(ciffile)
        for i in range(4):
            stru[i].Bisoequiv = 1
        gen.setStructure(stru)

        calc = gen._calc
        # Test parameters
        for par in gen.iterPars(recurse=False):
            pname = par.name
            defval = calc._getDoubleAttr(pname)
            self.assertEquals(defval, par.getValue())
            # Test setting values
            par.setValue(1.0)
            self.assertEquals(1.0, par.getValue())
            par.setValue(defval)
            self.assertEquals(defval, par.getValue())

        r = numpy.arange(0, 10, 0.1)
        y = gen(r)

        # Now create a reference PDF. Since the calculator is testing its
        # output, we just have to make sure we can calculate from the
        # PDFGenerator interface.
        from diffpy.srreal.pdfcalculator import PDFCalculator
        calc = PDFCalculator()
        calc.rstep = r[1] - r[0]
        calc.rmin = r[0]
        calc.rmax = r[-1] + 0.5 * calc.rstep
        calc.qmax = qmax
        calc.setScatteringFactorTableByType('N')
        calc.eval(stru)
        yref = calc.pdf

        diff = y - yref
        res = numpy.dot(diff, diff)
        self.assertAlmostEquals(0, res)
        return
예제 #6
0
    def parseLines(self, lines):
        """Parse list of lines in PDFfit format.

        Return Structure object or raise StructureFormatError.
        """
        p_nl = 0
        rlist = []
        try:
            self.stru = PDFFitStructure()
            stru = self.stru
            cell_line_read = False
            stop = len(lines)
            while stop > 0 and lines[stop - 1].strip() == "":
                stop -= 1
            ilines = iter(lines[:stop])
            # read header of PDFFit file
            for l in ilines:
                p_nl += 1
                words = l.split()
                if len(words) == 0 or words[0][0] == '#':
                    continue
                elif words[0] == 'title':
                    stru.title = l.lstrip()[5:].strip()
                elif words[0] == 'scale':
                    stru.pdffit['scale'] = float(words[1])
                elif words[0] == 'sharp':
                    l1 = l.replace(',', ' ')
                    sharp_pars = [float(w) for w in l1.split()[1:]]
                    if len(sharp_pars) < 4:
                        stru.pdffit['delta2'] = sharp_pars[0]
                        stru.pdffit['sratio'] = sharp_pars[1]
                        stru.pdffit['rcut'] = sharp_pars[2]
                    else:
                        stru.pdffit['delta2'] = sharp_pars[0]
                        stru.pdffit['delta1'] = sharp_pars[1]
                        stru.pdffit['sratio'] = sharp_pars[2]
                        stru.pdffit['rcut'] = sharp_pars[3]
                elif words[0] == 'spcgr':
                    key = 'spcgr'
                    start = l.find(key) + len(key)
                    value = l[start:].strip()
                    stru.pdffit['spcgr'] = value
                elif words[0] == 'shape':
                    self._parse_shape(l)
                elif words[0] == 'cell':
                    cell_line_read = True
                    l1 = l.replace(',', ' ')
                    latpars = [float(w) for w in l1.split()[1:7]]
                    stru.lattice = Lattice(*latpars)
                elif words[0] == 'dcell':
                    l1 = l.replace(',', ' ')
                    stru.pdffit['dcell'] = [float(w) for w in l1.split()[1:7]]
                elif words[0] == 'ncell':
                    l1 = l.replace(',', ' ')
                    stru.pdffit['ncell'] = [int(w) for w in l1.split()[1:5]]
                elif words[0] == 'format':
                    if words[1] != 'pdffit':
                        emsg = "%d: file is not in PDFfit format" % p_nl
                        raise StructureFormatError(emsg)
                elif words[0] == 'atoms' and cell_line_read:
                    break
                else:
                    self.ignored_lines.append(l)
            # Header reading finished, check if required lines were present.
            if not cell_line_read:
                emsg = "%d: file is not in PDFfit format" % p_nl
                raise StructureFormatError(emsg)
            # Load data from atom entries.
            p_natoms = reduce(lambda x, y: x * y, stru.pdffit['ncell'])
            # we are now inside data block
            for l in ilines:
                p_nl += 1
                wl1 = l.split()
                element = wl1[0][0].upper() + wl1[0][1:].lower()
                xyz = [float(w) for w in wl1[1:4]]
                occ = float(wl1[4])
                stru.addNewAtom(element, xyz=xyz, occupancy=occ)
                a = stru.getLastAtom()
                p_nl += 1
                wl2 = ilines.next().split()
                a.sigxyz = [float(w) for w in wl2[0:3]]
                a.sigo = float(wl2[3])
                p_nl += 1
                wl3 = ilines.next().split()
                p_nl += 1
                wl4 = ilines.next().split()
                p_nl += 1
                wl5 = ilines.next().split()
                p_nl += 1
                wl6 = ilines.next().split()
                a.sigU = numpy.zeros((3, 3), dtype=float)
                a.U11 = float(wl3[0])
                a.U22 = float(wl3[1])
                a.U33 = float(wl3[2])
                a.sigU[0, 0] = float(wl4[0])
                a.sigU[1, 1] = float(wl4[1])
                a.sigU[2, 2] = float(wl4[2])
                a.U12 = float(wl5[0])
                a.U13 = float(wl5[1])
                a.U23 = float(wl5[2])
                a.sigU[0, 1] = a.sigU[1, 0] = float(wl6[0])
                a.sigU[0, 2] = a.sigU[2, 0] = float(wl6[1])
                a.sigU[1, 2] = a.sigU[2, 1] = float(wl6[2])
            if len(stru) != p_natoms:
                emsg = "expected %d atoms, read %d" % (p_natoms, len(stru))
                raise StructureFormatError(emsg)
            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.pdffit['ncell'] = [1, 1, 1, p_natoms]
        except (ValueError, IndexError):
            emsg = "%d: file is not in PDFfit format" % p_nl
            exc_type, exc_value, exc_traceback = sys.exc_info()
            raise StructureFormatError, emsg, exc_traceback
        return stru