At the 2008 ADASS in Québec, I gave a short talk at the FITS BoF, describing FITS-WCS as an ontology. This (finally) is the worked-out version of that talk. It's not that this work has taken two years, but... other things got in the way.
Below, I'll relate the initial motivation for this work, add a couple of words about RDF, and then describe in turn the RDF ontology I've developed, and a couple of tools which can convert FITS headers back and forth between RDF and FITS files.
Motivation
Matthew Graham started it, by asking (2008 October 10 – archive unavailable right now), on the IVOA Semantics list
I want to represent the relationship “object has a RA of 134.556” as an RDF triple. Is there any existing ontology that would allow me to do this?
My rather glib response was that yes, there is indeed an existing ontology: FITS-WCS!
That's not a terribly useful answer for Matthew, since it skips the technicalities involved in expressing this ontology in RDF. That has now been remedied, at least in outline, and this document describes the result. Below, I describe the (implicit) FITS ontology for positions, as described in FITS WCS Paper I. It's not complete – for example, it doesn't describe any of the coordinate systems – but it captures the description of the axes, and their rotations. In particular, it represents the semantics expressed in the keywords: BITPIX, CUNITi, CRVALn, NAXISn, CRPIXn, CDELTn, CTYPEn, PCi, CDi, PVi and PSi.
First, where is this heading, and why?
This isn't the place for an introduction to, or argument for, RDF – you can find that elsewhere. Instead, we'll just summarise the crucial points as:
- RDF’ = resource description framework (not format)
- It's not about syntax: you can write it down and send it over the web; but you don’t always want to.
- It's not about efficiency: you might represent data as RDF internally; but you don’t always want to.
The key thing is that RDF is (if we can coin a phrase) ‘everything-neutral’ – it can be thought of as the assembly-language of the semantic web. That makes it useful for interchange in widely varying contexts, and it makes it useful when discussing different syntaxes, and the meaning associated with them. Also, obviously, it's useful for describing positions when you're already using RDF.
The FITS-WCS ontology
Consider a set of FITS headers, which we can represent in the usual way as follows:
SIMPLE = T BITPIX = -32 NAXIS = 3 CRPIX1 = 420 NAXIS1 = 10 CRPIX2 = 424.5 NAXIS2 = 10 CRPIX3 = 0 NAXIS3 = 4 CRVAL1 = 182.631 COMMENT axis number 1 PV1_1 = 1 PV1_2 = 2 CTYPE1 = 'RA---TAN' CRVAL2 = 39.3963 COMMENT axis number 2 PS2_1 = 'foo' PS2_2 = 'bar' CTYPE2 = 'DEC--TAN' COMMENT axis number 3 CTYPE3 = 'GROUP_NUMBER'
That's a plain list of key-value pairs, but those pairsp actually represent an intricate structure, which can be reconstructed by using suitable library software which has knowledge of that structure ‘built in’, and which merely needs the parameter slots filled in. That ‘built-in’ knowledge comes from Paper I but can, at least in part, be made explicit using the ontology.
Expressed as an RDF ontology, that FITS header looks like this:
@base <http://example.org/test1.fits> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix fits: <http://purl.org/astro/fits/core#> . @prefix ctype: <http://purl.org/astro/fits/ctype#> . @prefix prov: <http://purl.org/net/provenance/ns#> . <> fits:bitsPerPixel -32 ; fits:hasWCSInformation [ fits:cdMatrix "-1.06704000e-06 -1.25958000e-05 0.00000000e+00 -1.26016000e-05 1.06655000e-06 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+"^^<http://www.w3.org/2001/XMLSchema#string> ; fits:hasPixelAxis <#pa1>, <#pa2>, <#pa3> ; fits:hasPixelAxisList (<#pa1> <#pa2> <#pa3> ) ; fits:hasWorldAxis <#wa1>, <#wa2>, <#wa3> ; fits:hasWorldAxisList (<#wa1> <#wa2> <#wa3> ) ; prov:retrievedBy [ prov:performedBy [ prov:performedAt "2010-11-07T22:03:39"^^<http://www.w3.org/2001/XMLSchema#dateTime> ; a prov:NonHumanActor ; <http://xmlns.org/foaf/1.1/name> "fits-rdf 0.1, Hg:371db7dc857a, 2010-11-07T13:36:30-05:00" ] ; a prov:DataAccess ] ; a fits:WCSInformation ] ; a fits:FITSheader . <#pa1> fits:axisNumber 1 ; fits:numberOfPixels 10 ; fits:referencePixel 420 ; a fits:PixelAxis . <#pa2> fits:axisNumber 2 ; fits:numberOfPixels 10 ; fits:referencePixel 424.5 ; a fits:PixelAxis . <#pa3> fits:axisNumber 3 ; fits:numberOfPixels 4 ; fits:referencePixel 0 ; a fits:PixelAxis . <#wa1> fits:axisNumber 1 ; fits:coordinateType ctype:RA---TAN ; fits:projectionParameters (1 2 ) ; fits:referenceCoordinate 182.631 ; a fits:WorldAxis . <#wa2> fits:axisNumber 2 ; fits:coordinateType ctype:DEC--TAN ; fits:projectionParameterStrings ("foo" "bar" ) ; fits:referenceCoordinate 39.3963 ; a fits:WorldAxis . <#wa3> fits:axisNumber 3 ; fits:coordinateType ctype:GROUP_NUMBER ; a fits:WorldAxis .
The ontology is available at fits-core.ttl, and has the namespace http://purl.org/astro/fits/core – that PURL doesn't resolve, as yet.
Tools
I have some tools to automate the conversion from FITS to RDF, and back again. They're still rather preliminary, but if you want to experiment, see fits-rdf-0.1.tar.gz.