Corelyzer - PSICAT Integration

This weekend I finished the initial work of integrating PSICAT and Corelyzer. It is now possible to export the lithological core description from PSICAT and import it into Corelyzer where you can view it next to the core images:
CorelyzerPSICAT.png

The implementation consists of two components: a plugin for PSICAT and a plugin for Corelyzer. The PSICAT plugin simply exports the lithological core description from PSICAT into a simple, tab-separated file format. The Corelyzer plugin parses this file and renders it into a track inside Corelyzer. This design affords the maximum amount of flexibility because there is no actual dependency on PSICAT. Other tools or databases (dbSEABED? Janus? ICDP's DIS?) can generate a properly formatted TSV file and see the results in Corelyzer. The Corelyzer plugin supports multiple lithology schemes, each of which can define any number of lithologies and associate a color and pattern with each. I've included the USGS lithology scheme that I digitized for use in PSICAT.

The plugin is built against the current Subversion version of Corelyzer, so there's easy way to distribute the plugin for others to play around with. Perhaps Julian can put up a experimental build of Corelyzer that includes the plugin.

The rest of this article will be devoted to describing the technical details behind the plugin, the lithology data format, and the lithology scheme format. I've started a discussion in the Support Forum to track bugs and missing features. Feel free to join the discussion.

The PSICAT Plugin

The plugin for PSICAT to generate the lithology data format is pretty simple and straightforward. It's a standard PSICAT plugin that adds a new option ("Corelyzer data") to the File -> Export... menu. This is a variation on a common theme, so it was about 50 lines of code.

The Corelyzer Plugin

The plugin for Corelyzer is significantly more interesting. It is implemented entirely in Java using JOGL (even the texture wrangling), so there was no need to modify any of the native code to make it work.

I spent a little time to refine the current Freedraw approach. In the process, I created 3 classes that would be useful to include in the standard Corelyzer code base:

  • FreedrawContext - This class just wraps all of the parameters that are passed to CorelyzerPlugin#render(). This makes the method calls much simpler because you pass only a single parameter rather than a dozen. It also lets you add new fields later on without breaking older plugins.
  • FreedrawRenderer - This interface consists of two methods: dispose() which is called when the freedraw rectangle is destroyed and render(FreedrawContext context) which is called to do the actual rendering. This was done to separate the drawing code from the plugin code.
  • FreedrawPlugin - This class subclasses CorelyzerPlugin and adds some methods to register new freedraw rectangles and associate them with a FreedrawRenderer. It also provides an implementation of the CorelyzerPlugin#render() method that looks up which freedraw rectangle is being asked to render and forwards the request to the appropriate render. This allows a single plugin to easily manage multiple freedraw rectangles.

The plugin also includes some code for handling the lithology schemes (described below). This code is take almost verbatim from the PSICAT code base, so I may opt to just package it as a library to include with the plugin. For the time being, the source is included in the plugin's code base.

The bulk of the interesting work is done in the LithologyRenderer class. It loads up the lithology data (more below), maps the data to the current lithology scheme, and actually draws the colors and patterns. I ran into a few problems while implementing it. Originally the plugin was drawing the whole dataset, even the stuff that was off screen, every time render() was called. This made for choppy performance, so I optimized it to only draw the intervals that are on the screen.

I also ran into some OpenGL problems. GL is supposed to support a GL_REPEAT mode for tiling textures. However, I must have been doing something wrong, because when I enabled it, the performance went to hell. I ended up using GL_CLAMP for the textures implemented the tiling myself. I was worried this would cause performance issues, but it seems to work well enough. I also didn't get the blending of color and texture they way I wanted it. From the screenshot above, you can see the texture is rendered in color. I wanted to render the color and then subtract the texture like is done in PSICAT, but I couldn't figure out the proper blend function to do it.

Lithology Data Format

The lithological core description data is encoded in a simple tab-separated value format:

15.84   17.16
17.16   18.14   1.0:argillaceous,shaly,sandstone
18.14   18.78   0.7:massive,sand,sandstone,volcanic     0.3:massive,sand,sandstone

Each unit/interval is encoded on a single line. The first two fields in the row are the top and bottom depths of the interval in meters. The remaining fields (if any) are the lithologies associated with the interval. The lithology fields take the form of ratio:keyword1,keyword2,keyword3. The ratios in the lithology field should add up to 1.0. Each lithology field can have one or more keywords associated with it. The keywords are used to determine the color and pattern to use for rendering from the current lithology scheme (more below).

Currently the lithology data must be in a file called lithology.tsv inside of a zip file. The zip file was originally because I was planning on including the lithology patterns with the data but later decided to separate the data from the presentation. So there is currently no need to put things inside of a zip file. The plugin may be updated to accept individual files or to read from the existing Core ARchive format.

Example Files:

Lithology Scheme Format

The plugin currently supports multiple custom lithology schemes. The schemes are used to determine which color and pattern to use when rendering lithologies.

Each scheme is defined in a scheme.xml file using a straightforward XML format described below. The scheme.xml file and all associated patterns are packaged in a JAR archive and added to the classpath. All schemes on the classpath will be discovered and parsed.

The XML format:

<scheme name="lithology" scope="usgs">
    <entry>
        <keywords>Gravel,Conglomerate,1</keywords>
        <property name="name">Gravel or Conglomerate 1</property>
        <property name="image">images/601.png</property>
        <property name="color">160,82,45</property>
    </entry>
    <entry>
        <keywords>Gravel,Conglomerate,2</keywords>
        <property name="name">Gravel or Conglomerate 2</property>
        <property name="image">images/602.png</property>
        <property name="color">160,82,45</property>
    </entry>
    ...
</scheme>

Each scheme consists of a name, a scope, and zero or more entrys. Name is a bit of a misnomer, it really represents the category of the scheme. For a lithology scheme, you'll want to specify "lithology" as the name and an identifier for the scope. The snippet above is from the USGS lithology scheme that I digitized for use in PSICAT.

Each entry in a scheme consists of a keyword tag and any number of property tags. The keyword tag contains a comma-separated list of freeform strings used to identify the entry. The keywords can be a simple unique identifier, e.g. lith102, or can be a list of descriptive tags, e.g. gravel,conglomerate.

The keywords from the data file are matched to the entries by means of a fuzzy scoring algorithm. If your data will only be used with your custom lithology scheme, unique identifiers are fine. If the data may be used with other lithology schemes, using descriptive tags will allow some chance of portability between schemes.

Entries may contain any number of property tags. These can be used to associate data with each entry. For lithology schemes, the color and image properties may be specified. The color is specified in an RGB triplet in decimal values (0-255). The image is specified as a path within the JAR file. The images can be any standard image format.

Example Files:

Conclusion

This article has described the efforts in integrating PSICAT and Corelyzer and also how this effort can be re-used by other tools and databases. Feel free to ask questions, make comments, and submit bugs via the forum thread.