Example #1
0
def writeInterface(datafile, mscontext):
    #Interface branch
    #TODO: The bulk materials that define the interfaces must be written,
    #even if the material is not assigned to pixels.
    #Interface materials are not assigned to pixels. They must be
    #explicitly listed here.
    msobj = mscontext.getObject()
    interfacemsplugin = msobj.getPlugIn("Interfaces")
    for interfacename, interfacedef in interfacemsplugin.namedinterfaces.items(
    ):
        datafile.startCmd(OOF.LoadData.Microstructure.Interface.New)
        datafile.argument('microstructure', msobj.name())
        datafile.argument('name', interfacename)
        datafile.argument('interface_type', interfacedef)
        datafile.endCmd()

    #Write interface properties and materials.
    #An interface material is saved only if it has been assigned to
    #an interface.
    materialmenu.writeMaterials(datafile, [
        materialmanager.getMaterial(m)
        for m in interfacemsplugin.getInterfaceMaterials()
    ])

    #Assign interface materials to interfaces
    for matname, interfacenames in interfacemsplugin._materialassignments.items(
    ):
        if len(interfacenames) == 0:
            continue


##        datafile.startCmd(OOF.LoadData.MaterialandType)
##        datafile.argument('name',matname)
##        matobj=materialmanager.getMaterial(matname)
##        datafile.argument('properties', [prop.registration().name()
##                                         for prop in matobj.properties()])
##        datafile.argument('materialtype',matobj.type())
##        datafile.endCmd()
        datafile.startCmd(OOF.LoadData.Material.Interface.Assign)
        datafile.argument('microstructure', msobj.name())
        datafile.argument('material', matname)
        datafile.argument('interfaces', interfacenames)
        datafile.endCmd()
Example #2
0
def writeInterface(datafile, mscontext):
    #Interface branch
    #TODO: The bulk materials that define the interfaces must be written,
    #even if the material is not assigned to pixels.
    #Interface materials are not assigned to pixels. They must be
    #explicitly listed here.
    msobj=mscontext.getObject()
    interfacemsplugin=msobj.getPlugIn("Interfaces")
    for interfacename, interfacedef in interfacemsplugin.namedinterfaces.items():
        datafile.startCmd(OOF.LoadData.Microstructure.Interface.New)
        datafile.argument('microstructure',msobj.name())
        datafile.argument('name',interfacename)
        datafile.argument('interface_type',interfacedef)
        datafile.endCmd()

    #Write interface properties and materials.
    #An interface material is saved only if it has been assigned to
    #an interface.
    materialmenu.writeMaterials(datafile,
                                [materialmanager.getMaterial(m)
                                 for m in interfacemsplugin.getInterfaceMaterials()])

    #Assign interface materials to interfaces
    for matname, interfacenames in interfacemsplugin._materialassignments.items():
        if len(interfacenames)==0:
            continue
##        datafile.startCmd(OOF.LoadData.MaterialandType)
##        datafile.argument('name',matname)
##        matobj=materialmanager.getMaterial(matname)
##        datafile.argument('properties', [prop.registration().name()
##                                         for prop in matobj.properties()])
##        datafile.argument('materialtype',matobj.type())
##        datafile.endCmd()
        datafile.startCmd(OOF.LoadData.Material.Interface.Assign)
        datafile.argument('microstructure',msobj.name())
        datafile.argument('material',matname)
        datafile.argument('interfaces',interfacenames)
        datafile.endCmd()
Example #3
0
def writeSkeleton(datafile, skelcontext):
    skelcontext.begin_reading()
    try:
        skeleton = skelcontext.getObject()
        skelpath = skelcontext.path()

        # Create skeleton.
        datafile.startCmd(skelmenu.NewPeriodic)
        datafile.argument('name', skelcontext.name())
        datafile.argument('microstructure', skeleton.MS.name())
        datafile.argument('left_right_periodicity', skeleton.left_right_periodicity)
        datafile.argument('top_bottom_periodicity', skeleton.top_bottom_periodicity)
        if config.dimension() == 3:
            datafile.argument('front_back_periodicity', skeleton.front_back_periodicity)            
        datafile.endCmd()

        # Define nodes.
        datafile.startCmd(skelmenu.Nodes)
        datafile.argument('skeleton', skelpath)
        if config.dimension()==2:
            datafile.argument('points', [(nd.position().x, nd.position().y)
                                         for nd in skeleton.nodes])
        elif config.dimension()==3:
            datafile.argument('points', [(nd.position().x, nd.position().y, nd.position().z)
                                         for nd in skeleton.nodes])
        datafile.endCmd()

        # Nodes are written and read in the order in which they're stored
        # in the Skeleton's nodes list.  This is not the same as the
        # nodes' internal index, so we need to create a dictionary of
        # indices in the nodes list so that the elements' node tuples are
        # correct.
        nodedict = {}
        c = 0
        for node in skeleton.nodes:
            nodedict[node] = c
            c += 1
        # same for elements
        elementdict = {}
        c = 0
        for element in skeleton.elements:
            elementdict[element] = c
            c += 1

        # Write node partnerships using the node indices in nodedict
        if skeleton.left_right_periodicity or skeleton.top_bottom_periodicity \
               or (config.dimension()==3 and skeleton.front_back_periodicity):
            partners = []
            for node in skeleton.nodes:
                nodeno = nodedict[node]
                partnernos = [nodedict[n] for n in node.getPartners()]
                # Only save nontrivial partnerships, and only save
                # each set of partners once.  Partnerships are saved
                # as a tuple of node indices.  Order is unimportant.
                if partnernos and nodeno < min(partnernos):
                    partners.append(tuple([nodeno] + partnernos))
            datafile.startCmd(skelmenu.Partnerships)
            datafile.argument('skeleton', skelpath)
            datafile.argument('partnerlists', partners)
            datafile.endCmd()

        # Define elements, using the node indices in nodedict.
        datafile.startCmd(skelmenu.Elements)
        datafile.argument('skeleton', skelpath)
        datafile.argument('nodes', [tuple([nodedict[node] for node in el.nodes])
                                    for el in skeleton.elements])
        datafile.endCmd()


        # we don't have groups and boundaries set up in 3d yet.
        # TODO 3D: enable this in 3d when needed
        if config.dimension() == 2:
            # Node groups
            for group in skelcontext.nodegroups.groups:
                datafile.startCmd(skelmenu.NodeGroup)
                datafile.argument('skeleton', skelpath)
                datafile.argument('name', group)
                datafile.argument(
                    'nodes', 
                    [nodedict[node]
                     for node in skelcontext.nodegroups.get_group(group)])
                datafile.endCmd()

            # Element groups
            for group in skelcontext.elementgroups.groups:
                datafile.startCmd(skelmenu.ElementGroup)
                datafile.argument('skeleton', skelpath)
                datafile.argument('name', group)
                datafile.argument(
                    'elements',
                    [elementdict[el]
                     for el in skelcontext.elementgroups.get_group(group)])
                datafile.endCmd()

            for group in skelcontext.segmentgroups.groups:
                datafile.startCmd(skelmenu.SegmentGroup)
                datafile.argument('skeleton', skelpath)
                datafile.argument('name', group)
                nodepairs = [
                    seg.nodes()
                    for seg in skelcontext.segmentgroups.get_group(group)]
                datafile.argument(
                    'segments',
                    [(nodedict[n1], nodedict[n2]) for (n1, n2) in nodepairs])
                datafile.endCmd()

            # Materials assigned to Element Groups.  If a Material
            # isn't assigned to pixels in the Microstructure, be sure
            # to save the Material's definition first.
            msmatls = ooflib.SWIG.engine.material.getMaterials(skeleton.MS)
            groupmats = skelcontext.elementgroups.getAllMaterials()
            # skelmatls is a list of Materials used in the Skeleton
            # that aren't in the Microstructure.
            skelmatls = [m for (g, m) in groupmats if m not in msmatls]
            # Construct a list of Properties already defined in the
            # data file, so that they're not written twice.
            excludeProps = {}
            for mat in msmatls:
                for prop in mat.properties():
                    excludeProps[prop.registration().name()] = prop
            materialmenu.writeMaterials(datafile, skelmatls, excludeProps)
            # Now assign Materials to Groups.
            for group, material in groupmats:
                datafile.startCmd(skelmenu.AddMaterialToGroup)
                datafile.argument('skeleton', skelpath)
                datafile.argument('group', group)
                datafile.argument('material', material.name())
                datafile.endCmd()

            # Pinned nodes
            datafile.startCmd(skelmenu.PinnedNodes)
            datafile.argument('skeleton', skelpath)
            datafile.argument(
                'nodes',
                [nodedict[node] for node in skelcontext.pinnednodes.retrieve()])
            datafile.endCmd()

        # Point boundaries
        # sort keys to print in a consistent order
        sortedKeys = skeleton.pointboundaries.keys()
        sortedKeys.sort()
        #for pbname, pbdy in skeleton.pointboundaries.items():
        for pbname in sortedKeys:
            pbdy = skeleton.pointboundaries[pbname]
            datafile.startCmd(skelmenu.PointBoundary)
            datafile.argument('skeleton', skelpath)
            datafile.argument('name', pbname)
            datafile.argument('nodes', [nodedict[node] for node in pbdy.nodes])
            exterior = 0
            if isinstance(pbdy, skeletonboundary.ExteriorSkeletonPointBoundary):
                exterior = 1
            datafile.argument('exterior', exterior)
            datafile.endCmd()

        # Edge boundaries
        # sort keys to print in a consistent order
        sortedKeys = skeleton.edgeboundaries.keys()
        sortedKeys.sort()
        # for ebname, ebdy in skeleton.edgeboundaries.items():
        for ebname in sortedKeys:
            ebdy = skeleton.edgeboundaries[ebname]
            datafile.startCmd(skelmenu.EdgeBoundary)
            datafile.argument('skeleton', skelpath)
            datafile.argument('name', ebname)
            #Interface branch
            if ebdy._sequenceable==1:
                edgeset = rearrangeEdges([
                    tuple([nodedict[x] for x in edge.get_nodes()])
                    for edge in ebdy.edges
                    ])
            else:
                edgeset = [
                    tuple([nodedict[x] for x in edge.get_nodes()])
                    for edge in ebdy.edges
                    ]
            datafile.argument('edges', edgeset)
            exterior = 0
            if isinstance(ebdy, skeletonboundary.ExteriorSkeletonEdgeBoundary):
                exterior = 1
            datafile.argument('exterior', exterior)
            datafile.endCmd()

            #Interface branch
            interfacematname=skelcontext.getBoundary(ebname)._interfacematerial
            if interfacematname is not None:
                datafile.startCmd(OOF.LoadData.Material.Interface.Assign)
                datafile.argument('microstructure',skeleton.MS.name())
                datafile.argument('material',interfacematname)
                datafile.argument('interfaces',[skelcontext.name()+":"+ebname])
                datafile.endCmd()

    finally:
        skelcontext.end_reading()
Example #4
0
def writeSkeleton(datafile, skelcontext):
    skelcontext.begin_reading()
    try:
        # debug.fmsg()
        skeleton = skelcontext.getObject()
        skelpath = skelcontext.path()

        # Create skeleton.
        datafile.startCmd(skelmenu.NewPeriodic)
        datafile.argument('name', skelcontext.name())
        datafile.argument('microstructure',
                          skeleton.getMicrostructure().name())
        if config.dimension() == 2:
            # The names of the periodicity arguments in 2D have not been
            # changed to x_poeriodicity and y_periodicity to preserve
            # compatibility with old data files.
            datafile.argument('left_right_periodicity',
                              skeleton.getPeriodicity(0))
            datafile.argument('top_bottom_periodicity',
                              skeleton.getPeriodicity(1))
        if config.dimension() == 3:
            datafile.argument('x_periodicity', skeleton.getPeriodicity(0))
            datafile.argument('y_periodicity', skeleton.getPeriodicity(1))
            datafile.argument('z_periodicity', skeleton.getPeriodicity(2))
        datafile.endCmd()

        # debug.fmsg("nodes")
        # Define nodes.
        datafile.startCmd(skelmenu.Nodes)
        datafile.argument('skeleton', skelpath)
        if config.dimension() == 2:
            datafile.argument('points', [(nd.position().x, nd.position().y)
                                         for nd in skeleton.nodes])
        elif config.dimension() == 3:
            datafile.argument(
                'points',
                [tuple(node.position()) for node in skeleton.getNodes()])
        datafile.endCmd()

        # Nodes are written and read in the order in which they're stored
        # in the Skeleton's nodes list.  This is not the same as the
        # nodes' internal index, so we need to create a dictionary of
        # indices in the nodes list so that the elements' node tuples are
        # correct.
        #         nodedict = {}
        #         c = 0
        #         for node in skeleton.nodes:
        #             nodedict[node] = c
        #             c += 1
        #         # same for elements
        #         elementdict = {}
        #         c = 0
        #         for element in skeleton.elements:
        #             elementdict[element] = c
        #             c += 1

        # Write node partnerships using the node indices in nodedict
        #         if skeleton.x_periodicity or skeleton.y_periodicity \
        #                or (config.dimension()==3 and skeleton.z_periodicity):
        #             partners = []
        # #            for node in skeleton.nodes:
        #             for i in range(skeleton.nnodes()):
        #                 node = skeleton.getNode(i)
        #                 #nodeno = nodedict[node]
        #                 partnernos = [nodedict[n] for n in node.getPartners()]
        #                 # Only save nontrivial partnerships, and only save
        #                 # each set of partners once.  Partnerships are saved
        #                 # as a tuple of node indices.  Order is unimportant.
        #                 if partnernos and nodeno < min(partnernos):
        #                     partners.append(tuple([nodeno] + partnernos))
        #             datafile.startCmd(skelmenu.Partnerships)
        #             datafile.argument('skeleton', skelpath)
        #             datafile.argument('partnerlists', partners)
        #             datafile.endCmd()

        # Define elements, using the node indices
        # debug.fmsg("elements")
        datafile.startCmd(skelmenu.Elements)
        datafile.argument('skeleton', skelpath)
        datafile.argument('nodes', [
            tuple(node.getIndex() for node in element.getNodes())
            for element in skeleton.getElements()
        ])
        datafile.endCmd()

        # Node groups
        # debug.fmsg("node groups")
        for group in skelcontext.nodegroups.groups:
            datafile.startCmd(skelmenu.NodeGroup)
            datafile.argument('skeleton', skelpath)
            datafile.argument('name', group)
            datafile.argument('nodes', [
                node.getIndex()
                for node in skelcontext.nodegroups.get_group(group)
            ])
            datafile.endCmd()

        # Element groups
        # debug.fmsg("element groups")
        for group in skelcontext.elementgroups.groups:
            datafile.startCmd(skelmenu.ElementGroup)
            datafile.argument('skeleton', skelpath)
            datafile.argument('name', group)
            datafile.argument('elements', [
                el.getIndex()
                for el in skelcontext.elementgroups.get_group(group)
            ])
            datafile.endCmd()

        # debug.fmsg("segment groups")
        for group in skelcontext.segmentgroups.groups:
            datafile.startCmd(skelmenu.SegmentGroup)
            datafile.argument('skeleton', skelpath)
            datafile.argument('name', group)
            segs = [
                tuple(n.getIndex() for n in seg.getNodes())
                for seg in skelcontext.segmentgroups.get_group(group)
            ]
            datafile.argument('segments', segs)
            datafile.endCmd()

        # debug.fmsg("face groups")
        for group in skelcontext.facegroups.groups:
            datafile.startCmd(skelmenu.FaceGroup)
            datafile.argument('skeleton', skelpath)
            datafile.argument('name', group)
            faces = [
                tuple(n.getIndex() for n in face.getNodes())
                for face in skelcontext.facegroups.get_group(group)
            ]
            datafile.argument('faces', faces)
            datafile.endCmd()

        # Materials assigned to Element Groups.  If a Material
        # isn't assigned to pixels in the Microstructure, be sure
        # to save the Material's definition first.
        # debug.fmsg("materials")
        msmatls = ooflib.SWIG.engine.material.getMaterials(
            skeleton.getMicrostructure())
        groupmats = skelcontext.elementgroups.getAllMaterials()
        # skelmatls is a list of Materials used in the Skeleton
        # that aren't in the Microstructure.
        skelmatls = [m for (g, m) in groupmats if m not in msmatls]
        # Construct a list of Properties already defined in the
        # data file, so that they're not written twice.
        excludeProps = {}
        for mat in msmatls:
            for prop in mat.properties():
                excludeProps[prop.registration().name()] = prop
        materialmenu.writeMaterials(datafile, skelmatls, excludeProps)
        # Now assign Materials to Groups.
        for group, material in groupmats:
            datafile.startCmd(skelmenu.AddMaterialToGroup)
            datafile.argument('skeleton', skelpath)
            datafile.argument('group', group)
            datafile.argument('material', material.name())
            datafile.endCmd()

        # Pinned nodes
        datafile.startCmd(skelmenu.PinnedNodes)
        datafile.argument('skeleton', skelpath)
        datafile.argument(
            'nodes',
            [node.getIndex() for node in skelcontext.pinnednodes.retrieve()])
        datafile.endCmd()

        # debug.fmsg("boundaries")
        # Point boundaries
        # sort keys to print in a consistent order
        pointboundaries = skeleton.getPointBoundaries()
        sortedKeys = pointboundaries.keys()
        sortedKeys.sort()
        #for pbname, pbdy in skeleton.pointboundaries.items():
        for pbname in sortedKeys:
            pbdy = pointboundaries[pbname]
            datafile.startCmd(skelmenu.PointBoundary)
            datafile.argument('skeleton', skelpath)
            datafile.argument('name', pbname)
            datafile.argument('nodes',
                              [node.getIndex() for node in pbdy.getNodes()])
            exterior = 0
            if isinstance(pbdy,
                          cskeletonboundary.ExteriorCSkeletonPointBoundaryPtr):
                exterior = 1
            datafile.argument('exterior', exterior)
            datafile.endCmd()

        # Edge boundaries
        # sort keys to print in a consistent order
        edgeboundaries = skeleton.getEdgeBoundaries()
        sortedKeys = edgeboundaries.keys()
        sortedKeys.sort()
        # for ebname, ebdy in skeleton.edgeboundaries.items():
        for ebname in sortedKeys:
            ebdy = edgeboundaries[ebname]
            datafile.startCmd(skelmenu.EdgeBoundary)
            datafile.argument('skeleton', skelpath)
            datafile.argument('name', ebname)
            #             #Interface branch
            #             if ebdy._sequenceable==1:
            #                 edgeset = rearrangeEdges([
            #                     tuple([nodedict[x] for x in edge.get_nodes()])
            #                     for edge in ebdy.edges
            #                     ])
            #             else:
            edgeset = [
                tuple(edge.getNode(i).getIndex() for i in (0, 1))
                for edge in ebdy.getOrientedSegments()
            ]
            datafile.argument('edges', edgeset)
            exterior = 0
            if isinstance(ebdy,
                          cskeletonboundary.ExteriorCSkeletonEdgeBoundaryPtr):
                exterior = 1
            datafile.argument('exterior', exterior)
            datafile.endCmd()

#             #Interface branch
#             interfacematname=skelcontext.getBoundary(ebname)._interfacematerial
#             if interfacematname is not None:
#                 datafile.startCmd(OOF.LoadData.Material.Interface.Assign)
#                 datafile.argument('microstructure',skeleton.getMicrostructure().name())
#                 datafile.argument('material',interfacematname)
#                 datafile.argument('interfaces',[skelcontext.name()+":"+ebname])
#                 datafile.endCmd()

# Face boundaries
# sort keys to print in a consistent order
# debug.fmsg("face boundaries")
        faceboundaries = skeleton.getFaceBoundaries()
        # debug.fmsg("got faceboundaries")
        sortedKeys = faceboundaries.keys()
        sortedKeys.sort()
        # for ebname, ebdy in skeleton.faceboundaries.items():
        for fbname in sortedKeys:
            # debug.fmsg("fbname=", fbname)
            fbdy = faceboundaries[fbname]
            datafile.startCmd(skelmenu.FaceBoundary)
            datafile.argument('skeleton', skelpath)
            datafile.argument('name', fbname)
            faceset = [
                tuple(face.getNode(i).getIndex() for i in range(3))
                for face in fbdy.getFaces()
            ]
            # debug.fmsg("got faceset")
            faceset.sort()
            datafile.argument('faces', faceset)
            exterior = 0
            if isinstance(fbdy,
                          cskeletonboundary.ExteriorCSkeletonFaceBoundaryPtr):
                exterior = 1
            datafile.argument('exterior', exterior)
            datafile.endCmd()

# debug.fmsg("selections")
# Element selection
        datafile.startCmd(skelmenu.ElementSelection)
        datafile.argument('skeleton', skelpath)
        datafile.argument(
            'elements',
            [el.getIndex() for el in skelcontext.elementselection.retrieve()])
        datafile.endCmd()

        # Face selection
        datafile.startCmd(skelmenu.FaceSelection)
        datafile.argument('skeleton', skelpath)
        fas = [
            tuple(n.getIndex() for n in fa.getNodes())
            for fa in skelcontext.faceselection.retrieve()
        ]
        datafile.argument('faces', fas)
        datafile.endCmd()

        # Segment selection
        datafile.startCmd(skelmenu.SegmentSelection)
        datafile.argument('skeleton', skelpath)
        segs = [
            tuple(n.getIndex() for n in se.getNodes())
            for se in skelcontext.segmentselection.retrieve()
        ]
        datafile.argument('segments', segs)
        datafile.endCmd()

        # Node selection
        datafile.startCmd(skelmenu.NodeSelection)
        datafile.argument('skeleton', skelpath)
        datafile.argument(
            'nodes',
            [no.getIndex() for no in skelcontext.nodeselection.retrieve()])
        datafile.endCmd()

    finally:
        # debug.fmsg("done")
        skelcontext.end_reading()
Example #5
0
def writeSkeleton(datafile, skelcontext):
    skelcontext.begin_reading()
    try:
        skeleton = skelcontext.getObject()
        skelpath = skelcontext.path()

        # Create skeleton.
        datafile.startCmd(skelmenu.NewPeriodic)
        datafile.argument('name', skelcontext.name())
        datafile.argument('microstructure', skeleton.MS.name())
        datafile.argument('left_right_periodicity',
                          skeleton.left_right_periodicity)
        datafile.argument('top_bottom_periodicity',
                          skeleton.top_bottom_periodicity)
        if config.dimension() == 3:
            datafile.argument('front_back_periodicity',
                              skeleton.front_back_periodicity)
        datafile.endCmd()

        # Define nodes.
        datafile.startCmd(skelmenu.Nodes)
        datafile.argument('skeleton', skelpath)
        if config.dimension() == 2:
            datafile.argument('points', [(nd.position().x, nd.position().y)
                                         for nd in skeleton.nodes])
        elif config.dimension() == 3:
            datafile.argument(
                'points', [(nd.position().x, nd.position().y, nd.position().z)
                           for nd in skeleton.nodes])
        datafile.endCmd()

        # Nodes are written and read in the order in which they're stored
        # in the Skeleton's nodes list.  This is not the same as the
        # nodes' internal index, so we need to create a dictionary of
        # indices in the nodes list so that the elements' node tuples are
        # correct.
        nodedict = {}
        c = 0
        for node in skeleton.nodes:
            nodedict[node] = c
            c += 1
        # same for elements
        elementdict = {}
        c = 0
        for element in skeleton.elements:
            elementdict[element] = c
            c += 1

        # Write node partnerships using the node indices in nodedict
        if skeleton.left_right_periodicity or skeleton.top_bottom_periodicity \
               or (config.dimension()==3 and skeleton.front_back_periodicity):
            partners = []
            for node in skeleton.nodes:
                nodeno = nodedict[node]
                partnernos = [nodedict[n] for n in node.getPartners()]
                # Only save nontrivial partnerships, and only save
                # each set of partners once.  Partnerships are saved
                # as a tuple of node indices.  Order is unimportant.
                if partnernos and nodeno < min(partnernos):
                    partners.append(tuple([nodeno] + partnernos))
            datafile.startCmd(skelmenu.Partnerships)
            datafile.argument('skeleton', skelpath)
            datafile.argument('partnerlists', partners)
            datafile.endCmd()

        # Define elements, using the node indices in nodedict.
        datafile.startCmd(skelmenu.Elements)
        datafile.argument('skeleton', skelpath)
        datafile.argument('nodes', [
            tuple([nodedict[node] for node in el.nodes])
            for el in skeleton.elements
        ])
        datafile.endCmd()

        # we don't have groups and boundaries set up in 3d yet.
        # TODO 3D: enable this in 3d when needed
        if config.dimension() == 2:
            # Node groups
            for group in skelcontext.nodegroups.groups:
                datafile.startCmd(skelmenu.NodeGroup)
                datafile.argument('skeleton', skelpath)
                datafile.argument('name', group)
                datafile.argument('nodes', [
                    nodedict[node]
                    for node in skelcontext.nodegroups.get_group(group)
                ])
                datafile.endCmd()

            # Element groups
            for group in skelcontext.elementgroups.groups:
                datafile.startCmd(skelmenu.ElementGroup)
                datafile.argument('skeleton', skelpath)
                datafile.argument('name', group)
                datafile.argument('elements', [
                    elementdict[el]
                    for el in skelcontext.elementgroups.get_group(group)
                ])
                datafile.endCmd()

            for group in skelcontext.segmentgroups.groups:
                datafile.startCmd(skelmenu.SegmentGroup)
                datafile.argument('skeleton', skelpath)
                datafile.argument('name', group)
                nodepairs = [
                    seg.nodes()
                    for seg in skelcontext.segmentgroups.get_group(group)
                ]
                datafile.argument('segments', [(nodedict[n1], nodedict[n2])
                                               for (n1, n2) in nodepairs])
                datafile.endCmd()

            # Materials assigned to Element Groups.  If a Material
            # isn't assigned to pixels in the Microstructure, be sure
            # to save the Material's definition first.
            msmatls = ooflib.SWIG.engine.material.getMaterials(skeleton.MS)
            groupmats = skelcontext.elementgroups.getAllMaterials()
            # skelmatls is a list of Materials used in the Skeleton
            # that aren't in the Microstructure.
            skelmatls = [m for (g, m) in groupmats if m not in msmatls]
            # Construct a list of Properties already defined in the
            # data file, so that they're not written twice.
            excludeProps = {}
            for mat in msmatls:
                for prop in mat.properties():
                    excludeProps[prop.registration().name()] = prop
            materialmenu.writeMaterials(datafile, skelmatls, excludeProps)
            # Now assign Materials to Groups.
            for group, material in groupmats:
                datafile.startCmd(skelmenu.AddMaterialToGroup)
                datafile.argument('skeleton', skelpath)
                datafile.argument('group', group)
                datafile.argument('material', material.name())
                datafile.endCmd()

            # Pinned nodes
            datafile.startCmd(skelmenu.PinnedNodes)
            datafile.argument('skeleton', skelpath)
            datafile.argument('nodes', [
                nodedict[node] for node in skelcontext.pinnednodes.retrieve()
            ])
            datafile.endCmd()

        # Point boundaries
        # sort keys to print in a consistent order
        sortedKeys = skeleton.pointboundaries.keys()
        sortedKeys.sort()
        #for pbname, pbdy in skeleton.pointboundaries.items():
        for pbname in sortedKeys:
            pbdy = skeleton.pointboundaries[pbname]
            datafile.startCmd(skelmenu.PointBoundary)
            datafile.argument('skeleton', skelpath)
            datafile.argument('name', pbname)
            datafile.argument('nodes', [nodedict[node] for node in pbdy.nodes])
            exterior = 0
            if isinstance(pbdy,
                          skeletonboundary.ExteriorSkeletonPointBoundary):
                exterior = 1
            datafile.argument('exterior', exterior)
            datafile.endCmd()

        # Edge boundaries
        # sort keys to print in a consistent order
        sortedKeys = skeleton.edgeboundaries.keys()
        sortedKeys.sort()
        # for ebname, ebdy in skeleton.edgeboundaries.items():
        for ebname in sortedKeys:
            ebdy = skeleton.edgeboundaries[ebname]
            datafile.startCmd(skelmenu.EdgeBoundary)
            datafile.argument('skeleton', skelpath)
            datafile.argument('name', ebname)
            #Interface branch
            if ebdy._sequenceable == 1:
                edgeset = rearrangeEdges([
                    tuple([nodedict[x] for x in edge.get_nodes()])
                    for edge in ebdy.edges
                ])
            else:
                edgeset = [
                    tuple([nodedict[x] for x in edge.get_nodes()])
                    for edge in ebdy.edges
                ]
            datafile.argument('edges', edgeset)
            exterior = 0
            if isinstance(ebdy, skeletonboundary.ExteriorSkeletonEdgeBoundary):
                exterior = 1
            datafile.argument('exterior', exterior)
            datafile.endCmd()

            #Interface branch
            interfacematname = skelcontext.getBoundary(
                ebname)._interfacematerial
            if interfacematname is not None:
                datafile.startCmd(OOF.LoadData.Material.Interface.Assign)
                datafile.argument('microstructure', skeleton.MS.name())
                datafile.argument('material', interfacematname)
                datafile.argument('interfaces',
                                  [skelcontext.name() + ":" + ebname])
                datafile.endCmd()

    finally:
        skelcontext.end_reading()