LifeCampTO social graph

After LifeCampTO, I asked people to give me the list of people they wanted to talk to (or, well, those people’s primary keys ;) ). I’m still figuring out how to do a great little mail merge that reminds people of the keywords, but along the way, I thought I might I’d learn more about network visualization.

Here’s the resulting graph: (click on it for a larger version)

LifeCampTO social graph

So, what does this graph say?

You can see that most people have quite a lot of follow-up conversations ahead. It wasn’t the kind of event where most people walked away with only two or three conversations, although they might have smaller follow-up conversations with different groups of people. It might be interesting to do some cluster analysis around topics, and maybe someday I’ll figure out how to encode the data in order to make that analysis easier. ;) Based on this, our on-the-fly decision to have three big conversations turned out to have made sense, although it would also be interesting to try having small conversations about both popular and niche topics, and then having people come together at the end (or on a wiki).

Getting to this graph (and to the individualized graphs I’ve just figured out how to produce – it highlights each person’s connections) involved a lot of bubblegum and string.

  1. I typed in the data people had written down, using OpenOffice.org to form the upper triangle of an adjacency matrix. Two people’s sheets were missing, and one person didn’t have any connections incoming or outgoing. =( Thank you, programming competitions, for all those lovely data structures.
  2. I copied the adjacency matrix and pasted it onto itself using OOo’s Paste Special – Transpose, Skip Empty Cells. This gave me a full adjacency matrix.
  3. I used a really long and hairy OOo formula to concatenate the cells into Emacs Lisp code as an associative list, with extra information and an edge list.
  4. I copied that into Emacs and processed the associative list’s edges. I needed to do that anyway in order to be able to e-mail people personalized e-mail with all of their introductions, instead of sending one e-mail per edge. Along the way, I got the idea of visualizing the network diagram, so I spun off some code to output a full edge list in DOT format for visualization with circo.
  5. I used a command like
    circo -Gsplines=true < lifecampto.dot -Tpng > lifecampto.png

    to generate the graph shown.

  6. Then I thought it would be cool to personalize the graphs, too, so I wrote some more Emacs Lisp to generate personalized DOT files that highlighted the recipient in green and the recipient’s requested links/nodes in green, too. I used a Bash for loop to turn all those personalized DOT files into PNG files.

Example of a personalized image:

Tomorrow, I’ll work on the mail merge. =)

A little computer science is a dangerous, dangerous thing.

OpenOffice.org: Replacing dingbats

I _really_ should have blogged this when I first wrote it. That would’ve saved me time writing it again!

Sub ReplaceDingbats(optional doc)
	oDocument = IIf(IsMissing(doc), ThisComponent, doc)
	oSearchDesc = oDocument.createSearchDescriptor	
	for i = 1 to 9 
		oSearchDesc.searchString = "(;; )?\(" + i + "\)"
		oSearchDesc.searchRegularExpression = true
		mFound = oDocument.findFirst(oSearchDesc)
		do while not isNull(mFound)
			mFound.string = chr(&HF08B + i)
			mFound.CharFontName = "Wingdings"
			mFound = oDocument.findNext(mFound.End, oSearchDesc)
		loop
	next i
End Sub

It’s a macro for OpenOffice.org – replaces the widgets I use in formatting the book chapter…

I so rock =)

I have about 41 pages for my current chapter on taking notes in Emacs, and I still have to write the introduction and wrap-up sections. This means that I’ll need to do some more editing. It’s clearly time to apply another piece of advice from the wonderful book How to Write Fast (While Writing Well), by David Fryxell: don’t over-write, because the time you waste writing more than necessary and then editing down to the required length could be spent writing about something else!

I also rock because I’m getting the hang of writing macros for OpenOffice.org. Basic is not my favorite language and OpenOffice.org macro programming is sufficiently obscure that it’s hard to find examples of what I want to do. OOoMacros.org helped me learn enough to write a few more functions to make my writing life better. I wrote two new functions today: one to mark up wingdings in my code, and another to mark up the source code examples. Both save me lots of tedious work. The wingding function replaced all instances of (1), ;; (1), (2), ;; (2), until (9) and ;; (9) with the corresponding wingding. The example function marked up everything enclosed in <example>..</example> tags, formatting the first and last lines in a different style and using a single-line code style for short examples. Between that and the two functions I’d previously written to format about 80% of my command and keyboard shortcuts, editing is just so much better.

It seems that most people don’t tinker with their tools. I like doing so. I like getting to know what I can do with a tool and how far I can push it. This can be frustrating sometimes (I spent all afternoon trying to get Emacs to play nicely with other weblogs!), but most of the time, it’s both fun and useful. Not only am I saving myself time, I’m also exercising my brain and opening opportunities for other hacks down the line. This is good.

Oh! And W- is giving Ledger a try. The tool he’d been using to keep track of finances dropped some more of his data recently. Because it’s all magic inside, he couldn’t figure out what happened. I’d been going on about how awesome Ledger is, this command-line double-entry accounting tool that provides no bells or whistles but with which I can do all sorts of crazy things. He described how he wanted to budget, and I showed him how to do it. No screencast, but I do plan to review the audio and create some supporting materials for my upcoming article on Ledger and Gnuplot.

Life is good. =)

Yak shaving with OpenOffice.org

Fiddly little editing tasks are driving me mad. Formatting all the keyboard shortcuts as EmphasisBold and the command names as Literal… I figured that if I could write a program that got 80% of the cases right, that would not only save me time but also stress. So I spent two hours shaving the yak today, learning just enough OpenOffice.org Basic to put together two procedures that attempt to handle most of the cases. FormatCommands looks for anything within parentheses inside a body paragraph, and FormatKeyboardShortcut looks for things like C-c r t (remember, tasks). I don’t expect this to be usable to anyone, but if it can be a useful jumping-off-point for other people, that would be awesome.

Sub FormatCommands
   oDoc = ThisComponent
   Descriptor = oDoc.createSearchDescriptor()
   Descriptor.SearchRegularExpression = true
   Descriptor.SearchString = "\([^)]+\)"
   Found = oDoc.FindFirst(Descriptor)
   do while not isNull(Found)
       oNew = oDoc.Text.createTextCursorByRange(Found.Start)
       if oNew.CharStyleName = "" and (oNew.ParaStyleName = "Body" or oNew.ParaStyleName = "BodyFirst") then
             oNew.goRight(1, False)
             oNew.goRight(Len(Found.String) - 2, True)
             oNew.CharStyleName = "Literal"
       end if 
     Found = oDoc.findNext(Found.End, Descriptor)
   Loop   
End Sub
Sub FormatKeyboardShortcuts
   oDoc = ThisComponent
   Descriptor = oDoc.createSearchDescriptor()
   Descriptor.SearchRegularExpression = true
   Descriptor.SearchCaseSensitive = true
   Descriptor.SearchString = "([CMS]-)+([a-zA-Z0-9]+)*( [a-zA-Z0-9])* "
   Found = oDoc.FindFirst(Descriptor)
   do while not isNull(Found)
           if Found.CharStyleName = "" and (Found.ParaStyleName = "Body" or Found.ParaStyleName = "BodyFirst") then
                 Found.CharStyleName = "EmphasisBold"
           end if 
     Found = oDoc.findNext(Found.End, Descriptor)
   Loop   
End Sub