Monday, February 20, 2012

Exporting Graphs from neo4j

I've recently had a brief introduction to the Neo4j database - by way of the YOW 2011 conference in Brisbane.

It looks really interesting - so I set about performing a few experiments. One of which is taking a graph and exporting it for use via other tools.

For example, here's a really simple graph - shown via neoclipse:
Sample Graph
And the code to produce it is like this:

Node nodeA = graphDb.createNode();
Node nodeB = graphDb.createNode();
Node nodeC = graphDb.createNode();
Node nodeD = graphDb.createNode();
Node nodeE = graphDb.createNode();


nodeA.setProperty("name", "A");
nodeB.setProperty("name", "B");
nodeC.setProperty("name", "C");
nodeD.setProperty("name", "D");
nodeE.setProperty("name", "E");


Relationship rel = null;
rel = nodeB.createRelationshipTo(nodeA, RelationshipTypes.DEPENDS);
rel = nodeC.createRelationshipTo(nodeA, RelationshipTypes.DEPENDS);
rel = nodeD.createRelationshipTo(nodeC, RelationshipTypes.DEPENDS);
rel = nodeE.createRelationshipTo(nodeC, RelationshipTypes.DEPENDS);

Nothing exciting to see there.

So, using the Cypher language for querying, I thought I'd investigate how to dump the graph structure so I could export it.

Assuming that A is the starting point of our Graph - just getting the nodes which are related to A can be found via this query:

start n=node:concepts(name="A") 
match (n)<-[r]-(x) return x.name, r

Results are:
+-------------------------+
| x.name | r              |
+-------------------------+
| "C"    | :DEPENDS[1] {} |
| "B"    | :DEPENDS[0] {} |
+-------------------------+
2 rows, 978 ms

But, to retrieve the whole graph, I require all nodes which have a relationship with A. So another attempt is this - allowing for multiple depth relationships:

start n=node:concepts(name="A") 
match (n)<-[r:DEPENDS*1..3]-(x) return x.name, r

Results are:
+-------------------------------------------------+
| x.name | r                                      |
+-------------------------------------------------+
| "C"    | List(Relationship[1])                  |
| "E"    | List(Relationship[1], Relationship[3]) |
| "D"    | List(Relationship[1], Relationship[2]) |
| "B"    | List(Relationship[0])                  |
+-------------------------------------------------+
4 rows, 100 ms

However, this doesn't help to recreate the graph. To do this, I need each source and destination node - and the relationship. The next attempt makes use of the fact that you can specify a minimum cardinality of zero of the relationship predicate - which allows you to include the start node as well. Using this allows us to construct a query like this:

start n=node:concepts(name="A") 
match p1=(n)<-[rel:DEPENDS*0..2]-(x)<-[r:DEPENDS]-(y) 
return n, x, r, y 

Which returns results like this:
+-------------------------------------------------------------------------------+
| n                  | x                  | r              | y                  |
+-------------------------------------------------------------------------------+
| Node[1]{name->"A"} | Node[1]{name->"A"} | :DEPENDS[1] {} | Node[3]{name->"C"} |
| Node[1]{name->"A"} | Node[1]{name->"A"} | :DEPENDS[0] {} | Node[2]{name->"B"} |
| Node[1]{name->"A"} | Node[3]{name->"C"} | :DEPENDS[3] {} | Node[5]{name->"E"} |
| Node[1]{name->"A"} | Node[3]{name->"C"} | :DEPENDS[2] {} | Node[4]{name->"D"} |
+-------------------------------------------------------------------------------+
4 rows, 31 ms

From here, it's a small matter of programming to iterate through these results, and generate an XML representation (for example, GraphML style) - like this:


<graph start="1">
  <node id="1">
    <data key="d0">A</data>
  </node>
  <node id="3">
    <data key="d0">C</data>
  </node>
  <edge id="e1" source="3" target="1">
    <data key="d1">DEPENDS</data>
  </edge>
  <node id="2">
    <data key="d0">B</data>
  </node>
  <edge id="e0" source="2" target="1">
    <data key="d1">DEPENDS</data>
  </edge>
  <node id="5">
    <data key="d0">E</data>
  </node>
  <edge id="e3" source="5" target="3">
    <data key="d1">DEPENDS</data>
  </edge>
  <node id="4">
    <data key="d0">D</data>
  </node>
  <edge id="e2" source="4" target="3">
    <data key="d1">DEPENDS</data>
  </edge>
</graph>


The first column of the result - N - is simple used to infer the start node. In this case, it's "A" - as specified by the query.

Saturday, December 24, 2011

TweetBot UI

After the recent changes to the official Twitter iPhone app, I've done as others have - and looked at options.

At the moment, I'm trying TweetBot - self described as a Twitter app with personality.

And I'm really liking it. The transitions, animations and sounds make for an enjoyable experience.

But, there's a few little things which I think would improve it even further - one of which has been annoying me slightly (disproportionately to it's actual impact) - and that's the shape of the custom back button.

Let me illustrate ... here's a comparison shot between TweetBot - and the standard iOS back button:


I've highlighted the "problem" area - which shows:

  • the standard button has a much steeper angle, and finishes with a slight curve to the line
  • the TweetBot button is essentially a straight line (of a shallower angle) with a small curve at the end.
Like I said - not  a major issue. But every time I see it, I think how it would be nice to have it as the standard shape.

Thursday, September 08, 2011

Commuting with Helvetica

Wow, Queensland Rail have recently upgraded their corporate branding - but it's only now that they seem to be rolling out the new station identities:

New Station Signage

















And, they seem to have chosen Helvetica for the station signage as well - one of my favourite fonts. Who would have thought we would finally get some good design in our every day commuter life?

Strangely enough, some stations which have recently received new signs have had a similar version - but in italics! Quite bizarre. I'll update the post when I can take a picture.



Monday, February 04, 2008

Google Code - Part 1

As I've mentioned earlier, I'm using Google Code to host the apselex project - an Adobe Photoshop Elements Explorer.

It is very easy to get started, and quite easy to use.

But, one thing was eluding me - how to use images in the wiki. I know - the help page has some examples, but as with all these things, the devil is in the details.
  • the image needs to be an external link
  • as such it needs to be hosted, and available
  • a "makes sense" approach is to store images in the wiki directory itself
  • and then simply point to the image with a link like this:

    [http://apselex.googlecode.com/svn/wiki/ScreenshotExplorer.png]
Simple!

Naturally, using Eclipse, it was pretty straight forward to put some images in this directory. The approach I took was:
  • create a separate Eclipse project - mine was called ApselWiki
  • share this as a Team project (using subversion), and use the wiki as the URL

    https://apselex.googlecode.com/svn/wiki

    Note, that the wiki directory is outside the /trunk directory. That is, it's in the root of your project.
  • You can then simple paste new images into the Eclipse project - and also edit your wiki pages if you really like.
  • Then simply perform a "Team -> Synchronize"
Easy!

Tuesday, January 29, 2008

Photoshop Elements - Explorer Part 2

Due to overwhelming demand (well, at least 1 person :-)), I've put up my initial code for exploring the Photoshop Elements database. For a small bit of background info, see my previous post.

I thought I'd give google code a try for hosting - as such, the project is located here.

Drop me a line in the comments if you're interested in participating.

Tuesday, January 08, 2008

Real World Usability

This is a post on usability - in the "real world" - which may become something of a series.

The subject today is a ticket vending machine - not super exciting, but it's a a new model being rolled out in south east Queensland, so could be considered topical.

First, a picture:



Mmmm, what ever could be a problem with this shiny new design.

Well. A few things unfortunately. Let's see.

  1. the coin slot. There's not enough room for a right handed person to insert coins, without constantly scraping them up against the side of the machine. Why?



  2. the "ticket/change/receipt" hopper is too low. I understand that the machine needs to cater for people of all heights, including wheelchair access - but this is just too low. It requires constant stooping to fetch change and tickets.
  3. the touch screen. I'm not sure where to start with this one, since there are so many aspects ...
    1. the responsiveness (or lack of). there's a lag in the response - so that after you've pressed a soft button, you're not really sure if it's really pressed or not

    2. the angle - unless your eyes happen to be perpendicular to the screen, your screen presses will be off the mark - it seems that there is enough of a gap between the surface of the touch screen, and the actual LCD screen that this is a real problem.
Then there's the interaction flow. The series of screens you have to wade through to get a ticket is just plain cumbersome. Some issues are:
  1. To select a destination station, you need to go through a multi level alphabetical menu, or select from a "map". The map isn't too bad, but in combination with the "angle" problem, it's a little hard to use as well.

  2. There are no direct keys for common stations

  3. why not allow a one touch "daily to Central" from suburban machines?

I realise that these concerns will not be as prevalent once the smartcard side of things is operational (since most commuters will just use them to top up the value on their cards) - but they will still be relevant for paper tickets.

A little bit of research shows that these machines aren't a one off design for Translink - they're a customized version of an existing design which goes by the name of "Universal Vendor 1000". I wonder how much usability testing they did?

Friday, January 04, 2008

Photoshop Elements - Migrating to Version 6

Well, I thought my migration to Adobe Photoshop Elements Version 6 was complete - and I was very happy with the way things had gone.

Until, I needed to print one of my pre-migration dated images.

I was greeted the following, rather unfriendly dialog, and could not print.

Wtf? I was concerned to say the least.

I re-traced some of my steps ...
  • newly edited photos would print ok
  • new (Version 6) photos were ok
  • old (pre-version 6) photos were ok
  • old, edited photos were NOT ok
I smelled a rat with the migration process for edited images. The edited images had seemed to be imported as version sets correctly. I did a bit more checking. The following grab shows a typical (albeit) sample image:



Note that the original image in the Version set is selected, and the Size attributes are displayed correctly in the Properties window.

Now, have a look at this next one, with the newer image from the Version set selected:



I've highlighted the problem area - the image width and height are missing. This was pointing to all not being well with the edited image.

I waded through the information on the Adobe support site here, I couldn't find any exact match. I even resorted to the forums, which are extremely painful to use - and still no match.

So, I thought - there's nothing for it but to submit a bug report. This itself was fairly painless, but disappointing:
  1. no reference number, or tracking information was returned.
  2. no acknowledgment that a bug had even been reported (via email, for example).
However, I was determined not to be beaten by this. I went back to the support documents, and found that a number of suggested fixes finished with the recommendation to use the "Update Thumbnail" command. What the? I didn't think that this would be appropriate for me - since my thumbnails looked fine, thank you very much.

Well, I thought - what could possibly go wrong ?

I'm pleased to report that - it actually fixed the problem!! Woo hoo. I was a little surprised, but relieved to say the least. A few years of editing had not been lost.

I was wondering why I needed to do this though - I used the supported Catalog conversion process. If PSE needed my thumbnails to be updated, I would have preferred them to be done as part of the migration process.

However, this exercise did open my eyes to the strange support mechanisms provided by Adobe. When the product itself sports a gleaming new interface, it's a little sad that the support facilities are somewhat lacking - and in case of those forums, downright primitive.

If any Adobe guys are around - I guess you can close my bug report too :-)

Cheat Sheet Extensibility - Part 2

Oops.

I forgot to mention one of the little tricks required to make the cheat sheet actually usable - you need to be able to signal it's completion :-)

There are a few things required to make this happen:
  1. the task requires a UI control which allows the user to signal that the task is complete. I used a form hyperlink control, similar to the following:
    ImageHyperlink link = toolkit.createImageHyperlink(
    form.getBody(),
    SWT.WRAP);
    Image img = AbstractUIPlugin.imageDescriptorFromPlugin(
    Activator.PLUGIN_ID, "/icons/complete_task.gif").createImage();
    link.setImage(img);
    link.addHyperlinkListener(this);
  2. a reference to the task being edited must be obtained. Fortunately, this is made available when the setInput method is called. In this method, use some code like this:

    public void setInput(IEditableTask _task, IMemento memento) {
    task = _task;
    }
  3. attach a listener to the control


  4. when the link is activated, your listener will be fired. When this happens, the task should be set to complete. This is then just a simple method call using the task instance which has already been saved:

    task.complete();