Archive for April 2007

ImageJ plugins 2

(This is a followup to ImageJ plugins)

Let us say that each filter will have two constructors. Filter() will be used by the menu and macro systems exclusively. It should pop up a dialog and fetch values from the user. The macro system takes the first word of each field in the dialog and tries to fill in the values given as arguments. We’ll end up breaking this somewhat later, but this is fine by me. The macro language is an abomination.

The other constructor takes all the necessary parameters as arguments: Filter(param1, param2, …). It should be used when writing Java, and doesn’t pop up a dialog.

The end goal is to be able to write code like:


ImagePlus im = …;
ImagePlus im2 = (new Filter(param1, param2)).filter(im);

We can actually abstract essentially all this behavior into a superclass, which I’ll call Filter. The programmer should only specify the required parameters, a setup method, and a run method. Actually, he’ll have to define a Filter(param1, param2, …) constructor as well, but I don’t see a way to escape this in Java.

Filter() reflects upon the object that calls it (so it we don’t override it, it gets continuously inherited), and finds all that object’s fields. How do we tell it which fields should be parameters and what kind they are? Annotations!

Annotations are a new features from Java 5, which let you attach a few bits of data to objects, namely primitive types, arrays of primitive types, and enums. This is frustratingly slim, but Java was designed to be a straightjacket, not a set of wings.

We define annotations for each of our acceptable parameter types: numbers, strings, boolean values, binary masks, and kernels. The numbers, strings, and booleans are self explanatory. Binary masks are rectangular arrays of booleans; kernels are rectangular arrays of floats. We’ll want them for doing convolutions and morphology.

The annotation definition looks something like this:


@Retention(RetentionPolicy.RUNTIME)
public @interface BooleanPlugInParameter {
     String label();
     boolean value();
}

If Java had real polymorphism, we could use a single annotation, but that would be too easy. We’re stuck with this.

So we iterate through the list of all an object’s fields and add fields to a dialog:


GenericDialog gd = new GenericDialog(”Arguments to ” + this.getClass().toString());
for (Field f : this.getClass().getDeclaredFields()) {
     if (f.getAnnotation(BooleanPlugInParameter.class) != null) {
          // Java doesn’t let me define variables in the comparisons of if statements
          BooleanPlugInParameter bann = f.getAnnotation(BooleanPlugInParameter.class);
          gd.addCheckbox(bann.label(), bann.value());
     } else if (f.getAnnotation(NumericPlugInParameter.class) != null) {
          // similar stuff
     } // and similar stuff for each annotation
}

Then we display the dialog, get the responses back, and iterate through the fields again to put the data in the right places. This takes care of the macro language and menu use.

We can put several utility methods for the Java programmer into Filter as well:

ImagePlus applyFilter(ImagePlus imp)
Takes an ImagePlus, applies the filtering operation in place (defined by the class’s setup and run methods, and returns a reference to the same ImagePlus. The code is modified from ImageJ’s IJ.runPlugInFilter method.
ImagePlus duplicate(ImagePlus imp)
Make a deep copy of imp. This perhaps needn’t be carried around by every Filter, but it’s really nice to have. The code is a hacked up version of what’s in ImageJ’s Duplicator class.
ImagePlus filterDuplicate(ImagePlus imp)
Just the composition of the previous two: apply this filter to a duplicate of imp.

Here’s an example plugin using this structure. It’s purpose should be pretty obvious.


public class AddN extends Filter {
     @NumericPlugInParameter(label=”Value to add”, value=0) Integer n;

     public AddN(Integer n) { this.n = n; }

     public int setup(String cmd, ImagePlus imp) {
          return DOES_16 + DOES_STACK;
          // Yes, this framework automatically handles stacks right!
     }

     public void run(ImageProcessor ip) {
          short[] pix = ip.getPixels();
          for (int i = 0; i < pix.length; i++) pix[i] += n;
     }
}

This is the beginning though. We can subclass Filter to create more specialized frameworks: LocalFilter to automatically handle all filters requiring neighborhoods; Convolver, whose purpose is obvious; BinaryFilter which takes two images and performs binary operations between them. More on these possibilities later.

I am going to finish cleaning up the basic classes and make a release of it soon. Probably next week, since I actually want to put documentation in.

Fundamental Principles of Biology

Philip at BioCurious mentions a seminar at the Chemical Biophysics Symposium in Toronto entitled “Can fundamental principles of biology be uncovered by nanotechnology.”

Biology starts out with plenty of “fundamental principles” in place. Everything it inherits from physics and chemistry can be considered a “fundamental principle.” Computer science has contributed a few things as well, but to date these tend to be idealized if not trivial.

Evolution gives us a few fundamental principles, e.g. any organism we find must be able to reproduce. That’s actually an enormous constraint. Take pug dogs. They can’t breed without human intervention. If we were trying to decipher the biology of pugs, among the first hypotheses we would generate is that there’s some external agency helping them reproduce. But these constraints don’t tell you what order genes have on a chromosome.

Marcello Magnasco once explained the point of biology to me thus: “We’re trying to reverse engineer a flying saucer.” Most beasties encode what needs to be passed on to create a similar beastie in RNA or DNA, all of them that we know of make use of protein as a structural component. However, as soon as we’re dogmatic and say, “all the alien devices have screws and bolts” someone’s going to find something welded together.

This bothers physicists a lot. I know it bothered me. I think it’s partially a result of physics training. Feynman wrote somewhere in the lectures something to the tune of: physicists take the simplest possible manifestation of a phenomenon and call that physics, then shove the rest off into engineering.

In biology we start from the engineering and work back to the physical laws. Systems biologists have lost sight of this. The whole field is predicated on a desparate hope that everything you might ever want to know about a biological system is encoded in a directed graph a geneticist put together. The complete failure of this program leads to absurdities like Michael Elowitz’s continuing study on noise. I mean no insult to Elowitz. He’s the best of the bunch, and he’s played the current fad to get a professorship at Caltech. But if he were being judged on how probing a question he was asking to reduce the problem to the physics underneath, I think it would seem pretty boring.

So can we please stop seeking for fundamental principles of toaster oven design?

ImageJ plugins

I’ve started building a new plugin system for ImageJ which will be much easier to work with.

Just to review, the current plugin system uses two interfaces (ij.plugin.PlugIn and ij.plugin.PlugInFilter) to implement these. The second is meant for implementing image processing algorithms. It defines two functions:

int setup(String cmd, ImagePlus imp)
All the setup work for the plugin is supposed to be done here. All parameters are passed through cmd, which is a holdover from ImageJ’s reprehensible macro language. The actual image to process is passed through imp.
void run(ImageProcessor ip)
After ImageJ has called the setup function, it calls run for each element of the image stack. ImageProcessors hold the actual pixel data for each image in the stack, which is wrapped up in the ImagePlus.

Note several obvious problems:

  • Plugins receive all their parameters from a string, so you have to write a mini-parser for each plugin. Everyone writes different parsers.
  • The ij.plugin.filter.PlugInFilter interface insists that setup returns an int (telling the plugin’s capabilities, which is reasonable), and run returns a void. How do you get the new image back?
  • If you expect to run the plugin from a menu instead of the macro language or directly from Java, you have to write an interface to get parameters from the user. Then you have to make it not appear when you’re called from the other two contexts.

A fix should automatically support all three contexts (Java, the macro language, and menus), without any additional programmer effort. This is impossible, but we can get fairly close, as I’ll describe next.

Homeschooling

I happened across this post on homeschooling. Go, watch the video and be disturbed. I can’t be bothered.

I was homeschooled from the eighth grade until I went off to college, and it’s people like this who made it very uncomfortable for me. I come from way back in rural Virginia where most of the homeschoolers were like this.

On the other hand, my parents read classics at Cambridge, my father did further graduate work in structural engineering. They gave me a wonderful education: Latin, Greek, French, Italian, history, music, mathematics, physics, chemistry (we had a friend who was a chemistry professor at UNC Chapel Hill who oversaw that one). I went off to college, did the physics BS in about a year and a half, spent the next year doing almost all the requirements for a masters in math (I didn’t want to do abstract algebra, which I now regret), and then spent a year studying under a theorist who had passed Landau’s theoretical minimum, before wandering off to do my PhD here at the Rockefeller University.

The public schools where I was were simply incapable of imparting anything like this. Last time I checked they didn’t even offer calculus, algebra was still taught by the cheerleading coach, and the only foreign language was Spanish.

Many people claim that going to school is important for socialization. This is backwards. My classmates were stupid, brutish, and cruel. It took me years to recover socially, and only because I spent those years in the company of well adjusted, tolerant people.

Let me end with a quote from Feynman:

“I think, however, that there isn’t any solution to this problem of education other than to realize that the best teaching can be done only when there is a direct individual relationship between a student and a good teacher — a situation in which the student discusses ideas, thinks about the things, and talks about the things. It is impossible to learn very much by simply sitting in a lecture, or even by simply doing the problems that are assigned. But in our modern times we have so many students to teach that we have to try to find some substitute for the ideal. Perhaps my lectures can make some contribution. Perhaps in some small place where there are individual teachers and students, they may get some inspiration or some ideas from the lectures. Perhaps they will have fun thinking them through — or going on to develop some of the ideas further.”

A Choice of Programming Languages

A long time ago, I read Eric Raymond’s ‘How To Become a Hacker‘, in which he advises a newcomer what skills and mindsets to cultivate to become a contributing member of the open source community.  He advocates learning five programming languages: C, Perl, Python, Java and LISP.

I know all these languages, and I offer a completely different list: Forth, Haskell, and Smalltalk.

Why not Raymond’s five?  C you will either use for embedded programming (where Forth is superior) or number crunching (where Haskell is superior).  Perl and Python are random accretions.  Java is a programmer specific pathogen.  Everything that made LISP glorious has either been subsumed by Haskell or was lost with the death of the LISP machines.

Why my three?

  • Forth: To program well, you need to understand the hardware, not just the abstractions of the programming language.  Forth represents the only hardware designs which have become more elegant and easier to understand over the years.  I’ve my doubts about ANS Forth, but Charles Moore’s latest experiments are seductive and compelling.
  • Haskell: When you have left the realm of the machine itself, the only reliable source of structures and idioms to organize thoughts about programming is mathematics.  Haskell is the closest thing to pure mathematics available today.
  • Smalltalk: The most charming tools ever created to get a programmer through his work reside in Smalltalk environments.  The pale attempts to emulate them in Java and C++ are laughable.  Any development environment must be compared to this standard, and all others are lacking.  The closest competitors, and they are distant, are the most integrated and ascetic of the Forth environments.

I realize this list has a peculiar flavor.  I think the distinguishing characteristic is that they are languages where a single individual can assimilate the whole structure from top to bottom.  In Forth and Smalltalk, this means understanding the environment from to its roots.  In Haskell, it means understanding the language, which is a mathematical abstraction, to its roots.

Not that I have actually obtained such an understanding of any of the three.  What makes these languages from ones you can understand into ones you can love is that it’s obvious from the shallows that you can plumb the depths if you just devote some time.