<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>eric.ness.net &#187; Visualization</title>
	<atom:link href="http://eric.ness.net/archives/category/visualization/feed/" rel="self" type="application/rss+xml" />
	<link>http://eric.ness.net</link>
	<description>...I never learned to read.</description>
	<lastBuildDate>Sat, 21 Jan 2012 05:27:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>UUorld Map Visualization</title>
		<link>http://eric.ness.net/archives/uuorld-map-visualization/</link>
		<comments>http://eric.ness.net/archives/uuorld-map-visualization/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 20:50:28 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Visualization]]></category>

		<guid isPermaLink="false">http://eric.ness.net/?p=423</guid>
		<description><![CDATA[UUorld has quickly become one of my new favorite toys as of late.]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fuuorld-map-visualization%2F' data-shr_title='UUorld+Map+Visualization'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fuuorld-map-visualization%2F' data-shr_title='UUorld+Map+Visualization'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://eric.ness.net/wp-content/uploads/2010/02/blog.jpg"><img class="alignnone size-full wp-image-426" title="blog" src="http://eric.ness.net/wp-content/uploads/2010/02/blog.jpg" alt="" width="577" height="360" /></a></p>
<p><a title="UUorld" href="http://www.uuorld.com/">UUorld</a> has quickly become one of my new favorite toys as of late. What is it? As the site explains it &#8220;provides an immersive mapping environment, high-quality data, and critical analysis tools.&#8221;</p>
<p>Here is just a simple result of what the map looks like:</p>
<p><a href="http://eric.ness.net/wp-content/uploads/2010/02/example1.jpg"><img class="alignnone size-full wp-image-424" title="example1" src="http://eric.ness.net/wp-content/uploads/2010/02/example1.jpg" alt="" width="577" height="351" /></a></p>
<p>Here are some of the highlights:</p>
<ol>
<li>Supports time series data</li>
<li>Fairly extensive database to pull data from online (apparently of 10,000 different datasets)</li>
<li>Create you own datasets via csv files</li>
<li>Export to video</li>
<li>Export to KML file for use in google maps/earth.</li>
<li>Has the following border sets: Country, US States/Counties, US Zip Codes</li>
</ol>
<p>There is one caveat that I feel I must add to not give the impression that all is rosy &#8211; I bought the application over a week ago and it took several e-mails for them to reply to me and finally get my full download.</p>
<p><a href="http://eric.ness.net/wp-content/uploads/2010/02/example2.jpg"><img class="alignnone size-full wp-image-425" title="example2" src="http://eric.ness.net/wp-content/uploads/2010/02/example2.jpg" alt="" width="577" height="351" /></a></p>
<div class="shr-publisher-423"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://eric.ness.net/archives/uuorld-map-visualization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scatterplots Using R and MSSQL</title>
		<link>http://eric.ness.net/archives/scatterplots-using-r-and-mssql/</link>
		<comments>http://eric.ness.net/archives/scatterplots-using-r-and-mssql/#comments</comments>
		<pubDate>Fri, 27 Nov 2009 15:00:57 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Statistics]]></category>
		<category><![CDATA[Visualization]]></category>
		<category><![CDATA[R]]></category>

		<guid isPermaLink="false">http://eric.ness.net/?p=412</guid>
		<description><![CDATA[Scatterplots Using R and MSSQL]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fscatterplots-using-r-and-mssql%2F' data-shr_title='Scatterplots+Using+R+and+MSSQL'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fscatterplots-using-r-and-mssql%2F' data-shr_title='Scatterplots+Using+R+and+MSSQL'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://eric.ness.net/wp-content/uploads/2009/11/scatterplotwithr.jpg"><img class="alignnone size-full wp-image-416" title="scatterplotwithr" src="http://eric.ness.net/wp-content/uploads/2009/11/scatterplotwithr.jpg" alt="" width="577" height="360" /></a></p>
<p>As an extension of <a href="http://eric.ness.net/archives/histogram-lattices-using-r-and-mssql/">yesterdays post</a> here is another fairly cool chart you can do in <a href="http://www.r-project.org/">R</a>. For this little sample we are using the same data as before but for my sql query I have to do a crosstab query. So lets take a look at the code:</p>
<pre class="brush: jscript; title: ; notranslate">
# includes
library(RODBC)

# create connection
channel &lt;- odbcConnect(&quot;HealthDB&quot;)

# query database
myData &lt;- sqlQuery(channel, &quot;SELECT
Country AS 'Country',
Year AS 'Year',
[96741] AS 'GDP growth (annual %)--WDI-2009',
[96841] AS 'GDP per capita (constant 2000 US$)--WDI-2009',
[99941] AS 'Population growth (annual %)--WDI-2009',
[100041] AS 'Population, total--WDI-2009'
FROM
(
SELECT DISTINCT CountryID, Country, Year, IndicatorID, IndValue
FROM [Time Series Data]
WHERE (
((IndicatorID) = 96741) OR
((IndicatorID) = 96841) OR
((IndicatorID) = 99941) OR
((IndicatorID) = 100041))
AND
(((CountryID) = 4118) OR
((CountryID) = 4125) OR
((CountryID) = 4129) OR
((CountryID) = 4134) OR
((CountryID) = 4141) OR
((CountryID) = 4145) OR
((CountryID) = 4164) OR
((CountryID) = 4186) OR
((CountryID) = 4213) OR
((CountryID) = 4327) OR
((CountryID) = 4219) OR
((CountryID) = 4221) OR
((CountryID) = 4227) OR
((CountryID) = 4230) OR
((CountryID) = 4243) OR
((CountryID) = 4326) OR
((CountryID) = 4268) OR
((CountryID) = 4272) OR
((CountryID) = 4273) OR
((CountryID) = 4325) OR
((CountryID) = 4300) OR
((CountryID) = 4308) OR
((CountryID) = 4309) OR
((CountryID) = 4311) OR
((CountryID) = 4316))
AND
(NOT (Year IS NULL)) AND (Year &gt;= 1960) AND
(Year &lt;= 2007))
ps
PIVOT (
MAX(IndValue)
FOR IndicatorID IN ([96741], [96841], [99941], [100041] ) )
AS
pvt
order by Country, Year&quot;)

#close connection
odbcClose(channel)

#Plot charts
plot(myData[3:6], col=&quot;orange&quot;, main=&quot;Select Indicators for Europe and Central Asia&quot;)
</pre>
<p>Here is the result</p>
<p><a href="http://eric.ness.net/wp-content/uploads/2009/11/Scatterplot.jpg"><img class="alignnone size-full wp-image-414" title="Scatterplot" src="http://eric.ness.net/wp-content/uploads/2009/11/Scatterplot.jpg" alt="Scatterplot" width="577" height="400" /></a></p>
<div class="shr-publisher-412"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://eric.ness.net/archives/scatterplots-using-r-and-mssql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Histogram Lattices Using R and MSSQL</title>
		<link>http://eric.ness.net/archives/histogram-lattices-using-r-and-mssql/</link>
		<comments>http://eric.ness.net/archives/histogram-lattices-using-r-and-mssql/#comments</comments>
		<pubDate>Thu, 26 Nov 2009 19:22:41 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Statistics]]></category>
		<category><![CDATA[Visualization]]></category>
		<category><![CDATA[R]]></category>

		<guid isPermaLink="false">http://eric.ness.net/?p=402</guid>
		<description><![CDATA[Creating Histogram Lattices Using R and MSSQL]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fhistogram-lattices-using-r-and-mssql%2F' data-shr_title='Histogram+Lattices+Using+R+and+MSSQL'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fhistogram-lattices-using-r-and-mssql%2F' data-shr_title='Histogram+Lattices+Using+R+and+MSSQL'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://eric.ness.net/wp-content/uploads/2009/11/histogramlattice.jpg"><img class="alignnone size-full wp-image-405" title="histogramlattice" src="http://eric.ness.net/wp-content/uploads/2009/11/histogramlattice.jpg" alt="" width="577" height="360" /></a></p>
<p>After getting Joseph Adler&#8217;s book &#8220;<a href="http://oreilly.com/catalog/9780596009427">Baseball Hacks</a>&#8221; I&#8217;ve been wanting to get in to <a href="http://www.r-project.org/">R</a>. R is simply an amazing open source statistics/graphing application. For this example we are going pull data from a MSSQL database and make a histogram lattice of a couple of countries.</p>
<p>First, I pulled the data from <a href="http://healthsystems2020.healthsystemsdatabase.org/datasets/timeseriesdataset.aspx">HealthSystems2020</a> time series database and imported the data in to MSSQL. I did some minor touch ups to the database giving the indicator an id etc. The second thing you need to do is create an ODBC connection for your database here is a fairly good <a href="http://www.devasp.com/samples/dsn_sql.asp">tutorial</a>. In this example I called my ODBC DSN &#8220;HealthDB&#8221;. Also make sure you adjust you sql query so that they are pulling the correct names/values.</p>
<p>Finally, here is the code:</p>
<pre class="brush: jscript; title: ; notranslate">

# includes
library(RODBC)
library(lattice)

# create connection
channel &lt;- odbcConnect(&quot;HealthDB&quot;)

# query database
myData &lt;- sqlQuery(channel, &quot;SELECT Country, IndValue
FROM         [YOURTABLE]
WHERE     (id = 96841) AND (
(Country = 'Afghanistan') OR
(Country = 'Bangladesh') OR
(Country = 'Bhutan') OR
(Country = 'India') OR
(Country = 'Maldives') OR
(Country = 'Nepal') OR
(Country = 'Pakistan') OR
(Country = 'China') OR
(Country = 'Indonesia') OR
(Country = 'Sri Lanka'))&quot;)

#close connection
odbcClose(channel)

#create histogram
histogram(~ myData[,3] | myData[,1], type=&quot;count&quot;, col=&quot;red&quot;, main = &quot;GDP per capita (constant 2000 US$)&quot;, xlab=&quot;Country&quot;)
</pre>
<p>And here is the result:<br />
<a href="http://eric.ness.net/wp-content/uploads/2009/11/histogram.jpg"><img class="alignnone size-full wp-image-403" title="histogram" src="http://eric.ness.net/wp-content/uploads/2009/11/histogram.jpg" alt="histogram" width="577" height="376" /></a></p>
<div class="shr-publisher-402"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://eric.ness.net/archives/histogram-lattices-using-r-and-mssql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>K-Means Document Clustering</title>
		<link>http://eric.ness.net/archives/k-means-document-clustering/</link>
		<comments>http://eric.ness.net/archives/k-means-document-clustering/#comments</comments>
		<pubDate>Fri, 06 Nov 2009 17:35:48 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visualization]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Statistics]]></category>

		<guid isPermaLink="false">http://eric.ness.net/?p=357</guid>
		<description><![CDATA[K-Means Document Clustering in C#]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fk-means-document-clustering%2F' data-shr_title='K-Means+Document+Clustering'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fk-means-document-clustering%2F' data-shr_title='K-Means+Document+Clustering'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://eric.ness.net/wp-content/uploads/2009/11/kmeans.jpg"><img class="alignnone size-full wp-image-364" title="kmeans" src="http://eric.ness.net/wp-content/uploads/2009/11/kmeans.jpg" alt="" width="577" height="360" /></a></p>
<p>Using our <a href="http://eric.ness.net/archives/plotting-documents-words-using-latent-semantic-indexing/">previous example</a> as a basis to move to the next step let&#8217;s take a look at clustering using the <a href="http://en.wikipedia.org/wiki/K-means_clustering">K-Means</a> clustering algorithm to group the documents in to their appropriate categories.</p>
<p>In the paper â€œ<a href="http://lsa.colorado.edu/papers/JASIS.lsi.90.pdf">Indexing by Latent Semantic Analysis</a>â€ (Deerwester et al.) they have an example of 9 titles of different papers grouped in to two categories â€œhuman computer interactionâ€ &amp; â€œgraphs &amp; treesâ€. So far, we&#8217;ve used <a href="http://eric.ness.net/archives/singular-value-decomposition/">Singular Value Decomposition</a> (SVD) and <a href="http://eric.ness.net/archives/latent-semantic-indexing/">Latent Semantic Indexing</a> (LSI) to better understand the relationship of words and documents. In the <a href="http://eric.ness.net/archives/plotting-documents-words-using-latent-semantic-indexing/">last blog post</a> we then took the results in LSI to plot words and documents on a two dimensional Cartesian plane.</p>
<p>All of this is pretty interesting stuff in and of itself however, the next step really is to see which documents belong in each group. One way to do this is by using K-Means clustering.</p>
<blockquote><p>Simply speaking k-means clustering is an algorithm to classify or to group your objects based on attributes/features into K number of group. K is positive integer number. The grouping is done by minimizing the sum of squares of distances between data and the corresponding cluster centroid. Thus the purpose of K-mean clustering is to classify the data. [<a href="http://people.revoledu.com/kardi/tutorial/kMean/WhatIs.htm">Kardi Teknomo</a>]</p></blockquote>
<p>A big chunk of the code is built off of the same project we are working on. I am using <a href="http://sites.google.com/site/docaresh/">Aresh Saharkhiz</a> K-Means implementation in the project with some minor changes/refactoring done by me.</p>
<p>Let take a look at the code!</p>
<p>This first part is the display (an ASP.NET app.)</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;%@ Page Language=&quot;C#&quot; AutoEventWireup=&quot;true&quot; CodeBehind=&quot;Default.aspx.cs&quot; Inherits=&quot;LSITest._Default&quot; %&gt;
&lt;%@ Register Assembly=&quot;DundasWebChart&quot; Namespace=&quot;Dundas.Charting.WebControl&quot; TagPrefix=&quot;DCWC&quot; %&gt;
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;

&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; &gt;
&lt;head runat=&quot;server&quot;&gt;
    &lt;title&gt;LSI Test&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;
    &lt;div&gt;
        &lt;DCWC:Chart ID=&quot;Chart1&quot; runat=&quot;server&quot; Height=&quot;400px&quot; Width=&quot;400px&quot;
            ImageType=&quot;Jpeg&quot;&gt;
            &lt;Legends&gt;
                &lt;DCWC:Legend Name=&quot;Default&quot; Alignment=&quot;Center&quot; Docking=&quot;Bottom&quot;&gt;&lt;/DCWC:Legend&gt;
            &lt;/Legends&gt;
            &lt;Titles&gt;
                &lt;DCWC:Title Name=&quot;Title1&quot;&gt;
                &lt;/DCWC:Title&gt;
            &lt;/Titles&gt;
            &lt;Series&gt;
                &lt;DCWC:Series Name=&quot;Series1&quot; ChartType=&quot;Point&quot; MarkerBorderColor=&quot;64, 64, 64&quot;
                    ShadowOffset=&quot;1&quot;&gt;
                &lt;/DCWC:Series&gt;
                &lt;DCWC:Series Name=&quot;Series2&quot; ChartType=&quot;Point&quot; MarkerBorderColor=&quot;64, 64, 64&quot;
                    ShadowOffset=&quot;1&quot;&gt;
                &lt;/DCWC:Series&gt;
                &lt;DCWC:Series Name=&quot;Series3&quot; ChartType=&quot;Point&quot; MarkerBorderColor=&quot;64, 64, 64&quot;
                    ShadowOffset=&quot;1&quot;&gt;
                &lt;/DCWC:Series&gt;
            &lt;/Series&gt;
            &lt;ChartAreas&gt;
                &lt;DCWC:ChartArea Name=&quot;Series2&quot;&gt;
                    &lt;axisy interval=&quot;0.5&quot; maximum=&quot;2&quot; minimum=&quot;-1&quot;&gt;
                        &lt;majorgrid linecolor=&quot;Gray&quot; linestyle=&quot;Dash&quot; /&gt;
                    &lt;/axisy&gt;
                    &lt;axisx interval=&quot;0.5&quot; maximum=&quot;2.5&quot; minimum=&quot;-0.5&quot;&gt;
                        &lt;majorgrid linecolor=&quot;Gray&quot; linestyle=&quot;Dash&quot; /&gt;
                    &lt;/axisx&gt;
                &lt;/DCWC:ChartArea&gt;
            &lt;/ChartAreas&gt;
        &lt;/DCWC:Chart&gt;
    &lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>This is the code behind for the ASP.NET page. Because we are only dealing with two known categories K-Means is plotting out the two categories and if you wanted to do more you would definitely have to re-write the ColorCodeDocuments function.</p>
<pre class="brush: jscript; title: ; notranslate">
using System;
using System.Data;
using System.Drawing;
using System.Web.UI;
using Dundas.Charting.WebControl;

namespace LSITest
{
    public partial class _Default : Page
    {
        /// &lt;summary&gt;
        /// Handles the Load event of the Page control.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;sender&quot;&gt;The source of the event.&lt;/param&gt;
        /// &lt;param name=&quot;e&quot;&gt;The &lt;see cref=&quot;System.EventArgs&quot;/&gt; instance containing the event data.&lt;/param&gt;
        protected void Page_Load(object sender, EventArgs e)
        {
            // Perform LSI
            var mylsi = new lsi();
            mylsi.LSITest();
            double[,] myDocs = mylsi.MyDocs;

            // Plot Documents and the k-means
            const string distanceType = &quot;manhattan&quot;;
            PlotDocuments(myDocs, mylsi.MyDocRowCount);
            PlotKMeansPoints(myDocs, 2, distanceType);
            ColorCodeDocuments(distanceType);

            // If you want to plot the words just un-comment the next two lines
            //double[,] myWords = mylsi.MyWords;
            //PlotWords(myDocs, mylsi.MyWordsRowCount);

            // comment this line out to show words in legend
            Chart1.Series[&quot;Series2&quot;].ShowInLegend = false;
        }

        /// &lt;summary&gt;
        /// Plots the words.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;myWords&quot;&gt;My words.&lt;/param&gt;
        /// &lt;param name=&quot;myWordsRowCount&quot;&gt;My words row count.&lt;/param&gt;
        private void PlotWords(double[,] myWords, int myWordsRowCount)
        {
            for (int i = 0; i &lt; myWordsRowCount; i++)
            {
                Chart1.Series[&quot;Series2&quot;].Points.AddXY(myWords[i, 0], myWords[i, 1]);
            }

            // Set point colors and shapes
            Chart1.Series[&quot;Series2&quot;].LegendText = &quot;Words&quot;;
            Chart1.Series[&quot;Series2&quot;].Color = Color.Gray;
            Chart1.Series[&quot;Series2&quot;].MarkerStyle = MarkerStyle.Circle;
            Chart1.Series[&quot;Series2&quot;].MarkerSize = 6;
        }

        /// &lt;summary&gt;
        /// Plots the documents.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;myDocs&quot;&gt;My docs.&lt;/param&gt;
        /// &lt;param name=&quot;myDocRowCount&quot;&gt;My doc row count.&lt;/param&gt;
        private void PlotDocuments(double[,] myDocs, int myDocRowCount)
        {
            // Load documents
            for (int i = 0; i &lt; myDocRowCount; i++)
            {
                Chart1.Series[&quot;Series1&quot;].Points.AddXY(myDocs[i, 0], myDocs[i, 1]);
            }

            // Set point colors and shapes
            Chart1.Series[&quot;Series1&quot;].LegendText = &quot;Documents&quot;;
            Chart1.Series[&quot;Series1&quot;].Color = Color.Red;
            Chart1.Series[&quot;Series1&quot;].MarkerStyle = MarkerStyle.Diamond;
            Chart1.Series[&quot;Series1&quot;].MarkerSize = 12;
        }

        /// &lt;summary&gt;
        /// Plots the K means points.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;items&quot;&gt;The items.&lt;/param&gt;
        /// &lt;param name=&quot;k&quot;&gt;The k.&lt;/param&gt;
        /// &lt;param name=&quot;distanceType&quot;&gt;&lt;/param&gt;
        private void PlotKMeansPoints(double[,] items, int k, string distanceType)
        {
            ClusterCollection clusters = kmeans.ClusterDataSet(k, items, distanceType);

            for (int i = 0; i &lt; clusters.Count; i++)
            {
                Chart1.Series[&quot;Series3&quot;].Points.AddXY(clusters[i].ClusterMean[0], clusters[i].ClusterMean[1]);
            }

            // Set point colors and shapes
            Chart1.Series[&quot;Series3&quot;].LegendText = &quot;Cluster&quot;;
            Chart1.Series[&quot;Series3&quot;].Color = Color.Gold;
            Chart1.Series[&quot;Series3&quot;].MarkerStyle = MarkerStyle.Star6;
            Chart1.Series[&quot;Series3&quot;].MarkerSize = 18;
        }

        /// &lt;summary&gt;
        /// Colors the code documents.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;distanceType&quot;&gt;Type of the distance.&lt;/param&gt;
        private void ColorCodeDocuments(string distanceType)
        {
            var myDist = new similarity();

            // Extract data
            DataSet myDocs = Chart1.DataManipulator.ExportSeriesValues(&quot;Series1&quot;);
            DataSet myKMeansPoints = Chart1.DataManipulator.ExportSeriesValues(&quot;Series3&quot;);

            // Document counter
            int count = 0;

            // Get co-ordinates for k-means points
            double firstKMeansX = Convert.ToDouble(myKMeansPoints.Tables[0].Rows[0][&quot;X&quot;]);
            double firstKMeansY = Convert.ToDouble(myKMeansPoints.Tables[0].Rows[0][&quot;Y&quot;]);
            double secondKMeansX = Convert.ToDouble(myKMeansPoints.Tables[0].Rows[1][&quot;X&quot;]);
            double secondKMeansY = Convert.ToDouble(myKMeansPoints.Tables[0].Rows[1][&quot;Y&quot;]);

            foreach (DataRow docRow in myDocs.Tables[0].Rows)
            {
                // get co-ordinates for current doc
                double currentDocX = Convert.ToDouble(docRow[&quot;X&quot;]);
                double currentDocY = Convert.ToDouble(docRow[&quot;Y&quot;]);

                // load in to arrays
                double[] firstX = {currentDocX, currentDocY};
                double[] firstY = {firstKMeansX, firstKMeansY};
                double[] secondX = {currentDocX, currentDocY};
                double[] secondY = {secondKMeansX, secondKMeansY};

                // find the distance
                double firstDist = myDist.FindDistance(firstX, firstY, distanceType);
                double secondDist = myDist.FindDistance(secondX, secondY, distanceType);

                // Color accordingly
                Chart1.Series[&quot;Series1&quot;].Points[count].Color = firstDist &lt; secondDist ? Color.Blue : Color.Gray;
                count++;
            }
        }
    }
}
</pre>
<p>This is the K-Means class written by Aresh Saharkhiz with my changes</p>
<pre class="brush: jscript; title: ; notranslate">
/// Most of this code was written by Aresh Saharkhiz
/// Re-organized by me
/// See Code Project: http://www.codeproject.com/KB/recipes/K-Mean_Clustering.aspx
using System;
using System.Collections;
using System.Data;
using System.Diagnostics;

namespace LSITest
{
    public class kmeans
    {
        /// &lt;summary&gt;
        /// Calculates The Mean Of A Cluster OR The Cluster Center
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;cluster&quot;&gt;
        /// A two-dimensional array containing a dataset of numeric values
        /// &lt;/param&gt;
        /// &lt;returns&gt;
        /// Returns an Array Defining A Data Point Representing The Cluster Mean or Centroid
        /// &lt;/returns&gt;
        public static double[] ClusterMean(double[,] cluster)
        {
            int rowCount = cluster.GetUpperBound(0) + 1;
            int fieldCount = cluster.GetUpperBound(1) + 1;
            var dataSum = new double[1,fieldCount];
            var centroid = new double[fieldCount];

            for (int j = 0; j &lt; fieldCount; j++)
            {
                for (int i = 0; i &lt; rowCount; i++)
                {
                    dataSum[0, j] = dataSum[0, j] + cluster[i, j];
                }

                centroid[j] = (dataSum[0, j]/rowCount);
            }

            return centroid;
        }

        /// &lt;summary&gt;
        /// Seperates a dataset into clusters or groups with similar characteristics
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;clusterCount&quot;&gt;The number of clusters or groups to form&lt;/param&gt;
        /// &lt;param name=&quot;data&quot;&gt;An array containing data that will be clustered&lt;/param&gt;
        /// &lt;param name=&quot;type&quot;&gt;&lt;/param&gt;
        /// &lt;returns&gt;A collection of clusters of data&lt;/returns&gt;
        public static ClusterCollection ClusterDataSet(int clusterCount, double[,] data, string type)
        {
            int rowCount = data.GetUpperBound(0) + 1;
            int fieldCount = data.GetUpperBound(1) + 1;
            int stableClustersCount = 0;
            double[] dataPoint;
            var random = new Random();
            Cluster cluster;
            var clusters = new ClusterCollection();
            var clusterNumbers = new ArrayList(clusterCount);
            var myDist = new similarity();

            while (clusterNumbers.Count &lt; clusterCount)
            {
                int clusterNumber = random.Next(0, rowCount - 1);

                if (!clusterNumbers.Contains(clusterNumber))
                {
                    cluster = new Cluster();
                    clusterNumbers.Add(clusterNumber);
                    dataPoint = new double[fieldCount];

                    for (int field = 0; field &lt; fieldCount; field++)
                    {
                        dataPoint.SetValue((data[clusterNumber, field]), field);
                    }

                    cluster.Add(dataPoint);
                    clusters.Add(cluster);
                }
            }

            while (stableClustersCount != clusters.Count)
            {
                stableClustersCount = 0;
                ClusterCollection newClusters = ClusterDataSet(clusters, data, type);

                for (int clusterIndex = 0; clusterIndex &lt; clusters.Count; clusterIndex++)
                {
                    if ((myDist.FindDistance(newClusters[clusterIndex].ClusterMean, clusters[clusterIndex].ClusterMean, type)) == 0)
                    {
                        stableClustersCount++;
                    }
                }

                clusters = newClusters;
            }

            return clusters;
        }

        /// &lt;summary&gt;
        /// Seperates a dataset into clusters or groups with similar characteristics
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;clusters&quot;&gt;A collection of data clusters&lt;/param&gt;
        /// &lt;param name=&quot;data&quot;&gt;An array containing data to b eclustered&lt;/param&gt;
        /// &lt;param name=&quot;type&quot;&gt;&lt;/param&gt;
        /// &lt;returns&gt;A collection of clusters of data&lt;/returns&gt;
        public static ClusterCollection ClusterDataSet(ClusterCollection clusters, double[,] data, string type)
        {
            double[] dataPoint;
            double firstClusterDistance = 0.0;
            int rowCount = data.GetUpperBound(0) + 1;
            int fieldCount = data.GetUpperBound(1) + 1;
            int position = 0;
            var myDist = new similarity();

            // create a new collection of clusters
            var newClusters = new ClusterCollection();

            for (int count = 0; count &lt; clusters.Count; count++)
            {
                var newCluster = new Cluster();
                newClusters.Add(newCluster);
            }

            if (clusters.Count &lt;= 0)
            {
                throw new SystemException(&quot;Cluster Count Cannot Be Zero!&quot;);
            }

            for (int row = 0; row &lt; rowCount; row++)
            {
                dataPoint = new double[fieldCount];

                for (int field = 0; field &lt; fieldCount; field++)
                {
                    dataPoint.SetValue((data[row, field]), field);
                }

                for (int cluster = 0; cluster &lt; clusters.Count; cluster++)
                {
                    double[] clusterMean = clusters[cluster].ClusterMean;

                    if (cluster == 0)
                    {
                        firstClusterDistance = myDist.FindDistance(dataPoint, clusterMean, type);
                        position = cluster;
                    }
                    else
                    {
                        double secondClusterDistance = myDist.FindDistance(dataPoint, clusterMean, type);

                        if (firstClusterDistance &gt; secondClusterDistance)
                        {
                            firstClusterDistance = secondClusterDistance;
                            position = cluster;
                        }
                    }
                }

                newClusters[position].Add(dataPoint);
            }

            return newClusters;
        }

        /// &lt;summary&gt;
        /// Converts the data table to array.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;table&quot;&gt;The table.&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public static double[,] ConvertDataTableToArray(DataTable table)
        {
            int rowCount = table.Rows.Count;
            int fieldCount = table.Columns.Count;

            var dataPoints = new double[rowCount,fieldCount];

            for (int rowPosition = 0; rowPosition &lt; rowCount; rowPosition++)
            {
                DataRow row = table.Rows[rowPosition];

                for (int fieldPosition = 0; fieldPosition &lt; fieldCount; fieldPosition++)
                {
                    double fieldValue;
                    try
                    {
                        fieldValue = double.Parse(row[fieldPosition].ToString());
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.ToString());
                        throw new InvalidCastException(&quot;Invalid row at &quot; + rowPosition + &quot; and field &quot; + fieldPosition,
                                                       ex);
                    }

                    dataPoints[rowPosition, fieldPosition] = fieldValue;
                }
            }

            return dataPoints;
        }
    }

    /// &lt;summary&gt;
    /// A class containing a group of data with similar characteristics (cluster)
    /// &lt;/summary&gt;
    [Serializable]
    public class Cluster : CollectionBase
    {
        private double[] _clusterMean;
        private double[] _clusterSum;

        /// &lt;summary&gt;
        /// The sum of all the data in the cluster
        /// &lt;/summary&gt;
        public double[] ClusterSum
        {
            get { return _clusterSum; }
        }

        /// &lt;summary&gt;
        /// The mean of all the data in the cluster
        /// &lt;/summary&gt;
        public double[] ClusterMean
        {
            get
            {
                for (int count = 0; count &lt; this[0].Length; count++)
                {
                    _clusterMean[count] = (_clusterSum[count]/List.Count);
                }

                return _clusterMean;
            }
        }

        /// &lt;summary&gt;
        /// Returns the one dimensional array data located at the index
        /// &lt;/summary&gt;
        public virtual double[] this[int index]
        {
            get
            {
                //return the Neuron at IList[index]
                return (double[]) List[index];
            }
        }

        /// &lt;summary&gt;
        /// Adds a single dimension array data to the cluster
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;data&quot;&gt;A 1-dimensional array containing data that will be added to the cluster&lt;/param&gt;
        public virtual void Add(double[] data)
        {
            List.Add(data);

            if (List.Count == 1)
            {
                _clusterSum = new double[data.Length];

                _clusterMean = new double[data.Length];
            }

            for (int count = 0; count &lt; data.Length; count++)
            {
                _clusterSum[count] = _clusterSum[count] + data[count];
            }
        }
    }

    /// &lt;summary&gt;
    /// A collection of Cluster objects or Clusters
    /// &lt;/summary&gt;
    [Serializable]
    public class ClusterCollection : CollectionBase
    {
        /// &lt;summary&gt;
        /// Returns the Cluster at this index
        /// &lt;/summary&gt;
        public virtual Cluster this[int index]
        {
            get
            {
                //return the Neuron at IList[index]
                return (Cluster) List[index];
            }
        }

        /// &lt;summary&gt;
        /// Adds a Cluster to the collection of Clusters
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;cluster&quot;&gt;A Cluster to be added to the collection of clusters&lt;/param&gt;
        public virtual void Add(Cluster cluster)
        {
            List.Add(cluster);
        }
    }
}
</pre>
<p>Here is the similarity class than can calculate Euclidean, Manhattan, Chebyshev, Minkowski distances</p>
<pre class="brush: jscript; title: ; notranslate">
/// Most of this code was written by Aresh Saharkhiz
/// Re-organized by me
/// See Code Project: http://www.codeproject.com/KB/recipes/Quantitative_Distances.aspx
using System;

namespace LSITest
{
    public class similarity
    {
        /// &lt;summary&gt;
        /// Finds the distance.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;x&quot;&gt;The x.&lt;/param&gt;
        /// &lt;param name=&quot;y&quot;&gt;The y.&lt;/param&gt;
        /// &lt;param name=&quot;type&quot;&gt;The type.&lt;/param&gt;
        /// &lt;param name=&quot;distanceType&quot;&gt;&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public double FindDistance(double[] x, double[] y, string distanceType)
        {
            double distance;

            switch (distanceType.ToLower())
            {
                case &quot;euclidean&quot;:
                    distance = EuclideanDistance(x, y);
                    break;
                case &quot;manhattan&quot;:
                    distance = ManhattanDistance(x, y);
                    break;
                case &quot;minkowski&quot;:
                    distance = MinkowskiDistance(x, y, 1);
                    break;
                case &quot;chebyshev&quot;:
                    distance = ChebyshevDistance(x, y);
                    break;
                default:
                    distance = 0.0;
                    break;
            }

            return distance;
        }

        /// &lt;summary&gt;
        /// Finds the Euclideans distance.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;x&quot;&gt;The x.&lt;/param&gt;
        /// &lt;param name=&quot;y&quot;&gt;The y.&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public double EuclideanDistance(double[] x, double[] y)
        {
            double sum = 0.0;

            if (x.GetUpperBound(0) != y.GetUpperBound(0))
            {
                throw new ArgumentException(&quot;the number of elements in x must match the number of elements in y&quot;);
            }

            int count = x.Length;

            for (int i = 0; i &lt; count; i++)
            {
                sum += Math.Pow(Math.Abs(x[i] - y[i]), 2);
            }

            double distance = Math.Sqrt(sum);
            return distance;
        }

        /// &lt;summary&gt;
        /// Finds Manhattan distance.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;x&quot;&gt;The x.&lt;/param&gt;
        /// &lt;param name=&quot;y&quot;&gt;The y.&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public double ManhattanDistance(double[] x, double[] y)
        {
            double sum = 0.0;

            if (x.GetUpperBound(0) != y.GetUpperBound(0))
            {
                throw new ArgumentException(&quot;the number of elements in x must match the number of elements in y&quot;);
            }

            int count = x.Length;

            for (int i = 0; i &lt; count; i++)
            {
                sum += Math.Abs(x[i] - y[i]);
            }

            double distance = sum;
            return distance;
        }

        /// &lt;summary&gt;
        /// Finds Chebyshevs distance.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;x&quot;&gt;The x.&lt;/param&gt;
        /// &lt;param name=&quot;y&quot;&gt;The y.&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public static double ChebyshevDistance(double[] x, double[] y)
        {
            if (x.GetUpperBound(0) != y.GetUpperBound(0))
            {
                throw new ArgumentException(&quot;the number of elements in x must match the number of elements in y&quot;);
            }
            int count = x.Length;
            var newData = new double[count];

            for (int i = 0; i &lt; count; i++)
            {
                newData[i] = Math.Abs(x[i] - y[i]);
            }
            double max = double.MinValue;

            foreach (double num in newData)
            {
                if (num &gt; max)
                {
                    max = num;
                }
            }
            return max;
        }

        /// &lt;summary&gt;
        /// Finds Minkowskis distance.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;x&quot;&gt;The x.&lt;/param&gt;
        /// &lt;param name=&quot;y&quot;&gt;The y.&lt;/param&gt;
        /// &lt;param name=&quot;order&quot;&gt;The order.&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        public double MinkowskiDistance(double[] x, double[] y, double order)
        {
            double sum = 0.0;

            if (x.GetUpperBound(0) != y.GetUpperBound(0))
            {
                throw new ArgumentException(&quot;the number of elements in x must match the number of elements in y&quot;);
            }
            int count = x.Length;

            for (int i = 0; i &lt; count; i++)
            {
                sum = sum + Math.Pow(Math.Abs(x[i] - y[i]), order);
            }

            double distance = Math.Pow(sum, (1 / order));
            return distance;
        }
    }
}
</pre>
<p>And finally the same LSI class used in the previous examples.</p>
<pre class="brush: jscript; title: ; notranslate">
using System;
using SmartMathLibrary;

namespace LSITest
{
    public class lsi
    {
        // this returns the formated html results
        public int MyDocColumnCount;
        public int MyDocRowCount;
        public double[,] MyDocs;
        public double[,] MyWords;
        public int MyWordsColumnCount;
        public int MyWordsRowCount;
        public string ToPrint;

        /// &lt;summary&gt;
        /// LISs the test.
        /// &lt;/summary&gt;
        public void LSITest()
        {
            //Create Matrix
            var testArray = new double[,]
                                {
                                    {1, 0, 0, 1, 0, 0, 0, 0, 0},
                                    {1, 0, 1, 0, 0, 0, 0, 0, 0},
                                    {1, 1, 0, 0, 0, 0, 0, 0, 0},
                                    {0, 1, 1, 0, 1, 0, 0, 0, 0},
                                    {0, 1, 1, 2, 0, 0, 0, 0, 0},
                                    {0, 1, 0, 0, 1, 0, 0, 0, 0},
                                    {0, 1, 0, 0, 1, 0, 0, 0, 0},
                                    {0, 0, 1, 1, 0, 0, 0, 0, 0},
                                    {0, 1, 0, 0, 0, 0, 0, 0, 1},
                                    {0, 0, 0, 0, 0, 1, 1, 1, 0},
                                    {0, 0, 0, 0, 0, 0, 1, 1, 1},
                                    {0, 0, 0, 0, 0, 0, 0, 1, 1}
                                };

            // Load array in to Matrix
            var a = new Matrix(testArray);

            // print original matrix
            PrintMatrix(a);

            // preform Latent Semantic Indexing
            GetDocumentWordPlots(a);
        }

        /// &lt;summary&gt;
        /// Prints the matrix.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;myMatrix&quot;&gt;My matrix.&lt;/param&gt;
        private void PrintMatrix(IMatrix myMatrix)
        {
            ToPrint += &quot;&lt;br /&gt;&lt;br /&gt;&quot;;

            for (int i = 0; i &lt; myMatrix.Rows; i++)
            {
                for (int j = 0; j &lt; myMatrix.Columns; j++)
                {
                    ToPrint += String.Format(&quot;{0:0.##}&quot;, myMatrix.MatrixData[i, j]) + &quot;\t&quot;;
                }
                ToPrint += &quot;&lt;br /&gt;&quot;;
            }
        }

        /// &lt;summary&gt;
        /// Gets the document word plots.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;myMatrix&quot;&gt;My matrix.&lt;/param&gt;
        private void GetDocumentWordPlots(Matrix myMatrix)
        {
            // Run single value decomposition
            var svd = new SingularValueDecomposition(myMatrix);
            svd.ExecuteDecomposition();

            // Put components into individual matrices
            Matrix wordVector = svd.U.Copy();
            Matrix sigma = svd.S.ToMatrix();
            Matrix documentVector = svd.V.Copy();

            // get value of k
            // you can also manually set the value of k
            var k = (int) Math.Floor(Math.Sqrt(myMatrix.Columns));

            // reduce the vectors
            Matrix reducedWordVector = CopyMatrix(wordVector, wordVector.Rows, k - 1);
            Matrix reducedSigma = CreateSigmaMatrix(sigma, k - 1, k - 1);
            Matrix reducedDocumentVector = CopyMatrix(documentVector, documentVector.Rows, k - 1);

            // Recalculate the matrix
            Matrix docs = reducedDocumentVector*reducedSigma;
            Matrix words = reducedWordVector*reducedSigma;

            // Fill doc plot locations
            MyDocs = new double[docs.Rows,docs.Columns];
            for (int i = 0; i &lt; docs.Rows; i++)
            {
                for (int j = 0; j &lt; docs.Columns; j++)
                {
                    MyDocs[i, j] = docs.MatrixData[i, j];
                }
            }

            // Fill word plot locations
            MyWords = new double[words.Rows,words.Columns];
            for (int i = 0; i &lt; words.Rows; i++)
            {
                for (int j = 0; j &lt; words.Columns; j++)
                {
                    MyWords[i, j] = words.MatrixData[i, j];
                }
            }

            // Set counts for charts
            MyDocRowCount = docs.Rows;
            MyWordsRowCount = words.Rows;

            PrintMatrix(docs);
            PrintMatrix(words);
        }

        /// &lt;summary&gt;
        /// Creates the sigma matrix.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;matrix&quot;&gt;The matrix.&lt;/param&gt;
        /// &lt;param name=&quot;rowEnd&quot;&gt;The row end.&lt;/param&gt;
        /// &lt;param name=&quot;columnEnd&quot;&gt;The column end.&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        private static Matrix CreateSigmaMatrix(IMatrix matrix, int rowEnd, int columnEnd)
        {
            var copyMatrix = new Matrix(rowEnd, columnEnd);

            for (int i = 0; i &lt; columnEnd; i++)
            {
                copyMatrix.MatrixData[i, i] = matrix.MatrixData[i, 0];
            }

            return copyMatrix;
        }

        /// &lt;summary&gt;
        /// Copies the matrix.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;myMatrix&quot;&gt;My matrix.&lt;/param&gt;
        /// &lt;param name=&quot;rowEnd&quot;&gt;The row end.&lt;/param&gt;
        /// &lt;param name=&quot;columnEnd&quot;&gt;The column end.&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        private static Matrix CopyMatrix(IMatrix myMatrix, int rowEnd, int columnEnd)
        {
            var copyMatrix = new Matrix(rowEnd, columnEnd);

            for (int i = 0; i &lt; rowEnd; i++)
            {
                for (int j = 0; j &lt; columnEnd; j++)
                {
                    copyMatrix.MatrixData[i, j] = myMatrix.MatrixData[i, j];
                }
            }

            return copyMatrix;
        }
    }
}
</pre>
<p>And what do the results look like?</p>
<p><a href="http://eric.ness.net/wp-content/uploads/2009/11/kmeansresults.jpg"><img class="alignnone size-full wp-image-361" style="margin-left: 100px; margin-right: 100px;" title="kmeansresults" src="http://eric.ness.net/wp-content/uploads/2009/11/kmeansresults.jpg" alt="kmeansresults" width="400" height="400" /></a></p>
<p>As you can see the K-Means clustering algorithm correctly grouped the documents in the appropriate categories.</p>
<p>Recommended reading and thanks goes to <a href="http://www.codeproject.com/KB/recipes/K-Mean_Clustering.aspx">Aresh Saharkhiz</a> for sharing his implementation of K-Means Clustering.</p>
<div class="shr-publisher-357"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://eric.ness.net/archives/k-means-document-clustering/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Plotting Documents &amp; Words: Using Latent Semantic Indexing</title>
		<link>http://eric.ness.net/archives/plotting-documents-words-using-latent-semantic-indexing/</link>
		<comments>http://eric.ness.net/archives/plotting-documents-words-using-latent-semantic-indexing/#comments</comments>
		<pubDate>Fri, 06 Nov 2009 00:32:22 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visualization]]></category>

		<guid isPermaLink="false">http://eric.ness.net/?p=338</guid>
		<description><![CDATA[Plotting Documents &#038; Words from LSI results]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fplotting-documents-words-using-latent-semantic-indexing%2F' data-shr_title='Plotting+Documents+%26+Words%3A+Using+Latent+Semantic+Indexing'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fplotting-documents-words-using-latent-semantic-indexing%2F' data-shr_title='Plotting+Documents+%26+Words%3A+Using+Latent+Semantic+Indexing'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://eric.ness.net/wp-content/uploads/2009/11/plotting.jpg"><img class="alignnone size-full wp-image-343" title="plotting" src="http://eric.ness.net/wp-content/uploads/2009/11/plotting.jpg" alt="" width="577" height="360" /></a></p>
<p>In the<a href="http://eric.ness.net/archives/latent-semantic-indexing/"> last blog post</a> we looked over a couple of great papers talking about using <a href="http://eric.ness.net/archives/singular-value-decomposition/">Singular Value Decomposition</a> (SVD) to do <a href="http://eric.ness.net/archives/latent-semantic-indexing/">Latent Semantic Indexing</a> (LSI) using the <a href="http://smartmathlibrary.codeplex.com/">SmartMathLibrary</a>. Now that we have the results we should plot them to get a sense of where these words and documents lay on a two dimensional Cartesian plane.</p>
<p style="text-align: left;">Jennifer Flynnâ€™s presentation &#8220;<a href="http://www.soe.ucsc.edu/classes/cmps290c/Spring07/proj/Flynn_talk.pdf">Latent Semantic Indexing Using SVD and Riemannian SVD</a>&#8221; actually goes on to tell us how to do this. Essentially the process is the same as before however, k must equal 2. We ended up with k = 2 in our previous example however, in larger examples k will more than likely be a different number. Regardless, here we want to end up with a matrix with two columns giving us our (x,y) &#8211; if you wanted to plot these items in a three dimensional space k=3 and if you find an awesome way to plot where k=5 e-mail me.Â  The formulas we use are as follows after we have performed SVD.</p>
<blockquote>
<p style="text-align: left;"><strong>Documents = U*âˆ‘</strong></p>
<p style="text-align: left;"><strong>Words = V*âˆ‘</strong></p>
</blockquote>
<p style="text-align: left;">The resulting matrices give us our (x,y) co-ordinates that we can then plot. I have been using the Dundas charting library for over two years now but the library is expensive so you should go and get the free library <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=130f7986-bf49-4fe5-9ca8-910ae6ea442c&amp;DisplayLang=en">here</a> since Microsoft acquired them and is a free download. And again for simplicities sake, this project is just a simple ASP.NET application.</p>
<p style="text-align: left;">The LSI Class:</p>
<p style="text-align: left;">Please note that this is almost exactly the same as in the previous blog however, here at the end of the GetDocumentWordPlots function we use the formulas mention above to load the co-ordinates of the words and documents in to a double array that we will ultimately pass to the chart.</p>
<pre class="brush: jscript; title: ; notranslate">
using System;
using SmartMathLibrary;

namespace LSITest
{
    public class lsi
    {
        // this returns the formated html results
        public int MyDocColumnCount;
        public int MyDocRowCount;
        public double[,] MyDocs;
        public double[,] MyWords;
        public int MyWordsColumnCount;
        public int MyWordsRowCount;
        public string ToPrint;

        /// &lt;summary&gt;
        /// LISs the test.
        /// &lt;/summary&gt;
        public void LSITest()
        {
            //Create Matrix
            var testArray = new double[,]
                                {
                                    {1, 0, 0, 1, 0, 0, 0, 0, 0},
                                    {1, 0, 1, 0, 0, 0, 0, 0, 0},
                                    {1, 1, 0, 0, 0, 0, 0, 0, 0},
                                    {0, 1, 1, 0, 1, 0, 0, 0, 0},
                                    {0, 1, 1, 2, 0, 0, 0, 0, 0},
                                    {0, 1, 0, 0, 1, 0, 0, 0, 0},
                                    {0, 1, 0, 0, 1, 0, 0, 0, 0},
                                    {0, 0, 1, 1, 0, 0, 0, 0, 0},
                                    {0, 1, 0, 0, 0, 0, 0, 0, 1},
                                    {0, 0, 0, 0, 0, 1, 1, 1, 0},
                                    {0, 0, 0, 0, 0, 0, 1, 1, 1},
                                    {0, 0, 0, 0, 0, 0, 0, 1, 1}
                                };

            // Load array in to Matrix
            var a = new Matrix(testArray);

            // print original matrix
            PrintMatrix(a);

            // preform Latent Semantic Indexing
            GetDocumentWordPlots(a);
        }

        /// &lt;summary&gt;
        /// Prints the matrix.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;myMatrix&quot;&gt;My matrix.&lt;/param&gt;
        private void PrintMatrix(IMatrix myMatrix)
        {
            ToPrint += &quot;&lt;br /&gt;&lt;br /&gt;&quot;;

            for (int i = 0; i &lt; myMatrix.Rows; i++)
            {
                for (int j = 0; j &lt; myMatrix.Columns; j++)
                {
                    ToPrint += String.Format(&quot;{0:0.##}&quot;, myMatrix.MatrixData[i, j]) + &quot;\t&quot;;
                }
                ToPrint += &quot;&lt;br /&gt;&quot;;
            }
        }

        /// &lt;summary&gt;
        /// Gets the document word plots.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;myMatrix&quot;&gt;My matrix.&lt;/param&gt;
        private void GetDocumentWordPlots(Matrix myMatrix)
        {
            // Run single value decomposition
            var svd = new SingularValueDecomposition(myMatrix);
            svd.ExecuteDecomposition();

            // Put components into individual matrices
            Matrix wordVector = svd.U.Copy();
            Matrix sigma = svd.S.ToMatrix();
            Matrix documentVector = svd.V.Copy();

            // get value of k
            var k = 2;

            // reduce the vectors
            Matrix reducedWordVector = CopyMatrix(wordVector, wordVector.Rows, k - 1);
            Matrix reducedSigma = CreateSigmaMatrix(sigma, k - 1, k - 1);
            Matrix reducedDocumentVector = CopyMatrix(documentVector, documentVector.Rows, k - 1);

            // Recalculate the matrix
            Matrix docs = reducedDocumentVector*reducedSigma;
            Matrix words = reducedWordVector*reducedSigma;

            // Fill doc plot locations
            MyDocs = new double[docs.Rows,docs.Columns];
            for (int i = 0; i &lt; docs.Rows; i++)
            {
                for (int j = 0; j &lt; docs.Columns; j++)
                {
                    MyDocs[i, j] = docs.MatrixData[i, j];
                }
            }

            // Fill word plot locations
            MyWords = new double[words.Rows,words.Columns];
            for (int i = 0; i &lt; words.Rows; i++)
            {
                for (int j = 0; j &lt; words.Columns; j++)
                {
                    MyWords[i, j] = words.MatrixData[i, j];
                }
            }

            // Set counts for charts
            MyDocRowCount = docs.Rows;
            MyWordsRowCount = words.Rows;

            PrintMatrix(docs);
            PrintMatrix(words);
        }

        /// &lt;summary&gt;
        /// Creates the sigma matrix.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;matrix&quot;&gt;The matrix.&lt;/param&gt;
        /// &lt;param name=&quot;rowEnd&quot;&gt;The row end.&lt;/param&gt;
        /// &lt;param name=&quot;columnEnd&quot;&gt;The column end.&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        private static Matrix CreateSigmaMatrix(IMatrix matrix, int rowEnd, int columnEnd)
        {
            var copyMatrix = new Matrix(rowEnd, columnEnd);

            for (int i = 0; i &lt; columnEnd; i++)
            {
                copyMatrix.MatrixData[i, i] = matrix.MatrixData[i, 0];
            }

            return copyMatrix;
        }

        /// &lt;summary&gt;
        /// Copies the matrix.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;myMatrix&quot;&gt;My matrix.&lt;/param&gt;
        /// &lt;param name=&quot;rowEnd&quot;&gt;The row end.&lt;/param&gt;
        /// &lt;param name=&quot;columnEnd&quot;&gt;The column end.&lt;/param&gt;
        /// &lt;returns&gt;&lt;/returns&gt;
        private static Matrix CopyMatrix(IMatrix myMatrix, int rowEnd, int columnEnd)
        {
            var copyMatrix = new Matrix(rowEnd, columnEnd);

            for (int i = 0; i &lt; rowEnd; i++)
            {
                for (int j = 0; j &lt; columnEnd; j++)
                {
                    copyMatrix.MatrixData[i, j] = myMatrix.MatrixData[i, j];
                }
            }

            return copyMatrix;
        }
    }
}
</pre>
<p>Here is the code behind for the web page that displays the chart and the matrices. Essentially we iterate through the double array pulled from the LSI class and load them in to a chart series.</p>
<pre class="brush: jscript; title: ; notranslate">
using System;
using System.Drawing;
using System.Web.UI;
using Dundas.Charting.WebControl;

namespace LSITest
{
    public partial class _Default : Page
    {
        /// &lt;summary&gt;
        /// Handles the Load event of the Page control.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;sender&quot;&gt;The source of the event.&lt;/param&gt;
        /// &lt;param name=&quot;e&quot;&gt;The &lt;see cref=&quot;System.EventArgs&quot;/&gt; instance containing the event data.&lt;/param&gt;
        protected void Page_Load(object sender, EventArgs e)
        {
            var mylsi = new lsi();
            mylsi.LSITest();
            Label1.Text = mylsi.ToPrint;
            double[,] myDocs = mylsi.MyDocs;
            double[,] myWords = mylsi.MyWords;

            // Load documents
            for (int i = 0; i &lt; mylsi.MyDocRowCount; i++)
            {
                Chart1.Series[&quot;Series1&quot;].Points.AddXY(myDocs[i, 0], myDocs[i, 1]);
            }

            // Load words
            for (int i = 0; i &lt; mylsi.MyWordsRowCount; i++)
            {
                Chart1.Series[&quot;Series2&quot;].Points.AddXY(myWords[i, 0], myWords[i, 1]);
            }

            // Set title
            Chart1.Series[&quot;Series1&quot;].LegendText = &quot;Documents&quot;;
            Chart1.Series[&quot;Series2&quot;].LegendText = &quot;Words&quot;;

            // Set point colors and shapes
            Chart1.Series[&quot;Series1&quot;].Color = Color.Red;
            Chart1.Series[&quot;Series1&quot;].MarkerStyle = MarkerStyle.Diamond;
            Chart1.Series[&quot;Series1&quot;].MarkerSize = 12;
            Chart1.Series[&quot;Series2&quot;].Color = Color.Gray;
            Chart1.Series[&quot;Series2&quot;].MarkerStyle = MarkerStyle.Circle;
            Chart1.Series[&quot;Series2&quot;].MarkerSize = 6;
        }
    }
}
</pre>
<p>And finally here is the ASP.NET web page.</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;%@ Page Language=&quot;C#&quot; AutoEventWireup=&quot;true&quot; CodeBehind=&quot;Default.aspx.cs&quot; Inherits=&quot;LSITest._Default&quot; %&gt;
&lt;%@ Register Assembly=&quot;DundasWebChart&quot; Namespace=&quot;Dundas.Charting.WebControl&quot; TagPrefix=&quot;DCWC&quot; %&gt;
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;

&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; &gt;
&lt;head runat=&quot;server&quot;&gt;
    &lt;title&gt;LSI Test&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;
    &lt;div&gt;
        &lt;DCWC:Chart ID=&quot;Chart1&quot; runat=&quot;server&quot; Height=&quot;400px&quot; Width=&quot;400px&quot;
            ImageType=&quot;Jpeg&quot;&gt;
            &lt;Legends&gt;
                &lt;DCWC:Legend Name=&quot;Default&quot; Alignment=&quot;Center&quot; Docking=&quot;Bottom&quot;&gt;&lt;/DCWC:Legend&gt;
            &lt;/Legends&gt;
            &lt;Titles&gt;
                &lt;DCWC:Title Name=&quot;Title1&quot;&gt;
                &lt;/DCWC:Title&gt;
            &lt;/Titles&gt;
            &lt;Series&gt;
                &lt;DCWC:Series Name=&quot;Series1&quot; ChartType=&quot;Point&quot; MarkerBorderColor=&quot;64, 64, 64&quot;
                    ShadowOffset=&quot;1&quot;&gt;
                &lt;/DCWC:Series&gt;
                &lt;DCWC:Series Name=&quot;Series2&quot; ChartType=&quot;Point&quot; MarkerBorderColor=&quot;64, 64, 64&quot;
                    ShadowOffset=&quot;1&quot;&gt;
                &lt;/DCWC:Series&gt;
            &lt;/Series&gt;
            &lt;ChartAreas&gt;
                &lt;DCWC:ChartArea Name=&quot;Series2&quot;&gt;
                    &lt;axisy interval=&quot;0.5&quot; maximum=&quot;2&quot; minimum=&quot;-1&quot;&gt;
                        &lt;majorgrid linecolor=&quot;Gray&quot; linestyle=&quot;Dash&quot; /&gt;
                    &lt;/axisy&gt;
                    &lt;axisx interval=&quot;0.5&quot; maximum=&quot;2.5&quot; minimum=&quot;-0.5&quot;&gt;
                        &lt;majorgrid linecolor=&quot;Gray&quot; linestyle=&quot;Dash&quot; /&gt;
                    &lt;/axisx&gt;
                &lt;/DCWC:ChartArea&gt;
            &lt;/ChartAreas&gt;
        &lt;/DCWC:Chart&gt;
        &lt;br /&gt;
        &lt;asp:Label ID=&quot;Label1&quot; runat=&quot;server&quot; Text=&quot;&quot;&gt;&lt;/asp:Label&gt;
    &lt;/div&gt;
    &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>So lets see the result!</p>
<p><a href="http://eric.ness.net/wp-content/uploads/2009/11/documents.jpg"><img class="alignnone size-full wp-image-341" style="margin-left: 100px; margin-right: 100px;" title="documents" src="http://eric.ness.net/wp-content/uploads/2009/11/documents.jpg" alt="documents" width="400" height="400" /></a></p>
<p>Now obviously you could/should probably write this a different way but it gets you to where you need to be.</p>
<p>I would also recommend you read in Flynn&#8217;s presentation on how to compare two words/documents by using the dot product of two row vectors. Or one could also use the <a href="http://eric.ness.net/archives/euclidean-distance-score/">Euclidean Distance Score</a>. And if you are also interested I would recommend Sujit Pal&#8217;s blog post &#8220;<a href="http://sujitpal.blogspot.com/2008/10/ir-math-in-java-cluster-visualization.html">IR Math in Java : Cluster Visualization</a>&#8221; for additional reading.</p>
<div class="shr-publisher-338"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://eric.ness.net/archives/plotting-documents-words-using-latent-semantic-indexing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Backtesting With Heat Maps</title>
		<link>http://eric.ness.net/archives/backtesting-with-heat-maps/</link>
		<comments>http://eric.ness.net/archives/backtesting-with-heat-maps/#comments</comments>
		<pubDate>Mon, 25 May 2009 15:56:24 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Visualization]]></category>
		<category><![CDATA[Stocks]]></category>

		<guid isPermaLink="false">http://eric.ness.net/?p=204</guid>
		<description><![CDATA[I have found that placing back test data in to heat maps and animating it over time is a great way to visualize the data.]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fbacktesting-with-heat-maps%2F' data-shr_title='Backtesting+With+Heat+Maps'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fbacktesting-with-heat-maps%2F' data-shr_title='Backtesting+With+Heat+Maps'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://eric.ness.net/wp-content/uploads/2009/05/backtesting-with-heat-maps.jpg"><img class="alignnone size-full wp-image-205" title="backtesting-with-heat-maps" src="http://eric.ness.net/wp-content/uploads/2009/05/backtesting-with-heat-maps.jpg" alt="" width="577" height="360" /></a></p>
<p>I have found that placing back test data in to heat maps and animating it over time is a great way to visualize the data. You get some cool results with some crazy patterns.</p>
<div class="shr-publisher-204"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://eric.ness.net/archives/backtesting-with-heat-maps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Map Resources</title>
		<link>http://eric.ness.net/archives/map-resources/</link>
		<comments>http://eric.ness.net/archives/map-resources/#comments</comments>
		<pubDate>Tue, 10 Jun 2008 05:03:43 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Visualization]]></category>
		<category><![CDATA[Maps]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://eric.ness.net/?p=48</guid>
		<description><![CDATA[I have been a bit of research on a couple of map resources I thought I would put together.]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fmap-resources%2F' data-shr_title='Map+Resources'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fmap-resources%2F' data-shr_title='Map+Resources'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://eric.ness.net/wp-content/uploads/2008/06/maps.jpg"><img class="alignnone size-full wp-image-45" title="maps" src="http://eric.ness.net/wp-content/uploads/2008/06/maps.jpg" alt="" width="577" height="360" /></a></p>
<p>I have been a bit of research on a couple of map resources I thought I would put together.</p>
<p><a href="http://www.arc2earth.com">Arc2Earth</a></p>
<p><a href="http://geochalkboard.wordpress.com/2007/08/27/integrating-arcgis-and-google-earth-for-crime-analysis/">Integrating ArcGIS and Google Earth for Crime Analysis</a></p>
<p><a href="http://thematicmapping.org/">thematicmapping.org</a></p>
<p><a href="http://www.gpsvisualizer.com/map?form=googleearth">Convert your GPS data for use in Google Earth</a></p>
<p><a href="http://mapki.com/wiki/Add_Your_Own_Custom_Map">Add Your Own Custom Map</a></p>
<p><a href="http://mapki.com/wiki/Automatic_Tile_Cutter">Automatic Tile Cutter</a></p>
<p><a href="http://maps.forum.nu/">Some experiments with Google Maps</a></p>
<p><a href="http://econym.googlepages.com/index.htm">Google Maps API Tutorial</a></p>
<div class="shr-publisher-48"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://eric.ness.net/archives/map-resources/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ubigraph</title>
		<link>http://eric.ness.net/archives/ubigraph/</link>
		<comments>http://eric.ness.net/archives/ubigraph/#comments</comments>
		<pubDate>Thu, 22 May 2008 14:20:18 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visualization]]></category>

		<guid isPermaLink="false">http://eric.ness.net/?p=41</guid>
		<description><![CDATA[UbiGraph is a tool for visualizing dynamic graphs. It works with Python, Ruby, PHP, Java, C, C++, C#, Haskell, and OCaml. For More info check it out here.]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fubigraph%2F' data-shr_title='Ubigraph'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fubigraph%2F' data-shr_title='Ubigraph'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><img src="http://eric.ness.net/wp-content/uploads/2008/05/ubigraph.jpg" /></p>
<p>UbiGraph is a tool for visualizing dynamic graphs. It works with Python, Ruby, PHP, Java, C, C++, C#, Haskell, and OCaml. For More info check it out <a href="http://www.ubietylab.net/ubigraph/index.html">here</a>.</p>
<div class="shr-publisher-41"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://eric.ness.net/archives/ubigraph/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Timeline .NET</title>
		<link>http://eric.ness.net/archives/timeline-net/</link>
		<comments>http://eric.ness.net/archives/timeline-net/#comments</comments>
		<pubDate>Thu, 27 Mar 2008 01:49:22 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visualization]]></category>

		<guid isPermaLink="false">http://eric.ness.net/blog/archives/timeline-net/</guid>
		<description><![CDATA[<a href="http://weblogs.asp.net/rchartier/">Rob Chartier</a> just released an <a href="http://www.codeplex.com/timelinenet">API wrapper for .NET</a> of the <a title="Smile Timeline" href="http://simile.mit.edu/timeline/">MIT Simile Timeline API</a> and this thing is pretty cool.]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Ftimeline-net%2F' data-shr_title='Timeline+.NET'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Ftimeline-net%2F' data-shr_title='Timeline+.NET'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://weblogs.asp.net/rchartier/">Rob Chartier</a> just released an <a href="http://www.codeplex.com/timelinenet">API wrapper for .NET</a> of the <a title="Smile Timeline" href="http://simile.mit.edu/timeline/">MIT Simile Timeline API</a> and this thing is pretty cool.</p>
<p>[<a href="http://weblogs.asp.net/rchartier/archive/2008/03/25/timeline-net.aspx">read full article</a>]</p>
<div class="shr-publisher-13"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://eric.ness.net/archives/timeline-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Flash Force Directed Graph</title>
		<link>http://eric.ness.net/archives/flash-force-directed-graph/</link>
		<comments>http://eric.ness.net/archives/flash-force-directed-graph/#comments</comments>
		<pubDate>Wed, 22 Aug 2007 00:01:52 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Visualization]]></category>

		<guid isPermaLink="false">http://eric.ness.net/blog/archives/flash-force-directed-graph/</guid>
		<description><![CDATA[I came across this nice little flash force directed graph today. It was put together by <a href="http://www.creativesynthesis.net/blog/projects/graph-gear/">Creative Synthesis</a>.]]></description>
			<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fflash-force-directed-graph%2F' data-shr_title='Flash+Force+Directed+Graph'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Feric.ness.net%2Farchives%2Fflash-force-directed-graph%2F' data-shr_title='Flash+Force+Directed+Graph'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetTop Automatic --><p>I came across this nice little flash force directed graph today. It was put together by <a href="http://www.creativesynthesis.net/blog/projects/graph-gear/">Creative Synthesis</a>.</p>
<p><a title="Force Directed Grapg" href="http://eric.ness.net/blog/wp-content/uploads/2007/08/force-directed-graph.jpg"></a></p>
<p>The thing that makes this nice actually is (a) it works and (b) the xml file is very intuitive.</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;graph title=&quot;Sample Graph&quot; bgcolor=&quot;ffffff&quot; linecolor=&quot;cccccc&quot; viewmode=&quot;display&quot; width=&quot;725&quot; height=&quot;400&quot;&gt;
     &lt;node id=&quot;n1&quot; text=&quot;Some Text&quot; image=&quot;Some Image Link&quot; link=&quot;Some Link&quot; scale=&quot;100&quot; color=&quot;0000ff&quot; textcolor=&quot;0000ff&quot;/&gt;
     &lt;node id=&quot;n2&quot; text=&quot;Some Text&quot; image=&quot;Some Image Link&quot; link=&quot;Some Link&quot; scale=&quot;100&quot; color=&quot;0000ff&quot; textcolor=&quot;0000ff&quot;/&gt;
     &lt;node id=&quot;n3&quot; text=&quot;Some Text&quot; image=&quot;Some Image Link&quot; link=&quot;Some Link&quot; scale=&quot;100&quot; color=&quot;0000ff&quot; textcolor=&quot;0000ff&quot;/&gt;

     &lt;edge sourceNode=&quot;n1&quot; targetNode=&quot;n2&quot; label=&quot;Some Label&quot; textcolor=&quot;555555&quot;/&gt;
     &lt;edge sourceNode=&quot;n1&quot; targetNode=&quot;n3&quot; label=&quot;Some Label&quot; textcolor=&quot;555555&quot;/&gt;
&lt;/graph&gt;
</pre>
<p>Doesn&#8217;t get much simpler.</p>
<div class="shr-publisher-8"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><!-- End Shareaholic LikeButtonSetBottom Automatic -->]]></content:encoded>
			<wfw:commentRss>http://eric.ness.net/archives/flash-force-directed-graph/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

