Base class for a family of classes that store an entire column of graph metric values.
The derived classes differ in how the graph metric values are mapped to worksheet rows.
Inheritance: Object
Example #1
0
        TryCreateStackedTable
        (
            Microsoft.Office.Interop.Excel.Workbook oWorkbook,
            String sWorksheetName,
            GraphMetricColumn oGraphMetricColumn,
            out ListObject oStackedTable
        )
        {
            Debug.Assert(oWorkbook != null);
            Debug.Assert(!String.IsNullOrEmpty(sWorksheetName));
            Debug.Assert(oGraphMetricColumn != null);
            AssertValid();

            oStackedTable = null;
            Worksheet oWorksheet;
            Range     oColumnARange;

            if (
                !ExcelUtil.TryGetOrAddWorksheet(oWorkbook, sWorksheetName,
                                                out oWorksheet)
                ||
                !ExcelUtil.TryGetRange(oWorksheet, "A:A", out oColumnARange)
                )
            {
                return(false);
            }

            try
            {
                // The worksheet can contain multiple top-N-by tables, so we need
                // to find where to put the new table.

                Range oColumn1HeaderCell = GetColumn1HeaderCellForStackedTable(
                    oWorksheet, oColumnARange);

                // Create just the first column.  The table will auto-expand when
                // this class adds the table's other column.
                //
                // (It's assumed here that oGraphMetricColumn represents the
                // table's first column.)

                oColumn1HeaderCell.set_Value(Missing.Value,
                                             oGraphMetricColumn.ColumnName);

                Range oTableRange = oColumn1HeaderCell;
                ExcelUtil.ResizeRange(ref oTableRange, 2, 1);

                oStackedTable = ExcelTableUtil.AddTable(oWorksheet, oTableRange,
                                                        oGraphMetricColumn.TableName, TableStyleNames.NodeXLTable);

                ExcelTableUtil.SetColumnWidth(oColumn1HeaderCell,
                                              oGraphMetricColumn.ColumnWidthChars);
            }
            catch (System.Runtime.InteropServices.COMException)
            {
                return(false);
            }

            return(true);
        }
    TryCalculateWordMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        String statusColumnName,
        out GraphMetricColumn [] wordMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        Debug.Assert( !String.IsNullOrEmpty(statusColumnName) );

        // Use the WordMetricCalculator2() class to calculate word metrics for
        // all groups.
        //
        // This is somewhat wasteful, because we don't actually need all the
        // word metrics for all groups.  A future version might refactor common
        // code out of WordMetricCalculator2() that can be called by that class
        // and this one.

        GraphMetricUserSettings oGraphMetricUserSettings =
            calculateGraphMetricsContext.GraphMetricUserSettings;

        WordMetricUserSettings oWordMetricUserSettings =
            oGraphMetricUserSettings.WordMetricUserSettings;

        GraphMetrics eOriginalGraphMetricsToCalculate =
            oGraphMetricUserSettings.GraphMetricsToCalculate;

        Boolean bOriginalTextColumnIsOnEdgeWorksheet =
            oWordMetricUserSettings.TextColumnIsOnEdgeWorksheet;

        String sOriginalTextColumnName =
            oWordMetricUserSettings.TextColumnName;

        Boolean bOriginalCountByGroup = oWordMetricUserSettings.CountByGroup;

        oGraphMetricUserSettings.GraphMetricsToCalculate = GraphMetrics.Words;
        oWordMetricUserSettings.TextColumnIsOnEdgeWorksheet = true;
        oWordMetricUserSettings.TextColumnName = statusColumnName;
        oWordMetricUserSettings.CountByGroup = true;

        try
        {
            return ( ( new WordMetricCalculator2() ).TryCalculateGraphMetrics(
                graph, calculateGraphMetricsContext, out wordMetricColumns) );
        }
        finally
        {
            oGraphMetricUserSettings.GraphMetricsToCalculate =
                eOriginalGraphMetricsToCalculate;

            oWordMetricUserSettings.TextColumnIsOnEdgeWorksheet =
                bOriginalTextColumnIsOnEdgeWorksheet;

            oWordMetricUserSettings.TextColumnName = sOriginalTextColumnName;
            oWordMetricUserSettings.CountByGroup = bOriginalCountByGroup;
        }
    }
        TryCalculateGraphMetrics
        (
            IGraph graph,
            CalculateGraphMetricsContext calculateGraphMetricsContext,
            out GraphMetricColumn [] graphMetricColumns
        )
        {
            Debug.Assert(graph != null);
            Debug.Assert(calculateGraphMetricsContext != null);
            AssertValid();

            graphMetricColumns = new GraphMetricColumn[0];

            // Attempt to retrieve the group information the WorkbookReader object
            // may have stored as metadata on the graph.

            GroupInfo [] aoGroups;

            if (
                !calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
                    GraphMetrics.GroupMetrics)
                ||
                !GroupUtil.TryGetGroups(graph, out aoGroups)
                )
            {
                return(true);
            }

            // Count the edges using the IntergroupEdgeCalculator class in the
            // Algorithms namespace, which knows nothing about Excel.

            IList <IntergroupEdgeInfo> oIntergroupEdges;

            if (!(new Algorithms.IntergroupEdgeCalculator()).
                TryCalculateGraphMetrics(graph,
                                         calculateGraphMetricsContext.BackgroundWorker, aoGroups, true,
                                         out oIntergroupEdges))
            {
                // The user cancelled.

                return(false);
            }

            // Add a row to the group-edge table for each pair of groups that has
            // edges.

            graphMetricColumns = CreateGraphMetricColumns(
                AddRows(aoGroups, oIntergroupEdges));

            return(true);
        }
Example #4
0
        TryCalculateGraphMetrics
        (
            IGraph graph,
            CalculateGraphMetricsContext calculateGraphMetricsContext,
            out GraphMetricColumn [] graphMetricColumns
        )
        {
            Debug.Assert(graph != null);
            Debug.Assert(calculateGraphMetricsContext != null);
            AssertValid();

            graphMetricColumns = new GraphMetricColumn[0];

            if (
                graph.Directedness != GraphDirectedness.Directed
                ||
                !calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
                    GraphMetrics.ReciprocatedVertexPairRatio)
                )
            {
                return(true);
            }

            // Calculate the metric for each vertex using the
            // ReciprocatedVertexPairRatioCalculator class in the Algorithms
            // namespace, which knows nothing about Excel.

            Dictionary <Int32, Nullable <Double> > oReciprocatedVertexPairRatios;

            if (!(new Algorithms.ReciprocatedVertexPairRatioCalculator()).
                TryCalculateGraphMetrics(graph,
                                         calculateGraphMetricsContext.BackgroundWorker,
                                         out oReciprocatedVertexPairRatios))
            {
                // The user cancelled.

                return(false);
            }

            graphMetricColumns = new GraphMetricColumn [] {
                CreateGraphMetricColumn(graph, oReciprocatedVertexPairRatios)
            };

            return(true);
        }
    TryCountTermsNoGroups
    (
        IGraph oGraph,
        WordMetricUserSettings oWordMetricUserSettings,
        WordCounter oWordCounter,
        WordPairCounter oWordPairCounter,
        HashSet<String> oUniqueImportedIDs,
        out GraphMetricColumn [] oGraphMetricColumns
    )
    {
        Debug.Assert(oGraph != null);
        Debug.Assert(oWordMetricUserSettings != null);
        Debug.Assert(oWordCounter != null);
        Debug.Assert(oWordPairCounter != null);
        AssertValid();

        Boolean bTextColumnIsOnEdgeWorksheet =
            oWordMetricUserSettings.TextColumnIsOnEdgeWorksheet;

        System.Collections.IEnumerable oEdgesOrVertices =
            bTextColumnIsOnEdgeWorksheet ?
            (System.Collections.IEnumerable)oGraph.Edges :
            (System.Collections.IEnumerable)oGraph.Vertices;

        // Count the terms in each of the column's cells.

        foreach ( IMetadataProvider oEdgeOrVertex in EnumerateEdgesOrVertices(
            oEdgesOrVertices, bTextColumnIsOnEdgeWorksheet, oGraph,
            oUniqueImportedIDs) )
        {
            CountTermsInEdgeOrVertex(oEdgeOrVertex,
                oWordMetricUserSettings.TextColumnName, oWordCounter,
                oWordPairCounter);
        }

        oWordCounter.CalculateSalienceOfCountedTerms();
        oWordPairCounter.CalculateSalienceOfCountedTerms();
        oWordPairCounter.CalculateMutualInformationOfCountedTerms();

        // Transfer the words and word pairs to graph metric value lists.

        List<GraphMetricValueOrdered> oWordWordValues, oWordCountValues,
            oWordSalienceValues;

        List<GraphMetricValueOrdered> oWordPairWord1Values,
            oWordPairWord2Values, oWordPairCountValues,
            oWordPairSalienceValues, oWordPairMutualInformationValues;

        CreateGraphMetricValueLists(
            out oWordWordValues, out oWordCountValues, out oWordSalienceValues,
            
            out oWordPairWord1Values, out oWordPairWord2Values,
            out oWordPairCountValues, out oWordPairSalienceValues,
            out oWordPairMutualInformationValues
            );

        foreach (CountedWord oCountedWord in oWordCounter.CountedTerms)
        {
            AddCountedWordToValueLists(oCountedWord, oWordMetricUserSettings,
                oWordWordValues, oWordCountValues, oWordSalienceValues);
        }

        foreach (CountedWordPair oCountedWordPair in
            oWordPairCounter.CountedTerms)
        {
            AddCountedWordPairToValueLists(oCountedWordPair,
                oWordMetricUserSettings, oWordPairWord1Values,
                oWordPairWord2Values, oWordPairCountValues,
                oWordPairSalienceValues, oWordPairMutualInformationValues);
        }

        oGraphMetricColumns = CreateGraphMetricColumns(
            oWordWordValues, oWordCountValues, oWordSalienceValues, null,

            oWordPairWord1Values, oWordPairWord2Values, oWordPairCountValues,
            oWordPairSalienceValues, oWordPairMutualInformationValues, null
            );

        return (true);
    }
    TryCountEdgeTermsByGroup
    (
        IGraph oGraph,
        WordMetricUserSettings oWordMetricUserSettings,
        WordCounter oWordCounter,
        WordPairCounter oWordPairCounter,
        HashSet<String> oUniqueImportedIDs,
        out GraphMetricColumn [] oGraphMetricColumns
    )
    {
        Debug.Assert(oGraph != null);
        Debug.Assert(oWordMetricUserSettings != null);
        Debug.Assert(oWordCounter != null);
        Debug.Assert(oWordPairCounter != null);
        AssertValid();

        List<GraphMetricValueOrdered> oWordWordValues, oWordCountValues,
            oWordSalienceValues;

        List<GraphMetricValueOrdered> oWordPairWord1Values,
            oWordPairWord2Values, oWordPairCountValues,
            oWordPairSalienceValues, oWordPairMutualInformationValues;

        CreateGraphMetricValueLists(
            out oWordWordValues, out oWordCountValues, out oWordSalienceValues,
            
            out oWordPairWord1Values, out oWordPairWord2Values,
            out oWordPairCountValues, out oWordPairSalienceValues,
            out oWordPairMutualInformationValues
            );

        List<GraphMetricValueOrdered> oWordGroupNameValues =
            new List<GraphMetricValueOrdered>();

        List<GraphMetricValueOrdered> oWordPairGroupNameValues =
            new List<GraphMetricValueOrdered>();

        // Get the edges in each of the graph's groups.  Include a "dummy"
        // group that contains the edges that aren't contained in any real
        // groups.

        foreach ( GroupEdgeInfo oGroupEdgeInfo in
            GroupEdgeSorter.SortGroupEdges(oGraph, Int32.MaxValue,
                true, true) )
        {
            // Count the terms in this group.

            oWordCounter.Clear();
            oWordPairCounter.Clear();

            foreach ( IEdge oEdge in EnumerateEdgesOrVertices(
                oGroupEdgeInfo.Edges, true, oGraph, oUniqueImportedIDs) )
            {
                CountTermsInEdgeOrVertex(oEdge,
                    oWordMetricUserSettings.TextColumnName, oWordCounter,
                    oWordPairCounter);
            }

            oWordCounter.CalculateSalienceOfCountedTerms();
            oWordPairCounter.CalculateSalienceOfCountedTerms();
            oWordPairCounter.CalculateMutualInformationOfCountedTerms();

            // Transfer the words and word pairs to the graph metric value
            // lists.

            String sGroupName = oGroupEdgeInfo.GroupName;

            AddCountedWordsToValueLists( oWordCounter.CountedTerms,
                oWordMetricUserSettings, sGroupName, oWordWordValues,
                oWordCountValues, oWordSalienceValues, oWordGroupNameValues);

            AddCountedWordPairsToValueLists( oWordPairCounter.CountedTerms,
                oWordMetricUserSettings, sGroupName, oWordPairWord1Values,
                oWordPairWord2Values, oWordPairCountValues,
                oWordPairSalienceValues, oWordPairMutualInformationValues,
                oWordPairGroupNameValues);

            if (
                sGroupName == GroupEdgeSorter.DummyGroupNameForEntireGraph
                &&
                oUniqueImportedIDs != null
                )
            {
                // This is the dummy group that stores all the edges in the
                // graph.  Note that SortGroupEdges() guarantees that this is
                // the first group, so the imported IDs need to be cleared only
                // once within this loop.

                oUniqueImportedIDs.Clear();
            }
        }

        oGraphMetricColumns = CreateGraphMetricColumns(
            oWordWordValues, oWordCountValues, oWordSalienceValues,
            oWordGroupNameValues,
        
            oWordPairWord1Values, oWordPairWord2Values, oWordPairCountValues,
            oWordPairSalienceValues, oWordPairMutualInformationValues,
            oWordPairGroupNameValues
            );

        return (true);
    }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        AssertValid();

        graphMetricColumns = new GraphMetricColumn[0];

        BackgroundWorker oBackgroundWorker =
            calculateGraphMetricsContext.BackgroundWorker;

        ReadabilityMetricUserSettings oReadabilityMetricUserSettings =
            new ReadabilityMetricUserSettings();

        IGraph oGraphClone = CloneAndFilterGraph(graph);

        // The key is an IEdge and the value is the number of edges that cross
        // the edge.

        Dictionary<IEdge, Int32> oEdgeInformation;

        // The key is an IVertex and the value is a VertexInformation object.

        Dictionary<IVertex, VertexInformation> oVertexInformations;

        // Future improvement: Calculate edge and vertex information only when
        // necessary, based on the metrics selected by the user.

        LinkedList<GraphMetricColumn> oGraphMetricColumns =
            new LinkedList<GraphMetricColumn>();

        if (
            !TryCalculateEdgeInformation(oGraphClone, oBackgroundWorker,
                out oEdgeInformation)
            ||
            !TryCalculateVertexInformations(oGraphClone, oBackgroundWorker,
                out oVertexInformations)
            ||
            !TryCalculatePerEdgeAndPerVertexMetrics(oGraphClone, graph,
                oReadabilityMetricUserSettings, oBackgroundWorker,
                oEdgeInformation, oVertexInformations, oGraphMetricColumns)
            ||
            !TryCalculateOverallMetrics(oGraphClone,
                oReadabilityMetricUserSettings, oBackgroundWorker,
                oEdgeInformation, oVertexInformations, oGraphMetricColumns)
            )
        {
            // The user cancelled.

            return (false);
        }

        graphMetricColumns = oGraphMetricColumns.ToArray();

        return (true);
    }
    WriteGraphMetricColumnsToWorkbook
    (
        GraphMetricColumn [] graphMetricColumns,
        Microsoft.Office.Interop.Excel.Workbook workbook
    )
    {
        Debug.Assert(graphMetricColumns != null);
        Debug.Assert(workbook != null);
        AssertValid();

        // Clear any worksheets that must be cleared before anything else is
        // done.

        ClearWorksheets(graphMetricColumns, workbook);

        // (Note: Don't sort grapMetricColumns by worksheet name/table name in
        // an effort to minimize worksheet switches in the code below.  That
        // would interfere with the column order specified by the
        // IGraphMetricCalculator2 implementations.

        // Create a dictionary of tables that have been written to.  The key is
        // the worksheet name + table name, and the value is a WrittenTableInfo
        // object that contains information about the table.

        Dictionary<String, WrittenTableInfo> oWrittenTables =
            new Dictionary<String, WrittenTableInfo>();

        // Loop through the columns.

        String sCurrentWorksheetPlusTable = String.Empty;
        ListObject oTable = null;

        foreach (GraphMetricColumn oGraphMetricColumn in graphMetricColumns)
        {
            String sThisWorksheetPlusTable = oGraphMetricColumn.WorksheetName
                + oGraphMetricColumn.TableName;

            if (sThisWorksheetPlusTable != sCurrentWorksheetPlusTable)
            {
                // This is a different table.  Get its ListObject.

                if ( !TryGetTable(workbook, oGraphMetricColumn, out oTable) )
                {
                    continue;
                }

                sCurrentWorksheetPlusTable = sThisWorksheetPlusTable;
            }

            WrittenTableInfo oWrittenTableInfo;

            if ( !oWrittenTables.TryGetValue(sThisWorksheetPlusTable,
                out oWrittenTableInfo) )
            {
                // Show all the table's columns.  If a graph metric column
                // isn't visible, it can't be written to.

                ExcelHiddenColumns oExcelHiddenColumns =
                    ExcelColumnHider.ShowHiddenColumns(oTable);

                oWrittenTableInfo = new WrittenTableInfo();
                oWrittenTableInfo.Table = oTable;
                oWrittenTableInfo.HiddenColumns = oExcelHiddenColumns;
                oWrittenTableInfo.Cleared = false;

                oWrittenTables.Add(sThisWorksheetPlusTable, oWrittenTableInfo);
            }

            // Apparent Excel bug: Adding a column when the header row is not
            // the default row height increases the header row height.  Work
            // around this by saving the height and restoring it below.

            Double dHeaderRowHeight = (Double)oTable.HeaderRowRange.RowHeight;

            // Write the column.

            Debug.Assert(oTable != null);

            if (oGraphMetricColumn is GraphMetricColumnWithID)
            {
                WriteGraphMetricColumnWithIDToWorkbook(
                    (GraphMetricColumnWithID)oGraphMetricColumn, oTable);
            }
            else if (oGraphMetricColumn is GraphMetricColumnOrdered)
            {
                if (!oWrittenTableInfo.Cleared)
                {
                    // GraphMetricColumnOrdered columns require that the table
                    // be cleared before any graph metric values are written to
                    // it.

                    ExcelTableUtil.ClearTable(oTable);
                    oWrittenTableInfo.Cleared = true;

                    // Clear AutoFiltering, which interferes with writing an
                    // ordered list to the column.

                    ExcelTableUtil.ClearTableAutoFilters(oTable);
                }

                WriteGraphMetricColumnOrderedToWorkbook(
                    (GraphMetricColumnOrdered)oGraphMetricColumn, oTable);
            }
            else
            {
                Debug.Assert(false);
            }

            oTable.HeaderRowRange.RowHeight = dHeaderRowHeight;
        }

        // Restore any hidden columns in the tables that were written to.

        foreach (KeyValuePair<String, WrittenTableInfo> oKeyValuePair in
            oWrittenTables)
        {
            WrittenTableInfo oWrittenTableInfo = oKeyValuePair.Value;

            ExcelColumnHider.RestoreHiddenColumns(oWrittenTableInfo.Table,
                oWrittenTableInfo.HiddenColumns);
        }
    }
    ClearWorksheets
    (
        GraphMetricColumn [] aoGraphMetricColumns,
        Microsoft.Office.Interop.Excel.Workbook oWorkbook
    )
    {
        Debug.Assert(aoGraphMetricColumns != null);
        Debug.Assert(oWorkbook != null);
        AssertValid();

        // The top-N-by and top Twitter search network item worksheets can
        // contain multiple tables, one below the other.  If one of the tables
        // has more rows than before, Excel will raise an error when the table
        // is written again, because it would overlap the next table.  Clear
        // the entire worksheet so that all the tables are written from
        // scratch.

        foreach (String sWorksheetName in new String [] {
            WorksheetNames.TopNByMetrics,
            WorksheetNames.TwitterSearchNetworkTopItems,
            } )
        {
            if ( GraphMetricColumnsIncludeWorksheet(aoGraphMetricColumns,
                sWorksheetName) )
            {
                ExcelUtil.TryClearWorksheet(oWorkbook, sWorksheetName);
            }
        }
    }
Example #10
0
        TryGetRequiredColumnInformation
        (
            GraphMetricColumn oGraphMetricColumn,
            ListObject oTable,
            out Range oVisibleColumnData
        )
        {
            Debug.Assert(oGraphMetricColumn != null);
            Debug.Assert(oTable != null);
            AssertValid();

            oVisibleColumnData = null;

            // Add the specified column if it's not already present.

            String sColumnName  = oGraphMetricColumn.ColumnName;
            String sColumnStyle = oGraphMetricColumn.Style;

            Microsoft.Office.Interop.Excel.ListColumn oColumn;

            if (
                !ExcelTableUtil.TryGetTableColumn(oTable, sColumnName, out oColumn)
                &&
                !ExcelTableUtil.TryAddTableColumn(oTable, sColumnName,
                                                  oGraphMetricColumn.ColumnWidthChars, sColumnStyle, out oColumn)
                )
            {
                // Give up.

                return(false);
            }

            Range oColumnData;

            if (!ExcelTableUtil.TryGetTableColumnData(oTable, sColumnName,
                                                      out oColumnData))
            {
                return(false);
            }

            ExcelUtil.SetRangeStyle(oColumnData, sColumnStyle);

            String sNumberFormat = oGraphMetricColumn.NumberFormat;

            if (sNumberFormat != null)
            {
                oColumnData.NumberFormat = sNumberFormat;
            }

            // Wrapping text makes Range.set_Value() very slow, so turn it off.

            oColumn.Range.WrapText = false;

            // But wrap the text in the column's header.

            ExcelTableUtil.WrapTableColumnHeader(oColumn);

            // Get the visible range.

            if (!ExcelUtil.TryGetVisibleRange(oColumnData,
                                              out oVisibleColumnData))
            {
                return(false);
            }

            return(true);
        }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        AssertValid();

        graphMetricColumns = new GraphMetricColumn[0];

        if (
            graph.Directedness != GraphDirectedness.Directed
            ||
            !calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
                GraphMetrics.ReciprocatedVertexPairRatio)
            )
        {
            return (true);
        }

        // Calculate the metric for each vertex using the
        // ReciprocatedVertexPairRatioCalculator class in the Algorithms
        // namespace, which knows nothing about Excel.

        Dictionary< Int32, Nullable<Double> > oReciprocatedVertexPairRatios;

        if ( !( new Algorithms.ReciprocatedVertexPairRatioCalculator() ).
            TryCalculateGraphMetrics(graph,
                calculateGraphMetricsContext.BackgroundWorker,
                out oReciprocatedVertexPairRatios) )
        {
            // The user cancelled.

            return (false);
        }

        graphMetricColumns = new GraphMetricColumn [] {
            CreateGraphMetricColumn(graph, oReciprocatedVertexPairRatios)
            };

        return (true);
    }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,

        Algorithms.OneDoubleGraphMetricCalculatorBase
            oneDoubleGraphMetricCalculator,

        GraphMetrics graphMetric,
        String columnName,
        Double columnWidthChars,
        String style,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        Debug.Assert(oneDoubleGraphMetricCalculator != null);
        Debug.Assert( !String.IsNullOrEmpty(columnName) );

        Debug.Assert(columnWidthChars == ExcelTableUtil.AutoColumnWidth ||
            columnWidthChars > 0);

        AssertValid();

        graphMetricColumns = new GraphMetricColumn[0];

        if ( !calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
            graphMetric) )
        {
            return (true);
        }

        // Calculate the graph metrics for each vertex using the
        // OneDoubleGraphMetricCalculatorBase object, which knows nothing about
        // Excel.

        Dictionary<Int32, Double> oGraphMetrics;

        if ( !oneDoubleGraphMetricCalculator.TryCalculateGraphMetrics(graph,
            calculateGraphMetricsContext.BackgroundWorker, out oGraphMetrics) )
        {
            // The user cancelled.

            return (false);
        }

        // Transfer the graph metrics to an array of GraphMetricValue objects.

        List<GraphMetricValueWithID> oGraphMetricValues =
            new List<GraphMetricValueWithID>();

        foreach (IVertex oVertex in graph.Vertices)
        {
            // Try to get the row ID stored in the worksheet.

            Int32 iRowID;

            if ( TryGetRowID(oVertex, out iRowID) )
            {
                oGraphMetricValues.Add( new GraphMetricValueWithID(
                    iRowID, oGraphMetrics[oVertex.ID] ) );
            }
        }

        graphMetricColumns = new GraphMetricColumn [] {
            new GraphMetricColumnWithID( WorksheetNames.Vertices,
                TableNames.Vertices, columnName, columnWidthChars,
                NumericFormat, style, oGraphMetricValues.ToArray()
                ) };

        return (true);
    }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        AssertValid();

        List<GraphMetricColumn> oGraphMetricColumns =
            new List<GraphMetricColumn>();

        Boolean bCancelled = false;

        if ( calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
            this.GraphMetricToCalculate) )
        {
            bCancelled = !TryCalculateGraphMetricsInternal(graph,
                calculateGraphMetricsContext, oGraphMetricColumns);
        }

        graphMetricColumns = oGraphMetricColumns.ToArray();

        return (!bCancelled);
    }
        TryCalculateGraphMetrics
        (
            IGraph graph,
            CalculateGraphMetricsContext calculateGraphMetricsContext,
            out GraphMetricColumn [] graphMetricColumns
        )
        {
            Debug.Assert(graph != null);
            Debug.Assert(calculateGraphMetricsContext != null);
            AssertValid();

            graphMetricColumns = new GraphMetricColumn[0];

            if (!calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
                    GraphMetrics.Degree |
                    GraphMetrics.InDegree |
                    GraphMetrics.OutDegree
                    ))
            {
                return(true);
            }

            IVertexCollection oVertices = graph.Vertices;
            Int32             iVertices = oVertices.Count;

            // The following lists correspond to vertex worksheet columns.

            List <GraphMetricValueWithID> oInDegreeGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID> oOutDegreeGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID> oDegreeGraphMetricValues =
                new List <GraphMetricValueWithID>();

            // Create a dictionary to keep track of vertex degrees.  The key is the
            // IVertex.ID and the value is a zero-based index into the above lists.

            Dictionary <Int32, Int32> oVertexIDDictionary =
                new Dictionary <Int32, Int32>();

            // Calculate the degrees for each vertex using the
            // VertexDegreeCalculator class in the Algorithms namespace, which
            // knows nothing about Excel.
            //
            // For simplicity, all degree metrics (in-degree, out-degree, and
            // degree) are calculated regardless of whether the graph is directed
            // or undirected.  After all metrics are calculated,
            // FilterGraphMetricColumns() filters out the metrics that don't apply
            // to the graph, based on its directedness.

            Dictionary <Int32, VertexDegrees> oVertexDegreeDictionary;

            if (!(new Algorithms.VertexDegreeCalculator()).
                TryCalculateGraphMetrics(graph,
                                         calculateGraphMetricsContext.BackgroundWorker,
                                         out oVertexDegreeDictionary))
            {
                // The user cancelled.

                return(false);
            }

            Int32 iRowID;

            foreach (IVertex oVertex in oVertices)
            {
                if (!TryGetRowID(oVertex, out iRowID))
                {
                    continue;
                }

                VertexDegrees oVertexDegrees;

                if (!oVertexDegreeDictionary.TryGetValue(oVertex.ID,
                                                         out oVertexDegrees))
                {
                    Debug.Assert(false);
                }

                oInDegreeGraphMetricValues.Add(new GraphMetricValueWithID(
                                                   iRowID, oVertexDegrees.InDegree));

                oOutDegreeGraphMetricValues.Add(new GraphMetricValueWithID(
                                                    iRowID, oVertexDegrees.OutDegree));

                oDegreeGraphMetricValues.Add(new GraphMetricValueWithID(
                                                 iRowID, oVertexDegrees.Degree));

                Debug.Assert(oInDegreeGraphMetricValues.Count ==
                             oOutDegreeGraphMetricValues.Count);

                oVertexIDDictionary.Add(oVertex.ID,
                                        oInDegreeGraphMetricValues.Count - 1);
            }

            // Figure out which columns to add.

            graphMetricColumns = FilterGraphMetricColumns(graph,
                                                          calculateGraphMetricsContext, oInDegreeGraphMetricValues,
                                                          oOutDegreeGraphMetricValues, oDegreeGraphMetricValues);

            return(true);
        }
        TryCalculateGraphMetrics
        (
            IGraph graph,
            CalculateGraphMetricsContext calculateGraphMetricsContext,
            out GraphMetricColumn [] graphMetricColumns
        )
        {
            Debug.Assert(graph != null);
            Debug.Assert(calculateGraphMetricsContext != null);
            AssertValid();

            // Note regarding cell styles:
            //
            // Versions of NodeXL earlier than 1.0.1.130 didn't merge duplicate
            // edges before calculating graph metrics, and as a result some metrics
            // were invalid.  That was indicated by applying the CellStyleNames.Bad
            // Excel style to the invalid cells.  Starting in version 1.0.1.130
            // there are no longer invalid metrics, but the
            // CellStyleNames.GraphMetricGood style is always applied to those old
            // potentially bad metric cells (instead of null, which uses the
            // current cell style) in case graph metrics are calculated on an old
            // workbook that had bad metric cells.  If null were used, the old Bad
            // style would always remain on the previously bad cells, even if they
            // are now filled with good metric values.

            graphMetricColumns = new GraphMetricColumn[0];

            if (!calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
                    GraphMetrics.OverallMetrics))
            {
                return(true);
            }

            // Calculate the overall metrics using the OverallMetricCalculator
            // class in the Algorithms namespace, which knows nothing about Excel.

            OverallMetrics oOverallMetrics;

            if (!(new Algorithms.OverallMetricCalculator()).
                TryCalculateGraphMetrics(graph,
                                         calculateGraphMetricsContext.BackgroundWorker,
                                         out oOverallMetrics))
            {
                // The user cancelled.

                return(false);
            }

            OverallMetricRows oOverallMetricRows = new OverallMetricRows();


            //*********************************
            // Graph type
            //*********************************

            AddRow(OverallMetricNames.Directedness,
                   oOverallMetrics.Directedness.ToString(), oOverallMetricRows);


            //*********************************
            // Vertex count
            //*********************************

            AddRow(oOverallMetricRows);

            AddRow(OverallMetricNames.Vertices, oOverallMetrics.Vertices,
                   oOverallMetricRows);


            //*********************************
            // Edge counts
            //*********************************

            AddRow(oOverallMetricRows);

            AddRow(OverallMetricNames.UniqueEdges, oOverallMetrics.UniqueEdges,
                   oOverallMetricRows);

            AddRow(OverallMetricNames.EdgesWithDuplicates,
                   oOverallMetrics.EdgesWithDuplicates, oOverallMetricRows);

            AddRow(OverallMetricNames.TotalEdges, oOverallMetrics.TotalEdges,
                   oOverallMetricRows);


            //*********************************
            // Self-loops
            //*********************************

            AddRow(oOverallMetricRows);

            AddRow(OverallMetricNames.SelfLoops, oOverallMetrics.SelfLoops,
                   oOverallMetricRows);


            //*********************************
            // Reciprocation ratios
            //*********************************

            AddRow(oOverallMetricRows);

            AddRow(OverallMetricNames.ReciprocatedVertexPairRatio,

                   NullableToGraphMetricValue <Double>(
                       oOverallMetrics.ReciprocatedVertexPairRatio),

                   oOverallMetricRows);

            AddRow(OverallMetricNames.ReciprocatedEdgeRatio,

                   NullableToGraphMetricValue <Double>(
                       oOverallMetrics.ReciprocatedEdgeRatio),

                   oOverallMetricRows);


            //*********************************
            // Connected component counts
            //*********************************

            AddRow(oOverallMetricRows);

            AddRow(OverallMetricNames.ConnectedComponents,
                   oOverallMetrics.ConnectedComponents, oOverallMetricRows);

            AddRow(OverallMetricNames.SingleVertexConnectedComponents,
                   oOverallMetrics.SingleVertexConnectedComponents,
                   oOverallMetricRows);

            AddRow(OverallMetricNames.MaximumConnectedComponentVertices,
                   oOverallMetrics.MaximumConnectedComponentVertices,
                   oOverallMetricRows);

            AddRow(OverallMetricNames.MaximumConnectedComponentEdges,
                   oOverallMetrics.MaximumConnectedComponentEdges,
                   oOverallMetricRows);


            //*********************************
            // Geodesic distances
            //*********************************

            AddRow(oOverallMetricRows);

            AddRow(OverallMetricNames.MaximumGeodesicDistance,

                   NullableToGraphMetricValue <Int32>(
                       oOverallMetrics.MaximumGeodesicDistance),

                   oOverallMetricRows);

            AddRow(OverallMetricNames.AverageGeodesicDistance,

                   NullableToGraphMetricValue <Double>(
                       oOverallMetrics.AverageGeodesicDistance),

                   oOverallMetricRows);


            //*********************************
            // Graph density
            //*********************************

            AddRow(oOverallMetricRows);

            AddRow(OverallMetricNames.GraphDensity,
                   NullableToGraphMetricValue <Double>(oOverallMetrics.GraphDensity),
                   oOverallMetricRows);

            AddRow(OverallMetricNames.Modularity,
                   NullableToGraphMetricValue <Double>(oOverallMetrics.Modularity),
                   oOverallMetricRows);


            //*********************************
            // NodeXL version
            //*********************************

            AddRow(oOverallMetricRows);

            AddRow(OverallMetricNames.NodeXLVersion,
                   AssemblyUtil2.GetFileVersion(), oOverallMetricRows);


            graphMetricColumns = new GraphMetricColumn[] {
                CreateGraphMetricColumnOrdered(
                    OverallMetricsTableColumnNames.Name,
                    oOverallMetricRows.MetricNames),

                CreateGraphMetricColumnOrdered(
                    OverallMetricsTableColumnNames.Value,
                    oOverallMetricRows.MetricValues),
            };

            return(true);
        }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        AssertValid();

        graphMetricColumns = new GraphMetricColumn[0];

        if ( !calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
                GraphMetrics.Degree |
                GraphMetrics.InDegree |
                GraphMetrics.OutDegree
            ) )
        {
            return (true);
        }

        IVertexCollection oVertices = graph.Vertices;
        Int32 iVertices = oVertices.Count;

        // The following lists correspond to vertex worksheet columns.

        List<GraphMetricValueWithID> oInDegreeGraphMetricValues =
            new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID> oOutDegreeGraphMetricValues =
            new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID> oDegreeGraphMetricValues =
            new List<GraphMetricValueWithID>();

        // Create a dictionary to keep track of vertex degrees.  The key is the
        // IVertex.ID and the value is a zero-based index into the above lists.

        Dictionary<Int32, Int32> oVertexIDDictionary =
            new Dictionary<Int32, Int32>();

        // Calculate the degrees for each vertex using the
        // VertexDegreeCalculator class in the Algorithms namespace, which
        // knows nothing about Excel.
        //
        // For simplicity, all degree metrics (in-degree, out-degree, and
        // degree) are calculated regardless of whether the graph is directed
        // or undirected.  After all metrics are calculated,
        // FilterGraphMetricColumns() filters out the metrics that don't apply
        // to the graph, based on its directedness.

        Dictionary<Int32, VertexDegrees> oVertexDegreeDictionary;

        if ( !( new Algorithms.VertexDegreeCalculator() ).
            TryCalculateGraphMetrics(graph,
                calculateGraphMetricsContext.BackgroundWorker,
                out oVertexDegreeDictionary) )
        {
            // The user cancelled.

            return (false);
        }

        Int32 iRowID;

        foreach (IVertex oVertex in oVertices)
        {
            if ( !TryGetRowID(oVertex, out iRowID) )
            {
                continue;
            }

            VertexDegrees oVertexDegrees;

            if ( !oVertexDegreeDictionary.TryGetValue(oVertex.ID,
                out oVertexDegrees) )
            {
                Debug.Assert(false);
            }

            oInDegreeGraphMetricValues.Add(new GraphMetricValueWithID(
                iRowID, oVertexDegrees.InDegree) );

            oOutDegreeGraphMetricValues.Add(new GraphMetricValueWithID(
                iRowID, oVertexDegrees.OutDegree) );

            oDegreeGraphMetricValues.Add(new GraphMetricValueWithID(
                iRowID, oVertexDegrees.Degree) );

            Debug.Assert(oInDegreeGraphMetricValues.Count ==
                oOutDegreeGraphMetricValues.Count);

            oVertexIDDictionary.Add(oVertex.ID,
                oInDegreeGraphMetricValues.Count - 1);
        }

        // Figure out which columns to add.

        graphMetricColumns = FilterGraphMetricColumns(graph,
            calculateGraphMetricsContext, oInDegreeGraphMetricValues,
            oOutDegreeGraphMetricValues, oDegreeGraphMetricValues);

        return (true);
    }
        TryCalculateGraphMetrics
        (
            IGraph graph,
            CalculateGraphMetricsContext calculateGraphMetricsContext,
            out GraphMetricColumn [] graphMetricColumns
        )
        {
            Debug.Assert(graph != null);
            Debug.Assert(calculateGraphMetricsContext != null);
            AssertValid();

            graphMetricColumns = new GraphMetricColumn[0];

            // Attempt to retrieve the group information the WorkbookReader object
            // may have stored as metadata on the graph.

            GroupInfo [] aoGroups;

            if (
                !calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
                    GraphMetrics.GroupMetrics)
                ||
                !GroupUtil.TryGetGroups(graph, out aoGroups)
                )
            {
                return(true);
            }

            // The following lists correspond to group worksheet columns.

            List <GraphMetricValueWithID> oVerticesGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID> oUniqueEdgesGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID> oEdgesWithDuplicatesGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID> oTotalEdgesGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID> oSelfLoopsGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID>
            oReciprocatedVertexPairRatioGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID> oReciprocatedEdgeRatioGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID> oConnectedComponentsGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID>
            oSingleVertexConnectedComponentsGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID>
            oMaximumConnectedComponentVerticesGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID>
            oMaximumConnectedComponentEdgesGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID> oMaximumGeodesicDistanceGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID> oAverageGeodesicDistanceGraphMetricValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID> oGraphDensityGraphMetricValues =
                new List <GraphMetricValueWithID>();

            foreach (ExcelTemplateGroupInfo oExcelTemplateGroupInfo in aoGroups)
            {
                ICollection <IVertex> oVertices = oExcelTemplateGroupInfo.Vertices;

                if (oVertices == null || oVertices.Count == 0 ||
                    !oExcelTemplateGroupInfo.RowID.HasValue)
                {
                    continue;
                }

                OverallMetrics oOverallMetrics;

                if (!TryCalculateGraphMetricsForOneGroup(oExcelTemplateGroupInfo,
                                                         calculateGraphMetricsContext, out oOverallMetrics))
                {
                    // The user cancelled.

                    return(false);
                }

                Int32 iRowID = oExcelTemplateGroupInfo.RowID.Value;

                oVerticesGraphMetricValues.Add(new GraphMetricValueWithID(
                                                   iRowID, oOverallMetrics.Vertices));

                oUniqueEdgesGraphMetricValues.Add(new GraphMetricValueWithID(
                                                      iRowID, oOverallMetrics.UniqueEdges));

                oEdgesWithDuplicatesGraphMetricValues.Add(
                    new GraphMetricValueWithID(iRowID,
                                               oOverallMetrics.EdgesWithDuplicates));

                oTotalEdgesGraphMetricValues.Add(new GraphMetricValueWithID(iRowID,
                                                                            oOverallMetrics.TotalEdges));

                oSelfLoopsGraphMetricValues.Add(new GraphMetricValueWithID(iRowID,
                                                                           oOverallMetrics.SelfLoops));

                oReciprocatedVertexPairRatioGraphMetricValues.Add(
                    new GraphMetricValueWithID(iRowID,
                                               OverallMetricCalculator2.NullableToGraphMetricValue <Double>(
                                                   oOverallMetrics.ReciprocatedVertexPairRatio)));

                oReciprocatedEdgeRatioGraphMetricValues.Add(
                    new GraphMetricValueWithID(iRowID,
                                               OverallMetricCalculator2.NullableToGraphMetricValue <Double>(
                                                   oOverallMetrics.ReciprocatedEdgeRatio)));

                oConnectedComponentsGraphMetricValues.Add(
                    new GraphMetricValueWithID(iRowID,
                                               oOverallMetrics.ConnectedComponents));

                oSingleVertexConnectedComponentsGraphMetricValues.Add(
                    new GraphMetricValueWithID(iRowID,
                                               oOverallMetrics.SingleVertexConnectedComponents));

                oMaximumConnectedComponentVerticesGraphMetricValues.Add(
                    new GraphMetricValueWithID(iRowID,
                                               oOverallMetrics.MaximumConnectedComponentVertices));

                oMaximumConnectedComponentEdgesGraphMetricValues.Add(
                    new GraphMetricValueWithID(iRowID,
                                               oOverallMetrics.MaximumConnectedComponentEdges));

                oMaximumGeodesicDistanceGraphMetricValues.Add(
                    new GraphMetricValueWithID(iRowID,
                                               OverallMetricCalculator2.NullableToGraphMetricValue <Int32>(
                                                   oOverallMetrics.MaximumGeodesicDistance)));

                oAverageGeodesicDistanceGraphMetricValues.Add(
                    new GraphMetricValueWithID(iRowID,
                                               OverallMetricCalculator2.NullableToGraphMetricValue <Double>(
                                                   oOverallMetrics.AverageGeodesicDistance)));

                oGraphDensityGraphMetricValues.Add(
                    new GraphMetricValueWithID(iRowID,
                                               OverallMetricCalculator2.NullableToGraphMetricValue <Double>(
                                                   oOverallMetrics.GraphDensity)));
            }

            graphMetricColumns = new GraphMetricColumn [] {
                CreateGraphMetricColumnWithID(
                    GroupTableColumnNames.Vertices,
                    Int32NumericFormat,
                    oVerticesGraphMetricValues),

                CreateGraphMetricColumnWithID(
                    GroupTableColumnNames.UniqueEdges,
                    Int32NumericFormat,
                    oUniqueEdgesGraphMetricValues),

                CreateGraphMetricColumnWithID(
                    GroupTableColumnNames.EdgesWithDuplicates,
                    Int32NumericFormat,
                    oEdgesWithDuplicatesGraphMetricValues),

                CreateGraphMetricColumnWithID(
                    GroupTableColumnNames.TotalEdges,
                    Int32NumericFormat,
                    oTotalEdgesGraphMetricValues),

                CreateGraphMetricColumnWithID(
                    GroupTableColumnNames.SelfLoops,
                    Int32NumericFormat,
                    oSelfLoopsGraphMetricValues),

                CreateGraphMetricColumnWithID(
                    GroupTableColumnNames.ReciprocatedVertexPairRatio,
                    DoubleNumericFormat,
                    oReciprocatedVertexPairRatioGraphMetricValues),

                CreateGraphMetricColumnWithID(
                    GroupTableColumnNames.ReciprocatedEdgeRatio,
                    DoubleNumericFormat,
                    oReciprocatedEdgeRatioGraphMetricValues),

                CreateGraphMetricColumnWithID(
                    GroupTableColumnNames.ConnectedComponents,
                    Int32NumericFormat, oConnectedComponentsGraphMetricValues),

                CreateGraphMetricColumnWithID(
                    GroupTableColumnNames.SingleVertexConnectedComponents,
                    Int32NumericFormat,
                    oSingleVertexConnectedComponentsGraphMetricValues),

                CreateGraphMetricColumnWithID(
                    GroupTableColumnNames.MaximumConnectedComponentVertices,
                    Int32NumericFormat,
                    oMaximumConnectedComponentVerticesGraphMetricValues),

                CreateGraphMetricColumnWithID(
                    GroupTableColumnNames.MaximumConnectedComponentEdges,
                    Int32NumericFormat,
                    oMaximumConnectedComponentEdgesGraphMetricValues),

                CreateGraphMetricColumnWithID(
                    GroupTableColumnNames.MaximumGeodesicDistance,
                    Int32NumericFormat,
                    oMaximumGeodesicDistanceGraphMetricValues),

                CreateGraphMetricColumnWithID(
                    GroupTableColumnNames.AverageGeodesicDistance,
                    DoubleNumericFormat,
                    oAverageGeodesicDistanceGraphMetricValues),

                CreateGraphMetricColumnWithID(
                    GroupTableColumnNames.GraphDensity,
                    DoubleNumericFormat,
                    oGraphDensityGraphMetricValues),
            };

            return(true);
        }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        AssertValid();

        // Note regarding cell styles:
        //
        // Versions of NodeXL earlier than 1.0.1.130 didn't merge duplicate
        // edges before calculating graph metrics, and as a result some metrics
        // were invalid.  That was indicated by applying the CellStyleNames.Bad
        // Excel style to the invalid cells.  Starting in version 1.0.1.130
        // there are no longer invalid metrics, but the
        // CellStyleNames.GraphMetricGood style is always applied to those old
        // potentially bad metric cells (instead of null, which uses the
        // current cell style) in case graph metrics are calculated on an old
        // workbook that had bad metric cells.  If null were used, the old Bad
        // style would always remain on the previously bad cells, even if they
        // are now filled with good metric values.

        graphMetricColumns = new GraphMetricColumn[0];

        if ( !calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
            GraphMetrics.OverallMetrics) )
        {
            return (true);
        }

        // Calculate the overall metrics using the OverallMetricCalculator
        // class in the Algorithms namespace, which knows nothing about Excel.

        OverallMetrics oOverallMetrics;

        if ( !( new Algorithms.OverallMetricCalculator() ).
            TryCalculateGraphMetrics(graph,
                calculateGraphMetricsContext.BackgroundWorker,
                out oOverallMetrics) )
        {
            // The user cancelled.

            return (false);
        }

        OverallMetricRows oOverallMetricRows = new OverallMetricRows();


        //*********************************
        // Graph type
        //*********************************

        AddRow(OverallMetricNames.Directedness,
            oOverallMetrics.Directedness.ToString(), oOverallMetricRows);


        //*********************************
        // Vertex count
        //*********************************

        AddRow(oOverallMetricRows);

        AddRow(OverallMetricNames.Vertices, oOverallMetrics.Vertices,
            oOverallMetricRows);


        //*********************************
        // Edge counts
        //*********************************

        AddRow(oOverallMetricRows);

        AddRow(OverallMetricNames.UniqueEdges, oOverallMetrics.UniqueEdges,
            oOverallMetricRows);

        AddRow(OverallMetricNames.EdgesWithDuplicates,
            oOverallMetrics.EdgesWithDuplicates, oOverallMetricRows);

        AddRow(OverallMetricNames.TotalEdges, oOverallMetrics.TotalEdges,
            oOverallMetricRows);


        //*********************************
        // Self-loops
        //*********************************

        AddRow(oOverallMetricRows);

        AddRow(OverallMetricNames.SelfLoops, oOverallMetrics.SelfLoops,
            oOverallMetricRows);


        //*********************************
        // Reciprocation ratios
        //*********************************

        AddRow(oOverallMetricRows);

        AddRow(OverallMetricNames.ReciprocatedVertexPairRatio,

            NullableToGraphMetricValue<Double>(
                oOverallMetrics.ReciprocatedVertexPairRatio),

            oOverallMetricRows);

        AddRow(OverallMetricNames.ReciprocatedEdgeRatio,

            NullableToGraphMetricValue<Double>(
                oOverallMetrics.ReciprocatedEdgeRatio),

            oOverallMetricRows);


        //*********************************
        // Connected component counts
        //*********************************

        AddRow(oOverallMetricRows);

        AddRow(OverallMetricNames.ConnectedComponents,
            oOverallMetrics.ConnectedComponents, oOverallMetricRows);

        AddRow(OverallMetricNames.SingleVertexConnectedComponents,
            oOverallMetrics.SingleVertexConnectedComponents,
            oOverallMetricRows);

        AddRow(OverallMetricNames.MaximumConnectedComponentVertices,
            oOverallMetrics.MaximumConnectedComponentVertices,
            oOverallMetricRows);

        AddRow(OverallMetricNames.MaximumConnectedComponentEdges,
            oOverallMetrics.MaximumConnectedComponentEdges,
            oOverallMetricRows);


        //*********************************
        // Geodesic distances
        //*********************************

        AddRow(oOverallMetricRows);

        AddRow(OverallMetricNames.MaximumGeodesicDistance,

            NullableToGraphMetricValue<Int32>(
                oOverallMetrics.MaximumGeodesicDistance),

            oOverallMetricRows);

        AddRow(OverallMetricNames.AverageGeodesicDistance,

            NullableToGraphMetricValue<Double>(
                oOverallMetrics.AverageGeodesicDistance),

            oOverallMetricRows);


        //*********************************
        // Graph density
        //*********************************

        AddRow(oOverallMetricRows);

        AddRow(OverallMetricNames.GraphDensity,
            NullableToGraphMetricValue<Double>(oOverallMetrics.GraphDensity),
            oOverallMetricRows);

        AddRow(OverallMetricNames.Modularity,
            NullableToGraphMetricValue<Double>(oOverallMetrics.Modularity),
            oOverallMetricRows);


        //*********************************
        // NodeXL version
        //*********************************

        AddRow(oOverallMetricRows);

        AddRow(OverallMetricNames.NodeXLVersion,
            AssemblyUtil2.GetFileVersion(), oOverallMetricRows);


        graphMetricColumns = new GraphMetricColumn[] {

            CreateGraphMetricColumnOrdered(
                OverallMetricsTableColumnNames.Name,
                oOverallMetricRows.MetricNames),

            CreateGraphMetricColumnOrdered(
                OverallMetricsTableColumnNames.Value,
                oOverallMetricRows.MetricValues),
            };

        return (true);
    }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        AssertValid();

        graphMetricColumns = null;

        // Partition the graph into motifs using the MotifCalculator class in
        // the Algorithms namespace, which knows nothing about Excel.

        Algorithms.MotifCalculator oMotifCalculator =
            new Algorithms.MotifCalculator();

        ICollection<Motif> oMotifs;

        if ( !oMotifCalculator.TryCalculateMotifs(graph,
            m_eMotifsToCalculate, m_iDConnectorMinimumAnchorVertices,
            m_iDConnectorMaximumAnchorVertices,
            m_iCliqueMinimumMemberVertices, m_iCliqueMaximumMemberVertices,
            calculateGraphMetricsContext.BackgroundWorker, out oMotifs) )
        {
            // The user cancelled.

            return (false);
        }

        // Convert the collection of motifs to an array of GraphMetricColumn
        // objects.

        graphMetricColumns =
            GroupsToGraphMetricColumnsConverter.Convert<Motif>(
                oMotifs,
                (oMotif) => oMotif.VerticesInMotif,
                (oMotif) => MotifToGroupName(oMotif),
                true,
                (oMotif) => oMotif.CollapsedAttributes
                );

        return (true);
    }
    TryCreateStackedTable
    (
        Microsoft.Office.Interop.Excel.Workbook oWorkbook,
        String sWorksheetName,
        GraphMetricColumn oGraphMetricColumn,
        out ListObject oStackedTable
    )
    {
        Debug.Assert(oWorkbook != null);
        Debug.Assert( !String.IsNullOrEmpty(sWorksheetName) );
        Debug.Assert(oGraphMetricColumn != null);
        AssertValid();

        oStackedTable = null;
        Worksheet oWorksheet;
        Range oColumnARange;

        if (
            !ExcelUtil.TryGetOrAddWorksheet(oWorkbook, sWorksheetName,
                out oWorksheet)
            ||
            !ExcelUtil.TryGetRange(oWorksheet, "A:A", out oColumnARange)
            )
        {
            return (false);
        }

        try
        {
            // The worksheet can contain multiple top-N-by tables, so we need
            // to find where to put the new table.

            Range oColumn1HeaderCell = GetColumn1HeaderCellForStackedTable(
                oWorksheet, oColumnARange);

            // Create just the first column.  The table will auto-expand when
            // this class adds the table's other column.
            //
            // (It's assumed here that oGraphMetricColumn represents the
            // table's first column.)

            oColumn1HeaderCell.set_Value(Missing.Value,
                oGraphMetricColumn.ColumnName);

            Range oTableRange = oColumn1HeaderCell;
            ExcelUtil.ResizeRange(ref oTableRange, 2, 1);

            oStackedTable = ExcelTableUtil.AddTable(oWorksheet, oTableRange,
                oGraphMetricColumn.TableName, TableStyleNames.NodeXLTable);

            ExcelTableUtil.SetColumnWidth(oColumn1HeaderCell,
                oGraphMetricColumn.ColumnWidthChars);
        }
        catch (System.Runtime.InteropServices.COMException)
        {
            return (false);
        }

        return (true);
    }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        AssertValid();

        return ( TryCalculateGraphMetrics(graph, calculateGraphMetricsContext,
            new Algorithms.PageRankCalculator(), GraphMetrics.PageRank,
            VertexTableColumnNames.PageRank, ExcelTableUtil.AutoColumnWidth,
            CellStyleNames.GraphMetricGood, out graphMetricColumns) );
    }
    TryGetTable
    (
        Microsoft.Office.Interop.Excel.Workbook oWorkbook,
        GraphMetricColumn oGraphMetricColumn,
        out ListObject oTable
    )
    {
        Debug.Assert(oWorkbook != null);
        Debug.Assert(oGraphMetricColumn != null);
        AssertValid();

        oTable = null;
        String sTableName = oGraphMetricColumn.TableName;

        if ( !ExcelTableUtil.TryGetTable(oWorkbook,
            oGraphMetricColumn.WorksheetName, sTableName, out oTable) )
        {
            // The table couldn't be found.  It has to be created.

            if (sTableName == TableNames.GroupEdgeMetrics)
            {
                if ( !TryCreateGroupEdgeTable(oWorkbook, out oTable) )
                {
                    return (false);
                }
            }
            else if ( sTableName.StartsWith(TableNames.TopNByMetricsRoot) )
            {
                if ( !TryCreateStackedTable(oWorkbook,
                    WorksheetNames.TopNByMetrics,
                    oGraphMetricColumn, out oTable) )
                {
                    return (false);
                }
            }
            else if ( sTableName.StartsWith(
                TableNames.TwitterSearchNetworkTopItemsRoot) )
            {
                if ( !TryCreateStackedTable(oWorkbook,
                    WorksheetNames.TwitterSearchNetworkTopItems,
                    oGraphMetricColumn, out oTable) )
                {
                    return (false);
                }
            }
            else if (sTableName == TableNames.WordCounts)
            {
                // There is actually just one table on the words worksheet, not
                // a stack of tables, but that's okay.  TryCreateStackedTable()
                // doesn't care whether it will be called again with another
                // table for the worksheet.

                if ( !TryCreateStackedTable(oWorkbook,
                    WorksheetNames.WordCounts, oGraphMetricColumn,
                    out oTable) )
                {
                    return (false);
                }
            }
            else if (sTableName == TableNames.WordPairCounts)
            {
                if ( !TryCreateStackedTable(oWorkbook,
                    WorksheetNames.WordPairCounts, oGraphMetricColumn,
                    out oTable) )
                {
                    return (false);
                }
            }
            else
            {
                return (false);
            }
        }

        return (true);
    }
        TryCalculateGraphMetrics
        (
            IGraph graph,
            CalculateGraphMetricsContext calculateGraphMetricsContext,
            out GraphMetricColumn [] graphMetricColumns
        )
        {
            Debug.Assert(graph != null);
            Debug.Assert(calculateGraphMetricsContext != null);
            AssertValid();

            graphMetricColumns = new GraphMetricColumn[0];

            if (!calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
                    GraphMetrics.BrandesFastCentralities))
            {
                return(true);
            }

            // Calculate the centralities for each vertex using the
            // BrandesFastCalculator class in the Algorithms namespace, which knows
            // nothing about Excel.

            Dictionary <Int32, Algorithms.BrandesVertexCentralities>
            oVertexCentralitiesDictionary;

            if (!(new Algorithms.BrandesFastCentralityCalculator()).
                TryCalculateGraphMetrics(graph,
                                         calculateGraphMetricsContext.BackgroundWorker,
                                         out oVertexCentralitiesDictionary))
            {
                // The user cancelled.

                return(false);
            }

            // Transfer the centralities to arrays of GraphMetricValue objects.

            List <GraphMetricValueWithID> oBetweennessCentralityValues =
                new List <GraphMetricValueWithID>();

            List <GraphMetricValueWithID> oClosenessCentralityValues =
                new List <GraphMetricValueWithID>();

            foreach (IVertex oVertex in graph.Vertices)
            {
                // Try to get the row ID stored in the worksheet.

                Int32 iRowID;

                if (TryGetRowID(oVertex, out iRowID))
                {
                    Algorithms.BrandesVertexCentralities oVertexCentralities =
                        oVertexCentralitiesDictionary[oVertex.ID];

                    oBetweennessCentralityValues.Add(
                        new GraphMetricValueWithID(iRowID,
                                                   oVertexCentralities.BetweennessCentrality
                                                   ));

                    oClosenessCentralityValues.Add(
                        new GraphMetricValueWithID(iRowID,
                                                   oVertexCentralities.ClosenessCentrality
                                                   ));
                }
            }

            graphMetricColumns = new GraphMetricColumn [] {
                new GraphMetricColumnWithID(WorksheetNames.Vertices,
                                            TableNames.Vertices,
                                            VertexTableColumnNames.BetweennessCentrality,
                                            ExcelTableUtil.AutoColumnWidth,
                                            NumericFormat, CellStyleNames.GraphMetricGood,
                                            oBetweennessCentralityValues.ToArray()
                                            ),

                new GraphMetricColumnWithID(WorksheetNames.Vertices,
                                            TableNames.Vertices,
                                            VertexTableColumnNames.ClosenessCentrality,
                                            ExcelTableUtil.AutoColumnWidth,
                                            NumericFormat, CellStyleNames.GraphMetricGood,
                                            oClosenessCentralityValues.ToArray()
                                            )
            };

            return(true);
        }
    TryGetRequiredColumnInformation
    (
        GraphMetricColumn oGraphMetricColumn,
        ListObject oTable,
        out Range oVisibleColumnData
    )
    {
        Debug.Assert(oGraphMetricColumn != null);
        Debug.Assert(oTable != null);
        AssertValid();

        oVisibleColumnData = null;

        // Add the specified column if it's not already present.

        String sColumnName = oGraphMetricColumn.ColumnName;
        String sColumnStyle = oGraphMetricColumn.Style;

        Microsoft.Office.Interop.Excel.ListColumn oColumn;

        if (
            !ExcelTableUtil.TryGetTableColumn(oTable, sColumnName, out oColumn)
            &&
            !ExcelTableUtil.TryAddTableColumn(oTable, sColumnName,
                oGraphMetricColumn.ColumnWidthChars, sColumnStyle, out oColumn)
            )
        {
            // Give up.

            return (false);
        }

        Range oColumnData;

        if (!ExcelTableUtil.TryGetTableColumnData(oTable, sColumnName,
            out oColumnData) )
        {
            return (false);
        }

        ExcelUtil.SetRangeStyle(oColumnData, sColumnStyle);

        String sNumberFormat = oGraphMetricColumn.NumberFormat;

        if (sNumberFormat != null)
        {
            oColumnData.NumberFormat = sNumberFormat;
        }

        // Wrapping text makes Range.set_Value() very slow, so turn it off.

        oColumn.Range.WrapText = false;

        // But wrap the text in the column's header.

        ExcelTableUtil.WrapTableColumnHeader(oColumn);

        // Get the visible range.

        if ( !ExcelUtil.TryGetVisibleRange(oColumnData,
            out oVisibleColumnData) )
        {
            return (false);
        }

        return (true);
    }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        AssertValid();

        graphMetricColumns = new GraphMetricColumn[0];

        if ( !calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
            GraphMetrics.BrandesFastCentralities) )
        {
            return (true);
        }

        // Calculate the centralities for each vertex using the
        // BrandesFastCalculator class in the Algorithms namespace, which knows
        // nothing about Excel.

        Dictionary<Int32, Algorithms.BrandesVertexCentralities>
            oVertexCentralitiesDictionary;

        if ( !( new Algorithms.BrandesFastCentralityCalculator() ).
            TryCalculateGraphMetrics(graph,
                calculateGraphMetricsContext.BackgroundWorker,
                out oVertexCentralitiesDictionary) )
        {
            // The user cancelled.

            return (false);
        }

        // Transfer the centralities to arrays of GraphMetricValue objects.

        List<GraphMetricValueWithID> oBetweennessCentralityValues =
            new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID> oClosenessCentralityValues =
            new List<GraphMetricValueWithID>();

        foreach (IVertex oVertex in graph.Vertices)
        {
            // Try to get the row ID stored in the worksheet.

            Int32 iRowID;

            if ( TryGetRowID(oVertex, out iRowID) )
            {
                Algorithms.BrandesVertexCentralities oVertexCentralities =
                    oVertexCentralitiesDictionary[oVertex.ID];

                oBetweennessCentralityValues.Add(
                    new GraphMetricValueWithID(iRowID,
                        oVertexCentralities.BetweennessCentrality
                    ) );

                oClosenessCentralityValues.Add(
                    new GraphMetricValueWithID(iRowID,
                        oVertexCentralities.ClosenessCentrality
                    ) );
            }
        }

        graphMetricColumns = new GraphMetricColumn [] {

            new GraphMetricColumnWithID( WorksheetNames.Vertices,
                TableNames.Vertices,
                VertexTableColumnNames.BetweennessCentrality,
                ExcelTableUtil.AutoColumnWidth,
                NumericFormat, CellStyleNames.GraphMetricGood,
                oBetweennessCentralityValues.ToArray()
                ),

            new GraphMetricColumnWithID( WorksheetNames.Vertices,
                TableNames.Vertices,
                VertexTableColumnNames.ClosenessCentrality,
                ExcelTableUtil.AutoColumnWidth,
                NumericFormat, CellStyleNames.GraphMetricGood,
                oClosenessCentralityValues.ToArray()
                )
                };

        return (true);
    }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        AssertValid();

        graphMetricColumns = new GraphMetricColumn[0];

        WordMetricUserSettings oWordMetricUserSettings =
            calculateGraphMetricsContext.GraphMetricUserSettings
            .WordMetricUserSettings;

        if (
            !calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
                GraphMetrics.Words)
            ||
            String.IsNullOrEmpty(oWordMetricUserSettings.TextColumnName)
            )
        {
            return (true);
        }

        String [] asWordsToSkip = StringUtil.SplitOnCommonDelimiters(
            oWordMetricUserSettings.WordsToSkip);

        WordCounter oWordCounter = new WordCounter(asWordsToSkip);
        WordPairCounter oWordPairCounter = new WordPairCounter(asWordsToSkip);

        // The edges or vertices may have unique imported IDs.  If so, this
        // becomes a collection of the IDs.

        HashSet<String> oUniqueImportedIDs = 
            EdgesOrVerticesHaveImportedIDs(graph,
                oWordMetricUserSettings.TextColumnIsOnEdgeWorksheet) ?
            new HashSet<String>() : null;

        if (oWordMetricUserSettings.CountByGroup)
        {
            if (oWordMetricUserSettings.TextColumnIsOnEdgeWorksheet)
            {
                return ( TryCountEdgeTermsByGroup(graph,
                    oWordMetricUserSettings, oWordCounter, oWordPairCounter,
                    oUniqueImportedIDs, out graphMetricColumns) );
            }
            else
            {
                return ( TryCountVertexTermsByGroup(graph,
                    oWordMetricUserSettings, oWordCounter, oWordPairCounter,
                    oUniqueImportedIDs, out graphMetricColumns) );
            }
        }
        else
        {
            return ( TryCountTermsNoGroups(graph,
                oWordMetricUserSettings, oWordCounter, oWordPairCounter,
                oUniqueImportedIDs, out graphMetricColumns) );
        }
    }
Example #27
0
        TryCalculateGraphMetrics
        (
            IGraph graph,
            CalculateGraphMetricsContext calculateGraphMetricsContext,
            out GraphMetricColumn [] graphMetricColumns
        )
        {
            Debug.Assert(graph != null);
            Debug.Assert(calculateGraphMetricsContext != null);
            AssertValid();

            graphMetricColumns = new GraphMetricColumn[0];

            if (
                graph.Directedness != GraphDirectedness.Directed
                ||
                !calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
                    GraphMetrics.EdgeReciprocation)
                )
            {
                return(true);
            }

            // Calculate the reciprocated flag for each edge using the
            // EdgeReciprocationCalculator class in the Algorithms namespace, which
            // knows nothing about Excel.

            Dictionary <Int32, Boolean> oReciprocatedFlags;

            if (!(new Algorithms.EdgeReciprocationCalculator()).
                TryCalculateGraphMetrics(graph,
                                         calculateGraphMetricsContext.BackgroundWorker,
                                         out oReciprocatedFlags))
            {
                // The user cancelled.

                return(false);
            }

            // Transfer the flags to an array of GraphMetricValue objects.

            List <GraphMetricValueWithID> oReciprocatedValues =
                new List <GraphMetricValueWithID>();

            BooleanConverter oBooleanConverter = new BooleanConverter();

            foreach (IEdge oEdge in graph.Edges)
            {
                // Try to get the row ID stored in the worksheet.

                Int32 iRowID;

                if (TryGetRowID(oEdge, out iRowID))
                {
                    oReciprocatedValues.Add(
                        new GraphMetricValueWithID(iRowID,
                                                   oBooleanConverter.GraphToWorkbook(
                                                       oReciprocatedFlags[oEdge.ID])
                                                   ));
                }
            }

            graphMetricColumns = new GraphMetricColumn [] {
                new GraphMetricColumnWithID(WorksheetNames.Edges,
                                            TableNames.Edges,
                                            EdgeTableColumnNames.IsReciprocated,
                                            ExcelTableUtil.AutoColumnWidth, null,
                                            CellStyleNames.GraphMetricGood,
                                            oReciprocatedValues.ToArray()
                                            ),
            };

            return(true);
        }
    TryCountVertexTermsByGroup
    (
        IGraph oGraph,
        WordMetricUserSettings oWordMetricUserSettings,
        WordCounter oWordCounter,
        WordPairCounter oWordPairCounter,
        HashSet<String> oUniqueImportedIDs,
        out GraphMetricColumn [] oGraphMetricColumns
    )
    {
        Debug.Assert(oGraph != null);
        Debug.Assert(oWordMetricUserSettings != null);
        Debug.Assert(oWordCounter != null);
        Debug.Assert(oWordPairCounter != null);
        AssertValid();

        List<GraphMetricValueOrdered> oWordWordValues, oWordCountValues,
            oWordSalienceValues;

        List<GraphMetricValueOrdered> oWordPairWord1Values,
            oWordPairWord2Values, oWordPairCountValues,
            oWordPairSalienceValues, oWordPairMutualInformationValues;

        CreateGraphMetricValueLists(
            out oWordWordValues, out oWordCountValues, out oWordSalienceValues,
            
            out oWordPairWord1Values, out oWordPairWord2Values,
            out oWordPairCountValues, out oWordPairSalienceValues,
            out oWordPairMutualInformationValues
            );

        List<GraphMetricValueOrdered> oWordGroupNameValues =
            new List<GraphMetricValueOrdered>();

        List<GraphMetricValueOrdered> oWordPairGroupNameValues =
            new List<GraphMetricValueOrdered>();

        // Get a list of the graph's groups, adding a dummy group for the
        // entire graph and another to contain any non-grouped vertices.

        foreach ( GroupInfo oGroup in
            EnumerateGroupsForCountingVertexTerms(oGraph) )
        {
            // Count the terms in this group.

            oWordCounter.Clear();
            oWordPairCounter.Clear();

            foreach ( IVertex oVertex in EnumerateEdgesOrVertices(
                oGroup.Vertices, false, oGraph, oUniqueImportedIDs) )
            {
                CountTermsInEdgeOrVertex(oVertex,
                    oWordMetricUserSettings.TextColumnName, oWordCounter,
                    oWordPairCounter);
            }

            oWordCounter.CalculateSalienceOfCountedTerms();
            oWordPairCounter.CalculateSalienceOfCountedTerms();
            oWordPairCounter.CalculateMutualInformationOfCountedTerms();

            // Transfer the words and word pairs to the graph metric value
            // lists.

            AddCountedWordsToValueLists(oWordCounter.CountedTerms,
                oWordMetricUserSettings, oGroup.Name, oWordWordValues,
                oWordCountValues, oWordSalienceValues, oWordGroupNameValues);

            AddCountedWordPairsToValueLists(oWordPairCounter.CountedTerms,
                oWordMetricUserSettings, oGroup.Name, oWordPairWord1Values,
                oWordPairWord2Values, oWordPairCountValues,
                oWordPairSalienceValues, oWordPairMutualInformationValues,
                oWordPairGroupNameValues);
        }

        oGraphMetricColumns = CreateGraphMetricColumns(
            oWordWordValues, oWordCountValues, oWordSalienceValues,
            oWordGroupNameValues,
        
            oWordPairWord1Values, oWordPairWord2Values, oWordPairCountValues,
            oWordPairSalienceValues, oWordPairMutualInformationValues,
            oWordPairGroupNameValues
            );

        return (true);
    }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        AssertValid();

        graphMetricColumns = new GraphMetricColumn[0];

        // Attempt to retrieve the group information the WorkbookReader object
        // may have stored as metadata on the graph.

        GroupInfo [] aoGroups;

        if (
            !calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
                GraphMetrics.GroupMetrics)
            ||
            !GroupUtil.TryGetGroups(graph, out aoGroups)
            )
        {
            return (true);
        }

        // The following lists correspond to group worksheet columns.

        List<GraphMetricValueWithID> oVerticesGraphMetricValues =
            new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID> oUniqueEdgesGraphMetricValues =
            new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID> oEdgesWithDuplicatesGraphMetricValues =
            new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID> oTotalEdgesGraphMetricValues =
            new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID> oSelfLoopsGraphMetricValues =
            new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID>
            oReciprocatedVertexPairRatioGraphMetricValues =
            new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID> oReciprocatedEdgeRatioGraphMetricValues =
            new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID> oConnectedComponentsGraphMetricValues =
            new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID>
            oSingleVertexConnectedComponentsGraphMetricValues =
                new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID>
            oMaximumConnectedComponentVerticesGraphMetricValues =
                new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID>
            oMaximumConnectedComponentEdgesGraphMetricValues =
                new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID> oMaximumGeodesicDistanceGraphMetricValues =
            new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID> oAverageGeodesicDistanceGraphMetricValues =
            new List<GraphMetricValueWithID>();

        List<GraphMetricValueWithID> oGraphDensityGraphMetricValues =
            new List<GraphMetricValueWithID>();

        foreach (ExcelTemplateGroupInfo oExcelTemplateGroupInfo in aoGroups)
        {
            ICollection<IVertex> oVertices = oExcelTemplateGroupInfo.Vertices;

            if (oVertices == null || oVertices.Count == 0 ||
                !oExcelTemplateGroupInfo.RowID.HasValue)
            {
                continue;
            }

            OverallMetrics oOverallMetrics;

            if ( !TryCalculateGraphMetricsForOneGroup(oExcelTemplateGroupInfo,
                calculateGraphMetricsContext, out oOverallMetrics) )
            {
                // The user cancelled.

                return (false);
            }

            Int32 iRowID = oExcelTemplateGroupInfo.RowID.Value;

            oVerticesGraphMetricValues.Add( new GraphMetricValueWithID(
                iRowID, oOverallMetrics.Vertices) );

            oUniqueEdgesGraphMetricValues.Add( new GraphMetricValueWithID(
                iRowID, oOverallMetrics.UniqueEdges) );

            oEdgesWithDuplicatesGraphMetricValues.Add(
                new GraphMetricValueWithID(iRowID,
                    oOverallMetrics.EdgesWithDuplicates) );

            oTotalEdgesGraphMetricValues.Add(new GraphMetricValueWithID(iRowID,
                oOverallMetrics.TotalEdges) );

            oSelfLoopsGraphMetricValues.Add(new GraphMetricValueWithID(iRowID,
                oOverallMetrics.SelfLoops) );

            oReciprocatedVertexPairRatioGraphMetricValues.Add(
                new GraphMetricValueWithID( iRowID,
                    OverallMetricCalculator2.NullableToGraphMetricValue<Double>(
                        oOverallMetrics.ReciprocatedVertexPairRatio) ) );

            oReciprocatedEdgeRatioGraphMetricValues.Add(
                new GraphMetricValueWithID( iRowID,
                    OverallMetricCalculator2.NullableToGraphMetricValue<Double>(
                        oOverallMetrics.ReciprocatedEdgeRatio) ) );

            oConnectedComponentsGraphMetricValues.Add(
                new GraphMetricValueWithID(iRowID,
                    oOverallMetrics.ConnectedComponents) );

            oSingleVertexConnectedComponentsGraphMetricValues.Add(
                new GraphMetricValueWithID(iRowID,
                    oOverallMetrics.SingleVertexConnectedComponents) );

            oMaximumConnectedComponentVerticesGraphMetricValues.Add(
                new GraphMetricValueWithID(iRowID,
                    oOverallMetrics.MaximumConnectedComponentVertices) );

            oMaximumConnectedComponentEdgesGraphMetricValues.Add(
                new GraphMetricValueWithID(iRowID,
                    oOverallMetrics.MaximumConnectedComponentEdges) );

            oMaximumGeodesicDistanceGraphMetricValues.Add(
                new GraphMetricValueWithID(iRowID,
                    OverallMetricCalculator2.NullableToGraphMetricValue<Int32>(
                        oOverallMetrics.MaximumGeodesicDistance) ) );

            oAverageGeodesicDistanceGraphMetricValues.Add(
                new GraphMetricValueWithID( iRowID,
                    OverallMetricCalculator2.NullableToGraphMetricValue<Double>(
                        oOverallMetrics.AverageGeodesicDistance) ) );

            oGraphDensityGraphMetricValues.Add(
                new GraphMetricValueWithID( iRowID,
                    OverallMetricCalculator2.NullableToGraphMetricValue<Double>(
                        oOverallMetrics.GraphDensity) ) );
        }

        graphMetricColumns = new GraphMetricColumn [] {

            CreateGraphMetricColumnWithID(
                GroupTableColumnNames.Vertices,
                Int32NumericFormat,
                oVerticesGraphMetricValues),

            CreateGraphMetricColumnWithID(
                GroupTableColumnNames.UniqueEdges,
                Int32NumericFormat,
                oUniqueEdgesGraphMetricValues),

            CreateGraphMetricColumnWithID(
                GroupTableColumnNames.EdgesWithDuplicates,
                Int32NumericFormat,
                oEdgesWithDuplicatesGraphMetricValues),

            CreateGraphMetricColumnWithID(
                GroupTableColumnNames.TotalEdges,
                Int32NumericFormat,
                oTotalEdgesGraphMetricValues),

            CreateGraphMetricColumnWithID(
                GroupTableColumnNames.SelfLoops,
                Int32NumericFormat,
                oSelfLoopsGraphMetricValues),

            CreateGraphMetricColumnWithID(
                GroupTableColumnNames.ReciprocatedVertexPairRatio,
                DoubleNumericFormat,
                oReciprocatedVertexPairRatioGraphMetricValues),

            CreateGraphMetricColumnWithID(
                GroupTableColumnNames.ReciprocatedEdgeRatio,
                DoubleNumericFormat,
                oReciprocatedEdgeRatioGraphMetricValues),

            CreateGraphMetricColumnWithID(
                GroupTableColumnNames.ConnectedComponents,
                Int32NumericFormat, oConnectedComponentsGraphMetricValues),

            CreateGraphMetricColumnWithID(
                GroupTableColumnNames.SingleVertexConnectedComponents,
                Int32NumericFormat,
                oSingleVertexConnectedComponentsGraphMetricValues),

            CreateGraphMetricColumnWithID(
                GroupTableColumnNames.MaximumConnectedComponentVertices,
                Int32NumericFormat,
                oMaximumConnectedComponentVerticesGraphMetricValues),

            CreateGraphMetricColumnWithID(
                GroupTableColumnNames.MaximumConnectedComponentEdges,
                Int32NumericFormat,
                oMaximumConnectedComponentEdgesGraphMetricValues),

            CreateGraphMetricColumnWithID(
                GroupTableColumnNames.MaximumGeodesicDistance,
                Int32NumericFormat,
                oMaximumGeodesicDistanceGraphMetricValues),

            CreateGraphMetricColumnWithID(
                GroupTableColumnNames.AverageGeodesicDistance,
                DoubleNumericFormat,
                oAverageGeodesicDistanceGraphMetricValues),

            CreateGraphMetricColumnWithID(
                GroupTableColumnNames.GraphDensity,
                DoubleNumericFormat,
                oGraphDensityGraphMetricValues),
            };

        return (true);
    }
    FilterAndReformatWordMetrics
    (
        ref Int32 iTableIndex,
        GraphMetricColumn [] oWordMetricColumns,
        List<GroupEdgeInfo> oAllGroupEdgeInfos,
        List<GraphMetricColumn> oGraphMetricColumns
    )
    {
        Debug.Assert(iTableIndex >= 1);
        Debug.Assert(oWordMetricColumns != null);
        Debug.Assert(oAllGroupEdgeInfos != null);
        Debug.Assert(oGraphMetricColumns != null);
        AssertValid();

        // This method assumes a certain column order created by
        // WordMetricCalculator2.  This can be changed in the future to search
        // for columns, but that seems wasteful for now.

        Debug.Assert(oWordMetricColumns.Length == 10);
        Debug.Assert(oWordMetricColumns[0] is GraphMetricColumnOrdered);

        Debug.Assert(oWordMetricColumns[0].ColumnName ==
            WordTableColumnNames.Word);

        Debug.Assert(oWordMetricColumns[1].ColumnName ==
            WordTableColumnNames.Count);

        Debug.Assert(oWordMetricColumns[3].ColumnName ==
            WordTableColumnNames.Group);

        Debug.Assert(oWordMetricColumns[4].ColumnName ==
            WordPairTableColumnNames.Word1);

        Debug.Assert(oWordMetricColumns[5].ColumnName ==
            WordPairTableColumnNames.Word2);

        Debug.Assert(oWordMetricColumns[6].ColumnName ==
            WordPairTableColumnNames.Count);

        Debug.Assert(oWordMetricColumns[9].ColumnName ==
            WordPairTableColumnNames.Group);

        // Filter and reformat calculated metrics for words.

        FilterAndReformatWordMetrics(ref iTableIndex, "Words in Tweet",
            (GraphMetricColumnOrdered)oWordMetricColumns[0],
            null,
            (GraphMetricColumnOrdered)oWordMetricColumns[1],
            (GraphMetricColumnOrdered)oWordMetricColumns[3],
            oAllGroupEdgeInfos, GroupTableColumnNames.TopWordsInTweet,
            oGraphMetricColumns
            );

        // Filter and reformat calculated metrics for word pairs.

        FilterAndReformatWordMetrics(ref iTableIndex, "Word Pairs in Tweet",
            (GraphMetricColumnOrdered)oWordMetricColumns[4],
            (GraphMetricColumnOrdered)oWordMetricColumns[5],
            (GraphMetricColumnOrdered)oWordMetricColumns[6],
            (GraphMetricColumnOrdered)oWordMetricColumns[9],
            oAllGroupEdgeInfos, GroupTableColumnNames.TopWordPairsInTweet,
            oGraphMetricColumns
            );
    }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        AssertValid();

        graphMetricColumns = new GraphMetricColumn[0];

        // Attempt to retrieve the group information the WorkbookReader object
        // may have stored as metadata on the graph.

        GroupInfo [] aoGroups;

        if (
            !calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
                GraphMetrics.GroupMetrics)
            ||
            !GroupUtil.TryGetGroups(graph, out aoGroups)
            )
        {
            return (true);
        }

        // Count the edges using the IntergroupEdgeCalculator class in the
        // Algorithms namespace, which knows nothing about Excel.

        IList<IntergroupEdgeInfo> oIntergroupEdges;

        if ( !(new Algorithms.IntergroupEdgeCalculator() ).
            TryCalculateGraphMetrics(graph,
                calculateGraphMetricsContext.BackgroundWorker, aoGroups, true,
                out oIntergroupEdges) )
        {
            // The user cancelled.

            return (false);
        }

        // Add a row to the group-edge table for each pair of groups that has
        // edges.

        graphMetricColumns = CreateGraphMetricColumns(
            AddRows(aoGroups, oIntergroupEdges) );

        return (true);
    }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        AssertValid();

        graphMetricColumns = null;

        // Partition the graph into strongly connected components using the
        // ConnectedComponentCalculator class in the Algorithms namespace,
        // which knows nothing about Excel.
        //
        // Note that ConnectedComponentCalculator does its work synchronously.

        Algorithms.ConnectedComponentCalculator oConnectedComponentCalculator =
            new Algorithms.ConnectedComponentCalculator();

        IList< LinkedList<IVertex> > oComponents =
            oConnectedComponentCalculator.CalculateStronglyConnectedComponents(
                graph, false);

        // Convert the collection of components to an array of
        // GraphMetricColumn objects.

        graphMetricColumns =
            GroupsToGraphMetricColumnsConverter.Convert< LinkedList<IVertex> >(
                oComponents,
                (oComponent) => oComponent
                );

        return (true);
    }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        AssertValid();

        graphMetricColumns = null;

        // Partition the graph into clusters using the ClusterCalculator class
        // in the Algorithms namespace, which knows nothing about Excel.

        ICollection<Community> oCommunities;

        Algorithms.ClusterCalculator oClusterCalculator =
            new Algorithms.ClusterCalculator();

        oClusterCalculator.Algorithm = m_eAlgorithm;

        oClusterCalculator.PutNeighborlessVerticesInOneCluster =
            m_bPutNeighborlessVerticesInOneCluster;

        if ( !oClusterCalculator.TryCalculateGraphMetrics(graph,
                calculateGraphMetricsContext.BackgroundWorker,
                out oCommunities) )
        {
            // The user cancelled.

            return (false);
        }

        // Convert the collection of communities to an array of
        // GraphMetricColumn objects.

        graphMetricColumns =
            GroupsToGraphMetricColumnsConverter.Convert<Community>(
                oCommunities,
                (oCommunity) => oCommunity.Vertices
                );

        return (true);
    }
Example #34
0
        TryGetTable
        (
            Microsoft.Office.Interop.Excel.Workbook oWorkbook,
            GraphMetricColumn oGraphMetricColumn,
            out ListObject oTable
        )
        {
            Debug.Assert(oWorkbook != null);
            Debug.Assert(oGraphMetricColumn != null);
            AssertValid();

            oTable = null;
            String sTableName = oGraphMetricColumn.TableName;

            if (!ExcelTableUtil.TryGetTable(oWorkbook,
                                            oGraphMetricColumn.WorksheetName, sTableName, out oTable))
            {
                // The table couldn't be found.  It has to be created.

                if (sTableName == TableNames.GroupEdgeMetrics)
                {
                    if (!TryCreateGroupEdgeTable(oWorkbook, out oTable))
                    {
                        return(false);
                    }
                }
                else if (sTableName.StartsWith(TableNames.TopNByMetricsRoot))
                {
                    if (!TryCreateStackedTable(oWorkbook,
                                               WorksheetNames.TopNByMetrics,
                                               oGraphMetricColumn, out oTable))
                    {
                        return(false);
                    }
                }
                else if (sTableName.StartsWith(
                             TableNames.TwitterSearchNetworkTopItemsRoot))
                {
                    if (!TryCreateStackedTable(oWorkbook,
                                               WorksheetNames.TwitterSearchNetworkTopItems,
                                               oGraphMetricColumn, out oTable))
                    {
                        return(false);
                    }
                }
                else if (sTableName == TableNames.WordCounts)
                {
                    // There is actually just one table on the words worksheet, not
                    // a stack of tables, but that's okay.  TryCreateStackedTable()
                    // doesn't care whether it will be called again with another
                    // table for the worksheet.

                    if (!TryCreateStackedTable(oWorkbook,
                                               WorksheetNames.WordCounts, oGraphMetricColumn,
                                               out oTable))
                    {
                        return(false);
                    }
                }
                else if (sTableName == TableNames.WordPairCounts)
                {
                    if (!TryCreateStackedTable(oWorkbook,
                                               WorksheetNames.WordPairCounts, oGraphMetricColumn,
                                               out oTable))
                    {
                        return(false);
                    }
                }
                else
                {
                    return(false);
                }
            }

            return(true);
        }
    WriteGraphMetricColumnsToWorkbook
    (
        GraphMetricColumn [] aoGraphMetricColumns
    )
    {
        Debug.Assert(aoGraphMetricColumns != null);
        AssertValid();

        Microsoft.Office.Interop.Excel.Application oApplication =
            m_oWorkbook.Application;

        GraphMetricWriter oGraphMetricWriter = new GraphMetricWriter();

        oApplication.ScreenUpdating = false;

        try
        {
            oGraphMetricWriter.WriteGraphMetricColumnsToWorkbook(
                aoGraphMetricColumns, m_oWorkbook);

            if (m_bActivateRelevantWorksheetWhenDone)
            {
                // Let the user know that graph metrics have been calculated.

                oGraphMetricWriter.ActivateRelevantWorksheet(
                    aoGraphMetricColumns, m_oWorkbook);
            }
        }
        catch (Exception oException)
        {
            oApplication.ScreenUpdating = true;

            ErrorUtil.OnException(oException);

            this.Close();
            return;
        }

        oApplication.ScreenUpdating = true;
    }
    TryCalculateGraphMetrics
    (
        IGraph graph,
        CalculateGraphMetricsContext calculateGraphMetricsContext,
        out GraphMetricColumn [] graphMetricColumns
    )
    {
        Debug.Assert(graph != null);
        Debug.Assert(calculateGraphMetricsContext != null);
        AssertValid();

        graphMetricColumns = new GraphMetricColumn[0];

        if (
            graph.Directedness != GraphDirectedness.Directed
            ||
            !calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
                GraphMetrics.EdgeReciprocation)
            )
        {
            return (true);
        }

        // Calculate the reciprocated flag for each edge using the
        // EdgeReciprocationCalculator class in the Algorithms namespace, which
        // knows nothing about Excel.

        Dictionary<Int32, Boolean> oReciprocatedFlags;

        if ( !( new Algorithms.EdgeReciprocationCalculator() ).
            TryCalculateGraphMetrics(graph,
                calculateGraphMetricsContext.BackgroundWorker,
                out oReciprocatedFlags) )
        {
            // The user cancelled.

            return (false);
        }

        // Transfer the flags to an array of GraphMetricValue objects.

        List<GraphMetricValueWithID> oReciprocatedValues =
            new List<GraphMetricValueWithID>();

        BooleanConverter oBooleanConverter = new BooleanConverter();

        foreach (IEdge oEdge in graph.Edges)
        {
            // Try to get the row ID stored in the worksheet.

            Int32 iRowID;

            if ( TryGetRowID(oEdge, out iRowID) )
            {
                oReciprocatedValues.Add(
                    new GraphMetricValueWithID(iRowID,
                        oBooleanConverter.GraphToWorkbook(
                        oReciprocatedFlags[oEdge.ID] )
                    ) );
            }
        }

        graphMetricColumns = new GraphMetricColumn [] {

            new GraphMetricColumnWithID( WorksheetNames.Edges,
                TableNames.Edges,
                EdgeTableColumnNames.IsReciprocated,
                ExcelTableUtil.AutoColumnWidth, null,
                CellStyleNames.GraphMetricGood,
                oReciprocatedValues.ToArray()
                ),
                };

        return (true);
    }
        TryCalculateGraphMetrics
        (
            IGraph graph,
            CalculateGraphMetricsContext calculateGraphMetricsContext,

            Algorithms.OneDoubleGraphMetricCalculatorBase
            oneDoubleGraphMetricCalculator,

            GraphMetrics graphMetric,
            String columnName,
            Double columnWidthChars,
            String style,
            out GraphMetricColumn [] graphMetricColumns
        )
        {
            Debug.Assert(graph != null);
            Debug.Assert(calculateGraphMetricsContext != null);
            Debug.Assert(oneDoubleGraphMetricCalculator != null);
            Debug.Assert(!String.IsNullOrEmpty(columnName));

            Debug.Assert(columnWidthChars == ExcelTableUtil.AutoColumnWidth ||
                         columnWidthChars > 0);

            AssertValid();

            graphMetricColumns = new GraphMetricColumn[0];

            if (!calculateGraphMetricsContext.ShouldCalculateGraphMetrics(
                    graphMetric))
            {
                return(true);
            }

            // Calculate the graph metrics for each vertex using the
            // OneDoubleGraphMetricCalculatorBase object, which knows nothing about
            // Excel.

            Dictionary <Int32, Double> oGraphMetrics;

            if (!oneDoubleGraphMetricCalculator.TryCalculateGraphMetrics(graph,
                                                                         calculateGraphMetricsContext.BackgroundWorker, out oGraphMetrics))
            {
                // The user cancelled.

                return(false);
            }

            // Transfer the graph metrics to an array of GraphMetricValue objects.

            List <GraphMetricValueWithID> oGraphMetricValues =
                new List <GraphMetricValueWithID>();

            foreach (IVertex oVertex in graph.Vertices)
            {
                // Try to get the row ID stored in the worksheet.

                Int32 iRowID;

                if (TryGetRowID(oVertex, out iRowID))
                {
                    oGraphMetricValues.Add(new GraphMetricValueWithID(
                                               iRowID, oGraphMetrics[oVertex.ID]));
                }
            }

            graphMetricColumns = new GraphMetricColumn [] {
                new GraphMetricColumnWithID(WorksheetNames.Vertices,
                                            TableNames.Vertices, columnName, columnWidthChars,
                                            NumericFormat, style, oGraphMetricValues.ToArray()
                                            )
            };

            return(true);
        }