Skip to content

PdbxWriter

Write mmCIF data files or dictionaries using the input container or container list.

Source code in mmcif/io/PdbxWriter.py
class PdbxWriter(object):

    """Write mmCIF data files or dictionaries using the input container or container list."""

    def __init__(self, ofh=sys.stdout):
        self.__ofh = ofh
        self.__containerList = []
        self.__maximumLineLength = 2048
        self.__spacing = 2
        self.__indentDefinition = 3
        self.__indentSpace = " " * self.__indentDefinition
        self.__doDefinitionIndent = False
        # Maximum number of rows checked for value length and format
        self.__rowPartition = None
        # Defaults to double quoting preference -
        self.__preferDoubleQuotes = True
        self.__useAlignedColumns = True
        self.__useStopTokens = False
        self.__cnvCharRefs = False
        #
        self.__enforceAscii = False
        self.__isPy3 = sys.version_info[0] == 3
        # if self.__isPy3:
        #     self.__string_types = str
        # else:
        #    self.__string_types = basestring

    def setSetEnforceAscii(self, boolVal):
        self.__enforceAscii = boolVal

    def setConvertCharRefs(self, flag):
        self.__cnvCharRefs = flag

    def setUseStopTokens(self, flag):
        self.__useStopTokens = flag

    def setMaxLineLength(self, numChars):
        self.__maximumLineLength = numChars

    def setAlignmentFlag(self, flag=True):
        self.__useAlignedColumns = flag

    def setPreferSingleQuotes(self):
        self.__preferDoubleQuotes = False

    def setPreferDoubleQuotes(self):
        self.__preferDoubleQuotes = True

    def setRowPartition(self, numParts):
        """Maximum number of partitions used to format value length for column alignment"""
        self.__rowPartition = numParts

    def write(self, containerList, lastInOrder=None, selectOrder=None):
        self.__containerList = containerList
        for container in self.__containerList:
            self.writeContainer(container, lastInOrder=lastInOrder, selectOrder=selectOrder)

    def writeContainer(self, container, lastInOrder=None, selectOrder=None):
        indS = " " * self.__indentDefinition
        if container.getType() == "definition":
            self.__write("save_%s" % container.getName())
            # self.__write("save_%s\n" % container.getName())
            self.__doDefinitionIndent = True
            # self.__write(indS + "#\n")
        elif container.getType() == "data":
            if container.getGlobal():
                self.__write("global_\n")
                self.__doDefinitionIndent = False
                self.__write("\n")
            else:
                self.__write("data_%s\n" % container.getName())
                self.__doDefinitionIndent = False
                # self.__write("#\n")

        nmL = container.filterObjectNameList(lastInOrder=lastInOrder, selectOrder=selectOrder)
        for nm in nmL:
            obj = container.getObj(nm)
            objL = obj.getRowList()

            # Skip empty objects
            if not objL:
                continue

            # Item - value formattting
            elif len(objL) == 1:
                self.__writeItemValueFormat(obj)

            # Table formatting -
            elif objL and obj.getAttributeList():
                if self.__useAlignedColumns:
                    self.__writeTableFormat(obj)
                else:
                    self.__writeTable(obj)
            else:
                raise PdbxError("")

            if self.__doDefinitionIndent:
                self.__write(indS + "#")
            else:
                self.__write("#")

        # Add a trailing saveframe reserved word
        if container.getType() == "definition":
            self.__write("\nsave_\n")
        self.__write("#\n")

    def __write(self, st):
        try:
            if self.__cnvCharRefs:
                self.__ofh.write(st.encode("ascii", "xmlcharrefreplace").decode("ascii"))
            elif not self.__isPy3:
                if self.__enforceAscii:
                    self.__ofh.write(st.decode("ascii"))
                else:
                    self.__ofh.write(st)
                    # self.__ofh.write(st.encode('utf-8').decode('utf-8'))
            else:
                self.__ofh.write(st)
        except Exception as e:
            logger.exception("write fails with %s for %r", str(e), st)

    def __writeItemValueFormat(self, categoryObj):
        # indS = " " * self.__INDENT_DEFINITION
        myCategory = DataCategoryFormatted(categoryObj, preferDoubleQuotes=self.__preferDoubleQuotes)
        # Compute the maximum item name length within this category -
        attributeNameLengthMax = 0
        for attributeName in myCategory.getAttributeList():
            attributeNameLengthMax = max(attributeNameLengthMax, len(attributeName))
        itemNameLengthMax = self.__spacing + len(myCategory.getName()) + attributeNameLengthMax + 2
        #
        lineList = []
        # lineList.append(indS+"#\n")
        lineList.append("\n")
        for attributeName, _ in myCategory.getAttributeListWithOrder():
            if self.__doDefinitionIndent:
                #        - add indent --
                lineList.append(self.__indentSpace)

            itemName = "_%s.%s" % (myCategory.getName(), attributeName)
            lineList.append(itemName.ljust(itemNameLengthMax))

            lineList.append(myCategory.getValueFormatted(attributeName, 0))
            lineList.append("\n")

        self.__write("".join(lineList))

    def __writeTableFormat(self, categoryObj):
        # indS = " " * self.__INDENT_DEFINITION
        myCategory = DataCategoryFormatted(categoryObj, preferDoubleQuotes=self.__preferDoubleQuotes)
        # Write the declaration of the loop_
        #
        lineList = []
        # lineList.append(indS + '#\n')
        lineList.append("\n")
        if self.__doDefinitionIndent:
            lineList.append(self.__indentSpace)
        lineList.append("loop_")
        for attributeName in myCategory.getAttributeList():
            lineList.append("\n")
            if self.__doDefinitionIndent:
                lineList.append(self.__indentSpace)
            itemName = "_%s.%s" % (myCategory.getName(), attributeName)
            lineList.append(itemName)
        self.__write("".join(lineList))

        #
        # Write the data in tabular format -
        #
        # print myCategory.getName()
        # print myCategory.getAttributeList()

        #    For speed make the following evaluation on a portion of the table
        if self.__rowPartition is not None:
            numSteps = max(1, myCategory.getRowCount() // self.__rowPartition)
        else:
            numSteps = 1

        formatTypeList, _ = myCategory.getFormatTypeList(steps=numSteps)
        maxLengthList = myCategory.getAttributeValueMaxLengthList(steps=numSteps)
        spacing = " " * self.__spacing
        #

        # print formatTypeList
        # print dataTypeList
        # print maxLengthList
        #
        for iRow in range(myCategory.getRowCount()):
            lineList = []
            lineList.append("\n")
            if self.__doDefinitionIndent:
                lineList.append(self.__indentSpace + "  ")

            for iAt in range(myCategory.getAttributeCount()):
                formatType = formatTypeList[iAt]
                maxLength = maxLengthList[iAt]

                if formatType == "FT_UNQUOTED_STRING" or formatType == "FT_NULL_VALUE":
                    val = myCategory.getValueFormattedByIndex(iAt, iRow)
                    lineList.append(val.ljust(maxLength))

                elif formatType == "FT_NUMBER":
                    val = myCategory.getValueFormattedByIndex(iAt, iRow)
                    lineList.append(val.rjust(maxLength))

                elif formatType == "FT_QUOTED_STRING":
                    val = myCategory.getValueFormattedByIndex(iAt, iRow)
                    # don't pad the last item in row condition
                    if iAt == myCategory.getAttributeCount() - 1:
                        lineList.append(val.ljust(len(val)))
                    else:
                        lineList.append(val.ljust(maxLength + 2))

                elif formatType == "FT_MULTI_LINE_STRING":
                    val = myCategory.getValueFormattedByIndex(iAt, iRow)
                    lineList.append(val)

                lineList.append(spacing)

            self.__write("".join(lineList))
        self.__write("\n")
        if self.__useStopTokens:
            self.__write("stop_\n")

    def __writeTable(self, categoryObj, numSteps=5):
        indS = " " * self.__indentDefinition
        myCategory = DataCategoryFormatted(categoryObj, preferDoubleQuotes=self.__preferDoubleQuotes)
        # Write the declaration of the loop_
        #
        lineList = []
        lineList.append(indS + "#\n")
        if self.__doDefinitionIndent:
            lineList.append(self.__indentSpace)
        lineList.append("loop_")
        for attributeName in myCategory.getAttributeList():
            lineList.append("\n")
            if self.__doDefinitionIndent:
                lineList.append(self.__indentSpace)
            itemName = "_%s.%s" % (myCategory.getName(), attributeName)
            lineList.append(itemName)
        self.__write("".join(lineList))

        #
        formatTypeList, _ = myCategory.getFormatTypeList(steps=numSteps)
        spacing = " " * self.__spacing
        #
        for iRow in range(myCategory.getRowCount()):
            lineList = []
            lineList.append("\n")
            if self.__doDefinitionIndent:
                lineList.append(self.__indentSpace + "  ")

            for iAt in range(myCategory.getAttributeCount()):
                formatType = formatTypeList[iAt]

                if formatType == "FT_UNQUOTED_STRING" or formatType == "FT_NULL_VALUE":
                    val = myCategory.getValueFormattedByIndex(iAt, iRow)
                    lineList.append(val)

                elif formatType == "FT_NUMBER":
                    val = myCategory.getValueFormattedByIndex(iAt, iRow)
                    lineList.append(val)

                elif formatType == "FT_QUOTED_STRING":
                    val = myCategory.getValueFormattedByIndex(iAt, iRow)
                    lineList.append(val)

                elif formatType == "FT_MULTI_LINE_STRING":
                    val = myCategory.getValueFormattedByIndex(iAt, iRow)
                    lineList.append(val)

                lineList.append(spacing)

            self.__write("".join(lineList))
        self.__write("\n")
        if self.__useStopTokens:
            self.__write("stop_\n")

setRowPartition(self, numParts)

Maximum number of partitions used to format value length for column alignment

Source code in mmcif/io/PdbxWriter.py
def setRowPartition(self, numParts):
    """Maximum number of partitions used to format value length for column alignment"""
    self.__rowPartition = numParts