SubgraphCalculator.GetSubgraphAsNewGraph() loses metadata

Feb 25, 2011 at 3:03 AM

Hi, I have some trouble with metada. I'm trying to devide a bigger graph into sub-graphs with clustering and to save each sub-graph. From the vertices of each returned community I recreate a sub-graph by passing the vertices to the SubgraphCalculator. While the metadata are preserved within the returned community, the get lost when I create the sub-graph.

Any ideas how to transfer the metadata from the parent graph to the sub-graph.

Here thecode:

 MyGraphAdapter _graphAdapter = new MyGraphAdapter();

  IGraph graph = _graphAdapter.LoadGraphFromFile(currentFile.FullName);
                    cc.Algorithm = ClusterAlgorithm.WakitaTsurumi;
                    var cl = cc.CalculateGraphMetrics(graph);
                    foreach (var community in cl)
                        var subGraph = SubgraphCalculator.GetSubgraphAsNewGraph(community.Vertices);
//the subGraph doesn't contain any metadata anymore
Feb 25, 2011 at 4:47 AM
Edited Feb 25, 2011 at 4:48 AM


Yes, as indicated in the documentation, GetSubgraphAsNewGraph(), does not copy the metadata.  I've added an item to our feature request list to make copying the metadata an option.

In the meantime, if you give each vertex a unique Name, you can always retrieve the metadata from the original graph.  For example, to retrieve the metadata for one of the vertices in the new graph, you could do this:

IVertex originalVertex;
originalGraph.Vertices.Find(newVertex.Name, out originalVertex);
Object originalMetadata = originalVertex.GetValue("MyMetadata");

This will be slow for very large graphs because Vertex.Find() does a linear search, but you can always speed it up by first creating a Dictionary<String, IVertex> that maps vertex names to original vertices, then using the Dictionary instead of Find() to find the original vertices.

Unfortunately, this won't work for edges because GetSubgraphAsNewGraph() forgets to copy the Name for edges.  That will be fixed in the next release.  If you need this fixed now, you can make a copy of SubgraphCalculator.cs, rename the class, and insert the line "oNewEdge.Name = oIncidentEdge.Name;" at line 242.

-- Tony

Feb 25, 2011 at 4:11 PM

Thanks, that works.

Just for curiousity, why has a graph always emtpy edges? I have to do a 'is null' check when I get the edges out of graph, like this:

var edgeLookup = graph.Edges.Where(x=>x!=null).ToDictionary(x => x.Name);

Feb 27, 2011 at 5:57 PM

There cannot be null edges in the Graph.Edges collection.  In the following test code, the ToDictionary() line worked fine for me without checking for null.  In your case, exactly what happens when you leave out the check for null?

-- Tony

using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.NodeXL.Core;

namespace ConsoleApplication1
    class Program
        static void Main(string[] args)
            const Int32 Vertices = 100;
            const Int32 Edges = 100;
            IGraph oGraph = new Graph(GraphDirectedness.Undirected);
            IVertexCollection oVertices = oGraph.Vertices;
            IVertex[] aoAddedVertices = new IVertex[Vertices];
            IEdgeCollection oEdges = oGraph.Edges;

            for (Int32 i = 0; i < Vertices; i++)
                aoAddedVertices[i] = oVertices.Add();

            for (Int32 i = 0; i < Edges; i++)
                oEdges.Add(aoAddedVertices[0], aoAddedVertices[i]).Name = "Edge" + i.ToString();

            Dictionary<String, IEdge> oDictionary = oEdges.Where(x => true).ToDictionary(x => x.Name);