Showing posts with label Flex. Show all posts
Showing posts with label Flex. Show all posts

08 March 2011

To Flash or not to Flash

I love building stuff with Flash technologies. I think ActionScript 3.0 is an excellent language and Flex 4 is a very good framework. I'm not particularly enamored of the alternatives. I find JavaScript to be a mediocre language (albeit with some excellent libraries). I don't like wrangling CSS more than I have to (although Less makes it much nicer). I find HTML 5 to be a pretty immature technology so far. SilverLight's days are probably numbered. (I haven't yet delved into mobile operating systems, like Android and iOS, so I can't speak for those. And those aren't complete alternatives, anyway.)


Because I love Flash, I have a tendency to want to build everything in it. But over the years I've learned that this tendency must be curbed whenever possible. There are definite downsides to Flash, and especially to doing entire websites in Flash. (The now-defunct March of Man website and some abandoned versions of the Dinosauricon are testaments to this.)


For PhyloPic, it was pretty clear to me that there would be no significant advantage to building it in Flash. Load times would be increased without any functionality enhancement. I wouldn't be able to use it on my iPhone. And all the functionality I needed was easily available in plain old HTML/JavaScript/CSS.


With one exception.


The Submission Tool is built as a Flex app. There is one primary reason for this: image processing. Processing the silhouettes on the server side was an option, but one that could have potentially bogged the server down. (It's already starting to buckle a bit as is, pending some optimizations.) But, by using Flash's BitmapData class, I can do that bit of work on the client side before the silhouettes are shipped off to the database.


Of course there are some other benefits as well. In descending order of importance:

  • Flash allows for a more unified experience for the submitter. No page reloads and no cross-browser differences.
  • SPAM bots are much more capable of cracking HTML forms than cracking custom AMF web services. SWF files are generally opaque to them.
  • It was easier for me to build and test.
Had it just been those three reasons, there might still have been a good argument to do it as HTML/AJAX. The image processing requirement is what really tipped the scales. One hundred submitters contrasting, cropping, and rescaling bitmaps is much nicer if they're doing it on their own machines than if they're all doing it on the server. (Okay, I've barely had even two simultaneous submitters so far, but I can dream....)

There may be other Flash tools in PhyloPic's future. For example, I think it is the best technology for the Cladogram Generator. But for the rest of the site, plain old HTML/JavaScript/CSS is certainly sufficient—better, even.

UPDATE (2012 Jan 26): The Submission Page still uses Flash but is not a Flex app.

12 October 2010

What I Do For A Living: TRONiverse

We recently launched a Flash app for the upcoming film TRON: Legacy:


It pulls posts from Twitter, Facebook, and Flickr and displays them orbiting a 3D globe. You can click on the globe to find posts near that area. Post about TRON and your post might appear, too!

Also, we added a neat little Easter egg: click on the globe and then hold down the "M", "C", and "P" keys. (People who've seen the original film might have an idea what to expect....)

26 July 2010

3D Visualization of the Fossil Distribution of the Human-Chimpanzee Total Clade

What it says.
Click on the image to open the visualization.
I've been compiling data on "pan-mangani" fossils. This is my first March of Man toolshop post in a while: a 3D visualization of that data, where the horizontal axis is longitude, the vertical axis is latitude, and depth (the z-axis) is age. The "blobs" each represent a fossilized individual, and you can mouse over them to see what their taxon is.

Some data is missing, notably a lot of entries for our own species. Other data needs to be refined—some of the better-known species (ahem, Neandertals) are big clouds that need to be tied down to specific sites. Also, I obviously need to do more work on that present-day distribution map. But it's a decent start.


Fun things to do:

  • See if you can find the oldest individual (the lone specimen of Sahelanthropus tchadensis).
  • Try to find its Chadian compatriots.
  • Find the earliest non-African individuals (hint: East Europe and the Malayan Archipelago).
  • Wonder what the heck that thing in India is.
  • Look for the single cluster of extinct chimpanzees (Pan sp.).
  • Find the three subspecies of Homo sapiens other than our own. (Note: these may not be distinct from each other—I just prefer to err on the side of splitting for projects like these. Easier to revise later.)
  • Marvel at how easy it is to become sympathetic to multiregionalism when you just view the distribution data without any morphological context and ignore the fact that not all regions are good for preservation.
  • Wonder how people can possibly believe in baraminology in the face of such ample evidence. (Adding morphological data to this would help a lot—there really aren't any good "cutoff" points for our lineage.)
UPDATE:

Better version here.

27 May 2010

Upcoming Names on Nodes Presentation

I'll also be presenting Names on Nodes at iEvoBio, at the Software Bazaar on June 29. Here's the abstract:

Names on Nodes: Automating the Application of Taxonomic Names within a Phylogenetic Context

Names on Nodes1 is an open-source2 Flex application which utilizes a mathematical approach to automate the application of phylogenetically-defined names to phylogenetic hypotheses. Phylogenetic hypotheses are modeled as directed, acyclic graphs, and may be read from bioinformatics or graph files (Nexus, NexML, Newick, and GraphML) or created de novo. Hypotheses may also be merged from multiple sources. Names on Nodes stores hypotheses as MathML, an XML-based language for representing mathematical content and presentation. Phylogenetic definitions may be constructed using a visual editor and exported in MathML. Thus, it is possible to create a dictionary of defined names and automatically apply them to phylogenetic hypotheses. In the current version of the application, such dictionaries exist only as MathML files, but in future versions definitions may also be loaded from databases (e.g., RegNum).

Additional functionality in Names on Nodes includes the ability to coarsen a phylogenetic graph (thereby simplifying it while still reflecting the overall structure) or to export it as an image file (raster or vector, potentially with semantic annotations).

  1. Source code available at: http://bitbucket.org/keesey/namesonnodes-sa/
  2. MIT license
I have my work cut out for me....

08 April 2010

Viewing Phylogenies at Different Graph Resolution

Although I've been primarily reining in features on the next version of Names on Nodes, there was a new feature I couldn't resist adding. I think it's coming along pretty well.

A common problem with working with phylogenies is that many of them are gigantic, far too big to view all at once. As an example, consider Figure 1 from Beck et al. (2006). It models a hypothesis about placental mammal phylogeny, at an arbitrary resolution ("family-level"). Here's how the current version of Names on Nodes renders it:


When you look at it "zoomed out", it's almost impossible to know what's going on. When you look at it full size, you can see various local areas, but you lose a sense of what's going on with the larger image. Note that I've highlighted our own species' twig on the tree (Hominidae, the great ape clade) in yellow.

Earlier I used the term "resolution" to refer to the size of the graph's nodes. We can refer to a graph with very small nodes (e.g., each node representing an individual organism) as being "fine" and a graph with very large nodes (e.g., "class-level") as being "coarse". Thinking about the problem from this angle, I had the idea to create a control for coarsening or refining the viewed graph.

I implemented a simple graph-coarsening algorithm*, and then created an algorithm for picking the best name for the new, coarser graph's nodes. And here is the phylogeny at near-maximum coarseness:


This is placental phylogeny boiled down to its basics: rodents, laurasiatheres, and a bunch of other junk (including us). The node labelled "Placentalia*" contains the placental ancestor but not all descendants—it lacks an unnamed clade included most non-afrothere placentals. The unnamed greenish node includes all members of that unnamed clade except for rodents and laurasiatheres. (This happens to include Hominidae, which is why it has that greenish color.)

Let's refine it one step:


We're starting to get a better idea of the hypothesis. Finer:


Now we can see the basal split between afrotheres and other placentals, as well as developing complexity in Rodentia and Laurasiatheria. Finer:

Getting a little bit on the big side, now, but we can see more details. There are a lot of unnamed clades within Hystricoidea and Chiroptera—we can see that those clades are diverse, although we can't see details. Finer:
This has about 2/5 as many nodes as the base graph. It's a bit large, but still much easier to view than the base graph. Many important details are visible (e.g., the platyrrhine-catarrhine split), while others are just suggested (e.g., lots of diversity in Caviomorpha).

Obviously this works best if lots of clades have been named. I think it'll be a useful for boiling a phylogeny down to an appropriate level: coarser for quick overviews, finer for in-depth discussion.



* Basic summary of the coarsening algorithm:
  1. Look through all nodes that have children, and find the ones whose children are all terminal (sinks).
  2. Merge each of those nodes with their children to create a "supernode".
  3. Merge all overlapping supernodes. (This is important for graphs where nodes may have multiple ancestors, although it doesn't come into play in this example.)
  4. Remove the supernodes from the graph and repeat from step 1. Keep going until no nodes are left.
  5. Add the supernodes to a new graph. A supernode is ancestral to another supernode if any of its subnodes are ancestral to any of the other supernode's subnodes.

20 November 2009

What I Do For a Living, Part 312: Dr. Facilier's Parlour

I recently completed a new application. This one is a collection of three games associated with Disney's upcoming animated film, The Princess and the Frog. This one requires a Facebook account: Dr. Facilier's Parlour. (Dr. Facilier is the villain of the movie.)

This is my first completed project using certain technologies:
Also see the Shadow Shakedown game therein for an example of how DisplacementMapFilter can be useful. (I also got to do a tiny bit of character animation there.)

I have to say I was very pleased with all of these new technologies. In particular, the Spark component set is a huge improvement over the previous Halo components. Skinning components is so easy now it's hard to imagine that it was ever difficult. Adobe has acted on the "Favor composition to inheritance" maxim, and it has paid off. Also, props to Code Igniter, with its flexible tools and strong emphasis on the MVC pattern, for making PHP development (something I had all but sworn off) actually kind of fun.

Enjoy!

24 August 2009

Online NEXUS File Viewer

It's been a month since my last post, but I have a very good reason for the hiatus. Namely, I was busy getting married to this woman (at the Los Angeles County Museum of Natural History) and going on our honeymoon (in Sydney, Australia).

Now that I'm back in California, time to get back to work on Names on Nodes! I've just put together a small demo of two key parts of its functionality: the reading of NEXUS files and the displaying of phylogenetic networks. Click here to see the NEXUS Viewer demo. This application opens NEXUS files and displays the trees in them as a combined phylogenetic network.

Things you need to know:
  1. You must have a NEXUS file stored locally on your computer to use this.
  2. That file should have a TREES section. (If not, the viewer should just display a list of operational taxonomic units.)
  3. This could get messy for NEXUS files with lots of trees. (Although it's kind of neat-looking.)
  4. You can move the nodes around by clicking on them, or click anywhere else to move the entire diagram.
  5. I would dearly love to know if, for some reason, it does not work for a given file.
Enjoy!

23 July 2009

Two "Names on Nodes"-Related Launches

I'm still a clear way away from launching the beta application, but I've just made a couple of launches related to my long-time work-in-progress, Names on Nodes.

First up, and probably of more interest to most people, I've begun the documentation for the MathML definitions used by Names on Nodes. The document includes general reviews of relevant mathematical and biological concepts, a quick review of MathML and the technologies it's based on, some comments on correlating mathematical and biological concepts, and definitions for all entities (including operations) used by Names on Nodes. Note that this covers a lot of the same ground as in my 2007 paper, with a few minor changes in the symbols and terminology (e.g., I now call the ancestor of a clade a "cladogen" rather than a "cladogenetic set").

Secondly, I've made the project open-source, by moving it to Google Code. If you are a developer interested in checking this out, go here. It's incomplete, so I don't know if anyone will have any real interest in looking at it yet. (Honestly, I mostly posted so that, on the off chance that I unexpectedly kick the bucket, my magnum opus won't be lost forever.)

This information is also on the new Names on Nodes home page.

30 June 2009

New Useless Utility: Text Tree Maker

I finally got around to launching something at namesonnodes.org. No, it's not Names on Nodes itself, unfortunately. The project is taking a huge amount of time. But I thought I'd post something, so here's a little Flex application I made (using the new Flash Builder 4 Beta!) using a smidgen of the technology behind Names on Nodes.

Have you ever been discussing phylogeny online and wished there was an easy way to make a readable cladogram? (95% of readers leave.) Those of you who are left, check this out: Text Tree Maker. Just type in a Newick tree string, and voilá! Okay, so typing in a Newick tree string is not that easy in the first place, but it is easier.

Well, I'll be using it, anyway. Check this one out!


Ardipithecus
|--ALA-VP 2/10
`--+--ARA-VP 6/1
|--KNM-T1 13150
`--Praeanthropus
|--KNM-KP 29281
`--+--AL 288-1
|--KNM-WT 40000
|--KT 12/H1
|--LH 4
`--+--BOU-VP 12/130
|--Australopithecus
| |--Taung 1
| |--Australopithecus (Paranthropus)
| | |--SK 6
| | `--TM1517
| `--Australopithecus (Zinjanthropus)
| |--KNM-WT 17000
| |--OH 5
| `--Omo 18
`--Homo
|--KNM-ER 1470
|--KNM-ER 1813
|--OH 7
|--OH 9
`--Homo (Homo)
|--D 2600
|--KNM-ER 992
|--LB 1
`--+--Ceprano 1
|--Trinil 2
`--Homo (sapiens)
|--ATD 6-5
`--+--Mauer 1
`--+--Neandertal 1
`--+--Florisbad 1
|--Kabwe 1
`--Uppsala domkyrka: Carolus Linnaeus


NOTE: Right-click on the application and select "View Source" if you want to see some of the code behind it.

16 December 2008

My Yuletide Gift: Open Source ActionScript 3.0 Libraries!

I finally got around to setting up a Google Code site:

A Three-Pound Monkey Brain: ActionScript 3.0 Libraries

As you can see, there is still much to be done. But it's a start, and it's available to anyone.

Merry Solsticetime, everyone!

20 November 2008

Names on Nodes: Viewing Phylogenies

One of the primary uses for Names on Nodes will be as a viewer for phylogenetic hypotheses. The first incarnation will be able to digest hypotheses from NEXUS files; later versions will allow other file formats and ad hoc creation. I've been working on this aspect of the application lately and thought I'd post a few screen shots. (Warning: This is not the final look. I am definitely going to use a more legible font!)

Here's a very simple tree from a study on carnivoran phylogeny using supertrees (Bininda-Emonds et al. 1999):


(Note: the feliform side is a little outdated by now.)

This is a directed acyclic graph (and specifically a tree) rendered using the Flare ActionScript library, an extremely powerful (if sometimes frustrating) data visualization tool. It's based on the only tree in that particular NEXUS file. But what if a NEXUS file has more than one tree? This is where it gets kind of neat (I think)—Names on Nodes can show multiple hypotheses at once!

Here's a combination of two hypotheses from Novacek's (1989) study of mammalian phylogeny:


(Note: Much of this was changed by the subsequent molecular revolution in eutherian phylogeny.)

The NEXUS file has one tree based on extant organisms and another with some extinct taxonomic units. This network represents the phylogeny if both trees were true. Obviously, it shouldn't be taken too literally—there's no way carnivorans are descended from a hybridization of two disparate lineages, for example. But it shows a sort of consensus, and can be used for the application of phylogenetic definitions.

For the more botanically-inclined, here's a similar network for Rodman et al.'s (1984) analysis of Centrospermae:


(I have no idea how outdated this one is.)

Another thing that can be done in Names on Nodes is linking phylogenies together. For the aforementioned study by Bininda-Emonds et al. there is another NEXUS file focusing on Canidae. A user could open both files, drag the root node of the Canidae phylogeny to the terminal Canidae node in the Carnivora phylogeny, and equate the units with each other. This would produce something like this (cropped):


The root node in this phylogeny, then, could be equated with the Carnivora node in Novacek's phylogeny, and so on. In this way, gigantic networks can be compiled, representing the complete Tree of Life. Outdated hypotheses can be filtered to taste.

Next step: automated taxonomy.

Next next step: relating anything and everything to the Tree of Life.

17 August 2008

Sets for ActionScript

It's been a busy couple of months!

One of the things keeping me busy is, of course, Names on Nodes, the web application I am developing that will automate phylogenetic nomenclature. As part of that project, I have developed a mathematics package that I would eventually like to release as its own package. One class, however, is so useful that I have decided to jump the gun and offer it on its own.

We (ActionScript programmers) all know how useful the Array class is. It can be used to store a sequence of anything, so it can be repurposed as a list, a vector, an edge—all manner of collections.

Well, not all manner of collections. Just ordered collections that allow duplicate elements. What if you want a set: an unordered collection with no duplicates? I find I need sets all the time, but I have to use arrays. And arrays are not optimal for looking up an element's membership, or preventing duplication. As lists they're great, but as sets they suck.

For a while I used a class I'd made called ArraySet that wrapped an array, but this was only an improvement in API, not in performance. Then I took a cue from Java and created: HashSet.


The HashSet class wraps a Dictionary object, which it uses as a hash table. If an element belongs to the set, then that element is a self-referential key in the dictionary. If it doesn't, then there is no such key in the dictionary. And HashSet extends Proxy, so you can use bracket notation for many operations,. You can also use for..in and for each..in loops.

Here's a quick example:


// Create and populate the set.
var s:HashSet = HashSet.fromObject([1, 2, 3]);

trace(s.size); // 3
trace(s[1]); // 1
trace(s[2]); // 2
trace(s[0]); // undefined
trace(s.has(1)) // true

// Trace all elements of the set.
for each (var i:int in s)
{
trace(i);
}
// Trace all elements of the set (different method).
for (var x:* in s)
{
trace(x);
}

trace(s); // {1, 2, 3}
s.add(1);
trace(s); // {1, 2, 3}
s.add(4);
trace(s); // {1, 2, 3, 4}
s.remove(1);
trace(s); // {2, 3, 4}
delete s[2];
trace(s); // {3, 4}
s[3] = undefined;
trace(s); // {4}


...and so on. Full documentation is in the class itself, so you can figure out the details for yourself. I will mention that HashSet also has a number of functions in common with Array (every, filter, forEach, map, some) and others that are unique to sets (get empty, diff, intersect, prSubsetOf, subsetOf, union). It also has a few functions that Array really ought to have (clone, equals, remove).

Download it and try it! The full version is integrated into the mathematics package that I'm still tweaking, but this is too useful to keep to myself any longer. At least, I think so—let me know what you think.

06 June 2008

Three-Pound Monkey Brain: The Open Source Project

In an earlier post, I was bemoaning the unimaginative (and self-centered) name I was using for my general open source ActionScript project: net.tmkeesey. But someone pointed out to me this morning that a better name was staring me in the face all this time. Thus, I have changed the packages from net.tmkeesey to ... threelbmonkeybrain! (A bit long-winded, but unfortunately you cannot start package names with numerical digits.)

Along with this much-better name is a new location for the code. Point your Subversion clients to:
(Or, if you just want the code itself without unit tests, etc.: http://svn3.cvsdude.com/keesey/PROJECTS/ threelbmonkeybrain/as3/trunk/src/threelbmonkeybrain)

I've added a lot of new packages under the rubrics of threelbmonkeybrain.load and threelbmonkeybrain.net, but I have not had time to build full unit tests for them. Once that's done, I'll write more about those.

04 June 2008

More Additions to Open Code: Collections and Connectivity

I've added two new utility packages to net.tmkeesey. SVN repository here.)

net.tmkeesey.utils.mx
Static classes with utilities for handling Flex objects.
net.tmkeesey.utils.mx.ArrayCollectionUtil
Contains a convenience method for converting arrays to ArrayCollection objects with filters and/or sorts.
net.tmkeesey.utils.mx.Filtration
Contains handy functions which can be used for ICollectionView.filterFunction.
net.tmkeesey.utils.mx.ListCollectionViewUtil
Contains a convenience method for converting ListCollectionView objects to arrays, using filters and/or sorts.

net.tmkeesey.utils.net
Static classes with utilities for handling flash.net objects.
net.tmkeesey.utils.net.URLRequestHeaderUtil
Contains methods for cloning and comparing URLRequestHeader objects.
net.tmkeesey.utils.net.URLRequestUtil
Contains methods for cloning and comparing URLRequest objects.
net.tmkeesey.utils.net.URLVariablesUtil
Contains methods for cloning and comparing URLVariables objects.

As always, I commit nothing until I've created ASDoc comments and flexunit tests for everything.

(O.K., not the most exciting update, but....)

03 June 2008

Motion Blur

O.K., last one for the day—I promise.

I just committed a small addition to net.tmkeesey. As alluded to in my last post, it's motion blur. How easy is it to use? Here:

import net.tmkeesey.anim.effects.MotionBlur;
new MotionBlur(myDisplayObject);

Done. Now myDisplayObject will blur whenever you move it. It even works with preexisting filters. (Note that the blur looks best for horizontal and vertical motion, though. I may work on an improvement for that later.) There are also a few optional parameters: blurFactor (how much to blur per pixel moved), optimized (optimization flag—only uses powers of two for blurring if set to true the default), and quality (blur quality).

In the future I'd like to update this so that the parameters can be changed on the fly, but I'm not sure how useful that would really be. Good enough for now.

Once again, the code can be checked out from:
http://svn3.cvsdude.com/keesey/PROJECTS/tmkeesey/trunk

Updates to Open AS3 Code

Pursuant to my last post, I've added some general utility classes to the net.tmkeesey repository. They are arranged in two packages: utils.core and utils.display:

net.tmkeesey.utils.core
  • ClassUtil
  • ObjectUtil
  • StringUtil
  • TimerUtil
  • UIntUtil
  • XMLListUtil
  • XMLUtil
net.tmkeesey.utils.display
  • ColorUtil
  • DisplayObjectUtil

A couple of highlights:

UIntUtil.closestPowerOf2() can be used to optimize blur filters. (Coming soon: MotionBlur class.)

DisplayObjectUtil.findAncestor() searches an object's display ancestry for an object of a certain class. This can greatly facilitate communication between visual components. (And even nonvisual objects, as long as they have a parent property which is an instance of DisplayObjectContainer.)

As always, all classes come with unit tests and all code is commented with ASDoc (except for unit test code, where it would really be superfluous).

Once again, the repository is at: http://svn3.cvsdude.com/keesey/PROJECTS/tmkeesey/trunk

02 June 2008

I'm Going Open Source!

Over the years, I've come up with a large number of ActionScript packages that I reuse on projects. I've been meaning for a long time to release some of these packages to the public. Well, there's no time like the present, so I'm going to start.

One note: I'm using net.tmkeesey as a package name, but eventually I'd like to name it after something other than myself. So this is just provisional until I start opening up collaboration.

The repository is located at:



(I'm assuming that anyone who's read this far knows how to check out a project from a Subversion repository.)

I figured I'd start with the basics. I've included three very low-level packages: assert, core, and relate. These are distilled from packages I am using for Names on Nodes and other projects.

net.tmkeesey.assert.Assertion
Utility class with methods for making assertions.

net.tmkeesey.assert.AssertionError
Generic error type for a failed assertion.

net.tmkeesey.core.Property
Utility class for object properties.

net.tmkeesey.relate.ComparisonStack
Stores a stack of ordered, two-object comparisons. Used to prevent recursion.

net.tmkeesey.relate.Equality
Utility class for determining equality (either qualititave equality or identity) of two objects. Works with Equatable.

net.tmkeesey.relate.Equatable
Interface with a single method, equals(Object):Boolean, for determining qualitative equality.

net.tmkeesey.relate.Order
Utility class for determining the relative order of two objects. Works with Ordered.

net.tmkeesey.relate.Ordered
Interface which extends Equatable and adds a single method, findOrder(Object):int, for determining relative order.

There is also a full complement of unit tests in the flexunit_src folder. All code has full ASDoc comments.

Future additions may include: management of loaded assets, digital puppetry, some general user interface components, animation assistance, collection-related code, buttloads of utility classes, triggers, XML translation, MathML processing, "exoskeleton", and "champagne".

P.S. You may note that I'm defying my previous stance on uncradled brackets. I have to say, I gave them a chance, and I'm starting to understand why people like them. I can't put it into words just yet, but....

30 May 2008

Exopolis Online Ads

Just launched a new Flex minisite: Exopolis Online Ads.

(If you poke around long enough you might find a few little bugs, but it's mostly done.)

This is (obviously) a promotional piece for our banner ad capabilities. Doing the project in Flex made a lot of things easier: transitions, placement, deep-linking, back/forward button capabilities.

It's a bit risky loading banners directly into Flash, but fortunately Flex's AVM1Movie component largely keeps the banner functionality in its own "sandbox" (with a few exceptions that need tending to). Flash banner ads have some of the hackiest programming you'll ever care to see, but fortunately AVM1Movie prevents 99% of it from affecting the rest of the site.

I did get one nice, reuseable thing out of it, too: the MouseScrollCanvas component that controls those scrolling lists of links.

Which reminds me ... I really have to consolidate all the reuseable code I've written someday and release it....

Names, Nodes, and CRUD

The Third ISPN Meeting (mentioned here) is fast approaching. I'm still hoping to have an alpha version of Names on Nodes online by then, but it's going to be tricky. Currently I'm involved in a massive refactoring.

The basic point of Names on Nodes, as I've mentioned before, is to automate taxonomy. That is, you feed it:
  1. a bunch of phylogenetic definitions,
  2. a phylogeny, and
  3. specifier links, that is, correlations between definition specifiers (apomorphies, species, specimens) and units in the phylogeny (e.g., taxa in NEXUS trees).
Once properly fed, it spits out taxonomies, that is, associations of scientific names with sets of subtaxa.

That part of it is pretty much done. But there are two tricky parts I have yet to complete: data persistence and user interface. And what both basically boil down to is CRUD.

I've mentioned CRUD before here. It's an acronym for the four basic operations involved with data persistence, the four things you can do to a stored object. Those are:
  • Create
  • Retrieve
  • Update
  • Delete


As often happens in programming, I started out with an ad hoc sort of approach that worked well enough up to a point, but then I started finding myself in trouble. Duplicated code. Unnecessarily complex code. Code that was hard to update.

It was time to refactor.


Here's a breakdown of the new system.

Every user interface involved with persistent objects is managed by something called a FlowManager. This stores a navigable tree of FlowEntry objects, each associated with a visual FlowComponent.

The main application handles requests from all components within. These are sent to the application as bubbling events, that is, events that "bubble" up through the display hierarchy (say, from a button, to the form that contains it, to the flow manager, on up to the main application). Two of the major types of request are EditEntityEvent and DemandEntityEvent.

An EditEntityEvent comes with a persistent object (e.g., a species, a definition, a NEXUS file, etc.). The application's responsibility is to create a FlowComponent object that will display the entity and allow the user to edit it (Update).

A DemandEntityEvent comes with a class of persistent object (e.g., Species, Definition, Nexus, etc.). The application's responsibility, then, is to provide the "demander" with an object of that class, either by making a new one (Create) or by selecting an existing one (Retrieve).

(Note that I haven't mentioned Delete. I'm leaving that out of the first version. Any deletions will have to be made by myself, manually.)

One problem with my old approach was that I had different user interface components for each combination of CRU[D] action and persistent object. Take a couple dozen types of persistent object and multiply by three: that's how many components I had to make.

The new system, though, has just two types of FlowComponent: one for handling EditEntityEvent requests and the other for handling DemandEntityEvent requests.

The first one is the simplest: EntityEditor. It basically consists of the following components:
  • a form which shows all data in the persistent entity;
  • a bit of text that summarizes the entity in its current state (e.g., for a Binomen entity, something like "Prenomen nomen Author 1970");
  • a button that updates the entity in the database, or, if it is a new entity, creates it in the database; and
  • a "cancel" button.
The form has to be done individually for each type of persistent entity, but the rest is completely generic.

The other FlowComponent object, EntitySupplier, actually uses an EntityEditor object. Once the EntitySupplier object is given the class of entity that it's supposed to supply, it creates a default instance of that class and gives it to an EntityEditor, which it displays to the left. To the right, it displays a SuggestionBox, a grid showing various existing entities that might match what's in the editor.

The SuggestionBox uses a nonvisual object called an EntitySuggester, whose job is to watch for changes that the user makes to the persistent entity and come up with relevant, existing suggestions. For example, suppose the user is editing a new Publication object and starts to type in the authorship as "Linn". The PublicationSuggester sees this and checks the database for possible matches, coming up with "Linnaeus 1758". If this is the publication that the user wanted, then they can select it from the SuggestionBox without having to fill in any more information.

I still have to create a form and a suggester for every type of persistent entity, but this is a much neater division of labor than I had in the last version, where forms generated their own suggestions (which would be wasteful if you were just editing an existing entity).

Hope to get much done this weekend.
(Have to get much done this weekend....)