Wednesday, February 09, 2011

Engineering tricks with WolframAlpha

I’ve found Google great for simple problems like this:

20 pounds per cubic foot in kilograms per cubic meter= 320.36926 kilograms per cubic meter

But wolframalpha also lets you combine unit conversions with calculations:

(2 * 175 grams) per square meter * (2*3 meters squared) + ((20 pounds per cubic foot in kilograms per cubic meter) * 3 square meters * 5 millimeters)

Or just click on this link: http://www.wolframalpha.com/input/?i=(2+*+175+grams)+per+square+meter+*+(2*3+meters+squared)+%2B+((20+pounds+per+cubic+foot+in+kilograms+per+cubic+meter)+*+3+square+meters+*+5+millimeters)

What’s the above tell me? It’s the theoretical weight of the kayak I’m currently building – about 7kg. In reality when hand laying fibreglass you get a much higher weight of epoxy rather than the one to one ratio that’s possible under vacuum application and which I’m using above.

Hull fibreglassing

It’s taken awhile to get here, but the hull is now fibreglassed.

  • After struggling with the Resene colorwood stain affecting epoxy seal coats I found that a wash with isopropyl alcohol made for a nice clean bonding surface.
  • I rediscovered how to apply epoxy, everyone seems to have their own method but for me it’s plastic cards (old atm cards/loyalty cards etc are ideal) and short foam (usually yellow) rollers.
  • A hot air gun does absolute wonders at getting rid of air bubbles/foam.
  • I used high density 170g/sq m fibreglass that’s often used for model making. That equates to 5 ounce high density fibreglass which should be pretty strong (easy way to do the conversion… just use google – type “175 grams per square meter in ounces per square yard” in the search box).
  • Wet sanding within 48 hours is more effectively at smoothing the epoxy finish than waiting for it to set really hard.

second hull fill coat

Thursday, February 03, 2011

Hull ready to be fibreglassed

Finally completed staining/fairing/sanding the hull. Long process with lots of waiting for epoxy to dry. Here’s a photo of how the hull looks wetted down. The staining in combination with a kind of matching fairing compound does look patchy but I’ll roll on a very thin layer of epoxy to seal the wood before the fibreglass goes on and that will darken it down and make it look a lot more consistent.

WP_000022

Wednesday, January 26, 2011

Stems added and fairing the hull

Slow progress on the Black Pearl (yet to give it my own name yet) kayak. I’ve added stems (just the white paulownia so not so tough but shows up nicely against the stained hull), and I’ve been applying a fairing compound made of epoxy, lightweight filler, wood dust etc.

Just waiting 7 days now for it to thoroughly set before I sand back.

Here’s a pic:

 

20

Biggest lesson from all this… get the strips flat before staining! Basically the better the stripping the easier the rest will be.

Staining has been interesting… painful but interesting. The Resene Colorwood stain does work but you definitely need only a light rag application and maybe a wash with water after it’s set up. For the fairing I’ve managed to replicate the color using epoxy colours (black, blue and red – I watched them making it at Resene so I knew the constituent colours and proportions – it was on a their computer screen Smile).

Hard to get a good photo while it sits in the garage but this boat looks real sleek.

Monday, December 27, 2010

Hull Stripping and Attempted Staining

Stripping was relatively easy and very quick. The wood reminded me of making balsa wood models when I was a kid:)

Main points were:

  • Make sure strips are even thickness – if I do this again I’ll invest in a planner thicknesser.

WP_000011

  • I mostly just stapled strips only occasionally using a bead of glue – this had one advantage – towards the end as I looked at the forms and the shape of the hull I realised I had one form on  slightly wrong angle – not sure how this happened as I was sure I had it right at the beginning. Nevermind, I unscrewed it and re-adjusted just a tiny bit and suddenly it looked great.
  • I thought I’d stain the strips before using epoxy to glue them all thogether – unfortunately, Resene interior stain turns out to not be as epoxy compatible as the Resene staff thought it would be. It beaded a bit but wasn’t irrecoverable – I might even put more stain on after I rub it all back in preparation for fibreglassing – but if I do I’ll wash with acetone and use a much thinner application of stain. Check the image below…

WP_000024

 

Hull looks great but I can’t get a good photo showing it the way I see it in real life. Perhaps for the next posting…

Wednesday, December 08, 2010

Spatial Notes–Getting Started

Thought this would be harder than it turned out to be.

Objective: chart some metrics across geographic regions (in my case looking at customer metrics over New Zealand).

To get started I took advantage of SQL Server Spatial. Initially appearances are a  bit daunting until you try it… and it’s fairly easy.

  • Finding the GIS data
    • for NZ  Statistics NZ publish digital boundaries – versioned by publication year (2007, 2001, 1996 etc: http://www.stats.govt.nz/browse_for_stats/people_and_communities/geographic-areas/download-digital-boundaries.aspx
    • The data is available in both ESRI Shapefile format and MapInfo format. You can use shape2sql to load this data into sql server spatial. Unfortunately… it has a bug, it won’t create a table from the shp file inside shape2sql – I had to use SQL Profiler to capture the create table instruction and run it interactively – after that the data load works fine - not sure why.
    • The data has a hierarchy of increasingly larger geometrical areas made up of units of the smallest size (the meshblock). There’s Area Units, Urban Areas, Regional Councils etc.
  • Connecting people to areas
  • Aggregating
    • Use SQL Server Analysis Services, or much faster
    • Use PowerPivot – for me this allowed me to very quickly aggregate customer metrics from an internal database across areas loaded from the Stats NZ files
  • Reporting
    • It’d be nice if Excel had spatial reporting support, but it doesn’t – big thumbs down Microsoft…
    • I used SQL Server Reporting Services and the Map control. Problem is that I need to have the map data in SQL/SSAS. It’d be nice to load from PowerPivot but I can’t do that unless I store the Excel PowerPivot doc in Sharepoint 2010. Jumping through hoops to do this though… Microsoft – just get the spatial support into Excel please!

Sunday, December 05, 2010

Strip cutting

I followed Bjorn’s instructions and cut the strips with a circular saw. The planks were pinned to a folding stand at each end. The paulownia was extremely stable. It didn’t split when I pinned it at the edge of the plank. Not one of the strips split or snapped. In the end it was much easier than I expected. Suspect it would’ve been even easier if I had a decent saw…

Photo0045

Ebonizing Paulownia

Vinegar and steel wool, left for a few days, filtered and then applied to paulownia strip – thinking of using this on my kayak. Top of the strip has been painted twice.

Photo0047

Sunday, November 28, 2010

Black Pearl Forms

So terribly slow but here’s a snippet of the forms.

IMG_1180

 

Lessons learned:

  • Level everything first – makes it much easier to align cross sections
  • Don’t start screwing cross sections to wooden cross bars until they all line up right. Use clamps first.
  • Drill a hole about 5mm on the center of the waterline and shine a bright light from one end – you should be able to see the light all the way down
  • I pre-cut the forms for the deck and re-attached them – supposedly to make it easier for later. Not sure it was worth it.

Here’s that light shining through a couple of the holes.

IMG_1182

Tuesday, October 05, 2010

New Kayak Build: Black Pearl

Two years on from building a Guillemot Kayaks Night Heron stitch and glue I’ve just purchased plans for a Bjorn Thomasson Black Pearl. The Night Heron is a great kayak that’s very quick in the water but I just enjoyed the building side too much so I’ve decided to try building a strip kayak. Rather than go with something closer to the Night Heron I decided to go down a slightly different path:

  • As light as possible – means small or low volume
  • Doesn’t need speed – the Night Heron fulfils that requirement for me
  • Play boat – I’ve taken up canoe polo so I want the most manuverable sea kayak experience I can get – something that will respond to hip/torso movement.

I think the Black Pearl will do this but the proof will be in the pudding. You don’t just order this off the book – the plans are custom printed to your height, arm span and hip measurements.

I’ll update the blog as I go. It will take awhile – no rush as I have an existing kayak already.

Monday, October 04, 2010

Populating a Word Document from a Sharepoint List

I thought this would be simpler since Sharepoint and Word are so closely related. A mail merge based on list data perhaps? Maybe it’s possible with an office data connection file but I couldn’t figure it out.

Well, it was useful to me so here’s how I did it with Powershell and Word automation. The example here is a list of standards and the output will be a list of those standards formatted on one Word document. The soap call from powershell comes from somewhere on the net with an added soapaction header. The list has been created with folder items so it needs to list the items recursively – this wouldn’t apply to a normal list. You’ll figure it out as you start looking at the xml attributes. Best way to make progress with these sharepoint soap calls is to use Wireshark in combination with Stramit Caml Viewer.

Here we go…

function Execute-SOAPRequest 
(
[Xml] $SOAPRequest,
[String] $SOAPAction,
[String] $URL
)
{
write-host "Sending SOAP Request To Server: $URL"
$soapWebRequest = [System.Net.WebRequest]::Create($URL)
$soapWebRequest.Headers.Add("SOAPAction","`"" + $SOAPAction + "`"")

$soapWebRequest.ContentType = "text/xml;charset=`"utf-8`""
$soapWebRequest.Accept = "text/xml"
$soapWebRequest.Method = "POST"

write-host "Authenticating"
$soapWebRequest.Credentials = [System.Net.CredentialCache]::DefaultCredentials
if($soapWebRequest.Proxy -ne $null) {
$soapWebRequest.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
}

write-host "Initiating Send."
$requestStream = $soapWebRequest.GetRequestStream()
$SOAPRequest.Save($requestStream)
$requestStream.Close()

write-host "Send Complete, Waiting For Response."
$resp = $soapWebRequest.GetResponse()
$responseStream = $resp.GetResponseStream()
$soapReader = [System.IO.StreamReader]($responseStream)
$ReturnXml = [Xml] $soapReader.ReadToEnd()
$responseStream.Close()

write-host "Response Received."

return $ReturnXml
}

function Add-Standard
(
[String] $Standard,
[String] $Justification,
$Doc
)
{
$p = $Doc.Paragraphs.Add()
$p.Range.Text = $Standard
$p.Format.Style = "Heading 1"
$p.Range.InsertParagraphAfter()

$p = $Doc.Paragraphs.Add()
$p.Range.Text = $Justification
$p.Range.InsertParagraphAfter()
}

$d4 = [xml] @"
<?xml version="
1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="
http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<listName>{CF6E48BA-650A-489E-83AB-8EF1E545388A}</listName>
<queryOptions>
<QueryOptions>
<ViewAttributes Scope="Recursive"/>
<IncludeMandatoryColumns>False</IncludeMandatoryColumns>
</QueryOptions>
</queryOptions>
</GetListItems>
</soap:Body>
</soap:Envelope>
"@


# create a document from list data!
$w = new-object -com Word.Application
$w.Visible = $true
$d = $w.Documents.Add()

Execute-SOAPRequest -SOAPRequest $d4 -SOAPAction "
http://schemas.microsoft.com/sharepoint/soap/GetListItems" -URL "http://<some sharepoint site>/sites/CTO/_vti_bin/lists.asmx" |
foreach {$_.Envelope.Body.GetListItemsResponse.GetListItemsResult.listitems.data.row |
foreach {Add-Standard -Standard $_.ows_Standard -Justification $_.ows_Justification -d $d }
}

$d.SaveAs([ref]"c:\temp\standards.docx")
$d.Close()
$w.Quit()

Sunday, August 15, 2010

FST Auckland Conference Presentation

You can find the presentation I did for the Financial Services Technology conference in Auckland last week here.

Brief synopsis: systems/operational management provides a useful analogue to the problems faced by implementers of business intelligence environments: huge volumes of data streaming in for which you need to provide health indicators and predictions of the future.

In the case of Microsoft’s System Center Operations Manager tool this is done in a manner that is very different from conventional BI efforts that rely on staging large quantities of data, building relational and dimensional models and producing KPIs. The solutions developed for operations management can be usefully applied to BI efforts, particularly when not dealing with financial data.

Monday, August 09, 2010

CIO Conference–Enterprise 2.0 Presentation

I’ve put the presentation here: http://cid-0e5ff53cd7f11485.office.live.com/browse.aspx/Public/CIO%20Conference%20July%2010

Questions from the audience about my criticism of data focussed BI got me thinking about what might be a better model. I’ve changed the slide deck to cover more of a BI story for presentation at the FST conference in Auckland this Wednesday.

Seq.unfold

Don’t know why this had escaped me for so long!

 

let PascalsTriangle =
let nextLine aLine =
let partialLine =
aLine
|> Seq.pairwise
|> Seq.map (fun (x,y) -> x+y)
|> Seq.toList
List.append (1::partialLine) [1]
[1] |> Seq.unfold (fun s -> Some(s, nextLine s))

Compare to: Pascal’s Triangle in F#

Friday, July 30, 2010

Heat/Image Mapping with .Net/F#

As part of a demonstration to the Wellington .net user group this week I put together a demo showing a heat mapping of the performance of a transactional system as a function of time of day and arrival rate. My objective was to provide a simple eye balling test of whether performance was being impacted more by daytime customer loading or by competing overnight batch processing. I’ve tried a similar task before with Python and MatPlotLib but this time I wanted to see how easy it was to accomplish in .Net/F#.

The answer was ‘very easy’.

The interactive F# environment in VS2010 gives you JIT compiled code so it’s very fast to work with. The data structures/collections available within F# make importing and manipulating data simple – once it’s in memory you spend most of the time using filter, map and fold operations on elements – explicit recursion or iteration is rarely necessary.

I found I started with sequences then moved to arrays as data volumes increased and performance slowed. Array.Parallel.map/mapi seemed to make a significant difference whenever the operation being performed was of order a few milliseconds. It’s pointless parallising when the operation performed is short – the overhead of managing threads must just be too great.

Most of the effort was spent aggregating and binning the data, the actual image prep was trivial. The following assumes you have an array of data to display.

open System.Drawing
open System.Drawing.Imaging
open System.Windows.Forms
// adapted some code here from http://thecodedecanter.wordpress.com/2010/04/30/modelling-the-2d-heat-equation-in-f-using-100-lines-of-code/
let toBitmap (arr:Color[,]) =
let image = new Bitmap(arr.GetLength(0),arr.GetLength(1),Imaging.PixelFormat.Format24bppRgb)
for i=0 to image.Width-1
do
for
j=0 to image.Height-1
do
image.SetPixel(i, j, (arr.[i,j]))
done
done
image

let maxInArray2D (ar:'a[,]) =
seq{ for r in 0..Array2D.length1 ar-1
do
yield
Seq.max (ar.[r..r,*] |> Seq.cast<'a>)
} |> Seq.max

let intensityMap intensity = Color.FromArgb((int (intensity * 255.0)),0,0)

let bitmap imageArray =
let max = imageArray |> maxInArray2D
imageArray
|> Array2D.map (fun f -> f/max)
|> Array2D.map (fun f -> intensityMap f)
|> toBitmap

let ShowForm (f : Form) =
#if INTERACTIVE
f.Show()
#endif
#if
COMPILED
Application.Run(f)
#endif

let
BitmapForm bitmap =
let picBox = new PictureBox(BorderStyle = BorderStyle.Fixed3D, Image = bitmap, Size = bitmap.Size,
Dock = DockStyle.Fill, SizeMode = PictureBoxSizeMode.StretchImage)
let form = new Form(Text = "F# Connection Performance versus Connection Rate and Time", Size = bitmap.Size, AutoSize = true)
form.Controls.Add(picBox)
form

bitmap surfaceArray |> BitmapForm |> ShowForm


If you don’t have many points that’s going to generate a small image which you can expand by dragging the corner and Windows will magically interpolate for you. I’m sure there’s a way to explicitly do this with the BitmapForm API as well – just didn’t have time to figure that out.



If you want to interpolate yourself, you could try something simple like a bilinear approach:



let bilinearInterpolation f00 f01 f10 f11 x y =
let boundingBox = Array2D.zeroCreate<float> 2 2

boundingBox.[0,0] <- f00
boundingBox.[0,1] <- f01
boundingBox.[1,0] <- f10
boundingBox.[1,1] <- f11
let A = RowVector.ofList [1.-x; x]
let B = Matrix.ofArray2D boundingBox
let C = Vector.ofList [1.-y; y]
A * B * C


Or why not just double the resolution?



// take an array m x n and return (2m-1) x (2n-1)
let interpolate (A:float[,]) =
    let B = Array2D.zeroCreate<float> (2*(A.GetLength 0) - 1) (2*(A.GetLength 1) - 1)
    for row in 0..((A.GetLength 0) - 1) do
        for col in 0..((A.GetLength 1) - 1) do
            B.[2*row, 2*col] <- A.[row,col]
        done
    done
    //
    for row in 0..((B.GetLength 0) - 1) do
        if row % 2 = 0 then
            for col in 0..((B.GetLength 1) - 1) do
                if col % 2 = 1 then
                    B.[row, col] <- (B.[row,col-1] + B.[row,col+1]) / 2.
            done
        else
            for col in 0..((B.GetLength 1) - 1) do
                if col % 2 = 0 then
                    B.[row, col] <- (B.[row-1,col] + B.[row+1,col]) / 2.
                else
                    B.[row, col] <- (B.[row-1,col-1] + B.[row+1,col-1] + B.[row-1,col+1] + B.[row+1,col+1]) / 4.
            done
    done
    B

// now I can do this...
bitmap (surfaceArray |> interpolate |> interpolate |> interpolate |> interpolate)|> BitmapForm |> ShowForm


And generate results like this (where connection rate increases down, time goes across, and redness indicates duration of calls):



performancemap