Thursday, 23 April 2009

British MP’s Expenses Data Visualisation via Virtual Earth CTP

 

Following on from my previous blog on US Politicians data visualisation using a listbox, this time I’ve moved across the pond to my homeland and created one for British Politician’s Expenses (a bit of a hot topic in the UK at present) based on the CTP of the Virtual Earth for Silverlight control.

The application enables you to quickly view Members of Parliament (MP) expenses for 2007/08 based on:

  • Location / Political Party (colour of the pin)
  • Travel expenses (opacity of the pin)
  • Second home allowance (size of the pin)

Note: An MP represents ~100k people, so map gives a good indication of population density across Britain.

Using the Search tool you can filter the results  based on MP’s name/constituency Travel expenses and second home allowance. Any changes to the map are reflected in the pages URL making it easy to share custom reports via the share button on Twitter, Digg, Facebook and Email.

E.g. the link blow shows MPs in the South East of England:

http://home.btconnect.com/martibiz/mps.htm#?s=&t=0&h=0&y=51.5417&x=-0.1491&z=12

Sample screen shot 

Tech notes:

The visualisation makes use of Client Technical Preview (CTP). The data is sourced from the Guardian MP expense claims with MP geo data coming from TheyWorkForYou, though some data cleansing was required to link the two sets of data. The data is pulled in as  JSON, to keep things as fast as possible I embedded the JSON in the XAP assembly and loaded it using the following code:

void LoadMPdetails()
   {
       Stream file = Assembly.GetExecutingAssembly().GetManifestResourceStream("mmMPs.Assets.mpDetails.js"); 
       TextReader tr = new StreamReader(file);

       JsonArray jsonArray = (JsonArray)JsonArray.Load(tr);

       mps = new List<MP>();

       foreach (JsonObject jsonItem in jsonArray)
       {
           MP item = new MP();
           item.name = jsonItem["name"];
           item.constituency =  jsonItem["constituency"];
           item.party =  jsonItem["party"];
           mps.Add(item);
       }
   }

Even though this is a Silverlight 2.0 application we support deep linking (added to Silverlight 3.0 beta) so you can create custom views and share the links with your friends. Each time the viewport is changed or a search preformed the pages URL is updated and added to the browsers page history using  JQuery and jquery.history and some C# code provided by nerdplusart.com

The code below shows the logic to display the push pin with the tooltips:

private void AddPin2(Loc con)
        {
            // pushpin image
            Image image = new Image();

            if (con.mp == null)
                image.Source = new BitmapImage(new Uri("/assets/pinMagenta.png", UriKind.Relative));
            else        
            switch (con.mp.party)
            {
                case "Liberal Democrat":
                    image.Source = new BitmapImage(new Uri("/assets/pinYellow.png", UriKind.Relative));
                    break;

                case "Conservative":
                    image.Source = new BitmapImage(new Uri("/assets/pinBlue.png", UriKind.Relative));
                    break;
  
                case "Labour":
                    image.Source = new BitmapImage(new Uri("/assets/pinRed.png", UriKind.Relative));
                    break;

                default:
                    image.Source = new BitmapImage(new Uri("/assets/pinMagenta.png", UriKind.Relative));
                    break;
            }

            int size = 35;
            if (con.expense.Cost_Of_Staying_Away_From_Main_Home > 5000)
                size = (int) Math.Min(( (con.expense.Cost_Of_Staying_Away_From_Main_Home - 5000) / 5000) * 10 + 35,80);
            image.Width = size; image.Height = size;

            if (con.expense.Cost_Of_Staying_Away_From_Main_Home < 500)
                image.Opacity = 0.6;
            else
                image.Opacity = 0.6 + (con.expense.Cost_Of_Staying_Away_From_Main_Home / 23000);
            

            image.MouseEnter += new System.Windows.Input.MouseEventHandler(i_MouseEnter);
            image.MouseLeave += new System.Windows.Input.MouseEventHandler(i_MouseLeave);
            image.MouseLeftButtonDown +=new System.Windows.Input.MouseButtonEventHandler(image_MouseLeftButtonDown); // += new System.Windows.Input.MouseButtonEventHandler(image_MouseLeftButtonUp);


            // Add Tooltip
            var tooltipObject = new StackPanel();

            var title = new TextBlock();
            title.FontWeight = FontWeights.Bold;
            title.Text = con.name;
            tooltipObject.Children.Add(title);
            
            var description = new TextBlock();
            if (con.mp != null)
                description.Text = con.mp.party + " - " + con.mp.name + "\n\n" +getExpenseReport(con.expense); // .Total_Allowances_Claimed_Inc_Travel ; // "Info goes here....."; // "This is an arbitrary description of the \"Huge Square\" to be displayed within the Tooltip.";
            tooltipObject.Children.Add(description);

            image.Tag = con.name;

            ToolTipService.SetToolTip(image, tooltipObject);
            
            //Add the pushpin to the Map 
            myMap.Children.Add(image);

            //Position the pushpin using the attached properties 
            MapLayer.SetMapPosition(image, new Location(con.centre_lat, con.centre_lon));
            MapLayer.SetMapPositionMethod(image, PositionMethod.BottomLeft);

        }

Things I would have liked to do if I had the time:

Better control of the map pins when zooming out, would like some form of clustering and pins to be a bit smaller, 600+ large pins is too much for a place the size of Britain.

Restrict zoom level and panning just to the UK, as things get a bit confusing for the user seeing a small island with los of dots.

Host via Silverlight Streaming, but couldn’t figure out how I could get the deep linking working from an IFRAME hosted on a different domain.

Make the tooltip timeouts longer, but this isn’t a trivial task, though you can find a ToolTipService on codeplex that supports such a feature.

Friday, 27 February 2009

Open Street Map to XAML

After playing around with maps in my previous post, Silverlight USA States Visualisation, I decided to check out the maps at OpenStreetMap and see if I could embed them into a simple Silverlight app, for which you can see a live demo here.

app

Step 1 – Grab the data

This is very easy, just zoom into the location you want and then hit the Export tab, select format PDF and download your PDF image and save the file to disk e.g map.pdf.

streetmap

Once downloaded check all is ok (I had to download twice for some reason as first download was corrupted).

Step 2 – Import to Expression Design

To do this create rename the file to map.ai and import the data (File/Import) into Expression Design. At this stage you may want to delete some of the features, e.g. cost lines, borders etc.

For more info on this step check of post by Tim Heuer.

Step 3 – Export to Silverlight XAML

Select the File/Export and select Silverlight option this will then give you a map.xaml.

In my XAML I noticed 4 <image> of the format shown below, which I striped out of the XAML.

<

Image Source="Ipswich - Open Street Map_files/image3.png"/>

Step 4 – Embed in your Silverlight project

I pasted the contents into  and paste contents of map.xaml into your canvas..

code1

In the app I just add a scale factor based on the mouse wheel ( using Pete Blois MouseWheelHelper class), which works ok but doesn’t update the horizontal / vertical bar sizes/ranges.

code2 See online version here.

A note on file Sizes

The PDF I used for a medium sized English town (Ipswich) resulted in a 700K PDF file. Once converted to XAML this grew to 5.9MB (and still 1.7MB zipped). Trying to edit such a large file in VS2008 proved very slow which each edit of the file taking 10 seconds, hope VS2010 is faster.

Deep earth

For most Silverlight mapping tasks you would probably be better off using something like DeepEarth which makes use of DeepZoom, and a custom map source provider to enable Open Street Map data to be displayed within a Silverlight app, though not sure of the terms and conditions of using OpenStreetMap tile server, but you can see a live demo at http://deepzoom.soulclients.com/osm/.

Monday, 23 February 2009

Silverlight USA States Visualisation

Tim Heuer challenged his readers to create a Silverlight visualisation application; this is my entry…….

It displays visualisation of the following name value pairs (stored as embedded text files) from Wikipedia of:

  • Average salary per state
  • US elections 2008 votes per state - Wikipeida
  • Population per state - Wikipeidia

Other sources of info are on Wikipedia.

Step 1 - Simple Listbox

Each set of name value pairs are stored in their own embedded text file, which are then are then loaded into a observable type and bound to a list box. A slider bar then allows the user to filter the results. The data binding worked well but looked so 2003, so it was time to jazz it up.

Step 2 - Basic Item Template

I then put a nice border around items, could have added some simple graphics, bound the data to colour and opacity attributes, that would have made it a bit better but still it’s so 2005.

Step 3 - Advanced Item Template with paths

Then I remembering seeing a blog of a WPF app that created a USA map from a list box, so I ported the app to Silverlight, this required me to:

  • Resolve issues of Silverlight not supporting binding of certain types
  • Replacing XML data source with my custom observable type
  • Tweaking animation effects
  • Tweaking labels so they weren’t clipped by the state

The results are a great example of the strength of data binding to a custom list box to totally transform an app from a dull winforms style list box to an advanced visualisation. Using these features in WPF/Silverlight makes it very easy to separate the visualisation from data, and the ZAP file is only 36Kb, smalled than a PNG of the screenshot!

Due to time contains there are still a few rough edges, the animation could be a bit slicker, button designs could be improved any fixing the z-order of the selected state.

Future enhancements could include:

  • More complex data type, e.g. third axis to include time
  • Load your own data via local text file
  • Embeddable widget
  • Extra maps

Monday, 14 April 2008

Welcome

This is one of many blog sites I've created, perhaps I might come back some time and update it? For more info on me check out friendfeed.com/martimedia for an overall summary of my online life. Martin