C# NMF Ordered Connectivity Matrix Example

← All NMath Stats Code Examples

 


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using CenterSpace.NMath.Core;
using CenterSpace.NMath.Stats;
using System.IO;

namespace CenterSpace.NMath.Stats.Examples.CSharp
{
  /// <summary>
  /// A .NET example in C# showing how to create an ordered connectivity matrix to display the results of
  /// NMF clustering.
  /// </summary>
  /// <remarks>
  /// An ordered connectivity matrix is created by taking a connectivity matrix
  /// and reordering the rows and columns so that the most affiliated elements
  /// appear as clustered values along the diagonal. The reordering is determined
  /// as follows:
  /// 
  /// First a hierarchical cluster analysis is performed on the elements 
  /// represented in the connectivity matrix. For the purpose of clustering 
  /// the elements represented in the connectivity matrix are labeled 0, 1,
  /// 2,...,n-1, where n is the number of the elements. 
  /// 
  /// Given two integers, i and j, the provided distance function should return
  /// the distance between the ith and jth elements. If no distance function is
  /// provided the default distance function returns the value 1.0 - aij for 
  /// the distance between the ith and jth elements, where aij is the i, jth 
  /// element of the connectivity matrix A. 
  /// 
  /// After the hierarchical clustering process, the leaf nodes of the
  /// dendrogram produced from the results are traversed in order to produce a
  /// permutation vector. This permutation vector is used to reorder the rows
  /// and columns of the input connectivity matrix, causing the most affiliated 
  /// elements to appear as clusters of higher values along the diagonal.
  /// 
  /// The connectivity matrix used in this example is an NMFConsensusMatrix which
  /// is the result of using a Nonnegative Matrix Factorization (NMF) to cluster a set
  /// of samples.  The display in the example is a "heat map" with tightly clustered 
  /// elements colored in darker "hotter" colors (red, orange, yellow) which "cooler" 
  /// colors (green and blue) being used for the more loosely affiliated elements.
  /// </remarks>
  public partial class NMFOrderedConnectivityMatrixExample : Form
  {
    // Colors to use in the bitmap.
    private List<Color> colors_ = new List<Color>();

    // The heat map.
    private Bitmap heatMap_;

    public NMFOrderedConnectivityMatrixExample()
    {
      InitializeComponent();
      this.Height = 650;
      this.Width = 630;

      // Colors to use in the heat map. The colors range from
      // reds and oranges, for highly affiliated elements, to
      // greens and blues for loosely affiliated elements.
      colors_.Add( Color.DarkRed );
      colors_.Add( Color.OrangeRed );
      colors_.Add( Color.Orange );
      colors_.Add( Color.Yellow );
      colors_.Add( Color.GreenYellow );
      colors_.Add( Color.MediumSeaGreen );
      colors_.Add( Color.Green );
      colors_.Add( Color.LightGreen );
      colors_.Add( Color.LightBlue );
      colors_.Add( Color.Aqua );

      // First read in some data to cluster. In this example columns in the
      // the data frame represent samples to which we will apply a Nonnegative
      // Matrix Factorization (NMF) to get a connectivity matrix in the form of a
      // NMFConsensusMatrix.
      DataFrame data = DataFrame.Load( "nmf_data.dat", true, true, "\t", true ); 

      // Order of the NMF.
      int k = 3;

      // Number of factorizations to use in constructing the consensus matrix.
      int numberOfRuns = 25;

      // Construct the consensus matrix using a Gradient Descent, Constrained Least
      // Squares iterative algorithm.
      var consensusMatrix =
        new NMFConsensusMatrix<NMFGdClsUpdate>( data, k, numberOfRuns );

      // Construct the ordered connectivity matrix from the consensus matrix.
      var orderedConsensusMatrix = new OrderedConnectivityMatrix( consensusMatrix );

      // Construct and display the heat map by displaying the number in the ordered consensus matrix 
      // a pixels whose colors are "hotter" (red, orange) for higher values (highly affiliated), and 
      // cooler (green, yellow) for smaller values (less affiliated). Note that all the numbers in the
      // consensus matrix are between 0 and 1.
      int blockSize = 600 / orderedConsensusMatrix.Order;
      int s = ( blockSize + 1 ) * orderedConsensusMatrix.Order;
      heatMap_ = new Bitmap( s, s );
      int rowOffset = 0;
      int columnOffset = 0;
      for ( int i = 0; i < orderedConsensusMatrix.Order; i++ )
      {
        for ( int j = 0; j < orderedConsensusMatrix.Order; j++ )
        {
          Color c = GetColor( orderedConsensusMatrix[i, j] );
          for ( int bi = rowOffset; bi < rowOffset + blockSize; bi++ )
          {
            for ( int bj = columnOffset; bj < columnOffset + blockSize; bj++ )
            {
              heatMap_.SetPixel( bi, bj, c );
            }
          }
          columnOffset += blockSize;
        }
        columnOffset = 0;
        rowOffset += blockSize;
      }
    }

    static void Main()
    {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault( false );
      Application.Run( new NMFOrderedConnectivityMatrixExample() );
    }

    protected override void OnPaint( PaintEventArgs e )
    {
      base.OnPaint( e );
      int bmpUpperLeftRow = 10;
      int bmpUpperLeftCol = 10;
      if ( heatMap_ != null )
      {
        e.Graphics.DrawImage( heatMap_, bmpUpperLeftCol, bmpUpperLeftRow );
      }
    }

    private Color GetColor( double p )
    {
      if ( p == 1.0 )
        return colors_[0];
      if ( p >= .9 )
        return colors_[1];
      if ( p >= .8 )
        return colors_[2];
      if ( p >= .7 )
        return colors_[3];
      if ( p >= .6 )
        return colors_[4];
      if ( p >= .5 )
        return colors_[5];
      if ( p >= .4 )
        return colors_[6];
      if ( p >= .3 )
        return colors_[7];
      if ( p >= .2 )
        return colors_[8];
      if ( p >= .1 )
        return colors_[9];

      return Color.MidnightBlue;
    }
  }
}

← All NMath Stats Code Examples
Top