FITS-WCS is an ontology


Older: v1

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, and follows a brief presentation at the FITS BoF at the 2010 ADASS in Boston. 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.


Matthew Graham started it, by asking (2008 October 10), 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:

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.

RDF makes it possible to make available machine-understandable information with much less pre-coordination than otherwise. RDF is in no sense a replacement for FITS (it does not deal naturally with bulk data), but in situations where you have a small amount of ‘FITS-like’ information to describe, such as in an HTML page, or in XML, or (obviously) in any RDF application, the framework exploited here is a standardised technique for embedding that information in a machine-understandable way.

The work described on this page is simply showing how to exploit this framework, by repurposing the FITS-WCS logic into a concrete RDF ontology.

The FITS-WCS ontology

Consider a set of FITS headers, which we can represent in the usual way as follows:

BITPIX = -32
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
CRVAL2 = 39.3963
COMMENT   axis number 2
PS2_1 = 'foo'
PS2_2 = 'bar'
COMMENT   axis number 3

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 <> .
@prefix rdf: <> .
@prefix fits: <> .
@prefix ctype: <> .
@prefix prov: <> .

    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+00 """^^<> ;
        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"^^<> ;
                a prov:NonHumanActor ;
                <> "fits-rdf 0.1, Hg:371db7dc857a, 2010-11-07T13:36:30-05:00"
            ] ;
            a prov:DataAccess
        ] ;
        a fits:WCSInformation
    ] ;
    a fits:FITSheader .

    fits:axisNumber 1 ;
    fits:numberOfPixels 10 ;
    fits:referencePixel 420 ;
    a fits:PixelAxis .

    fits:axisNumber 2 ;
    fits:numberOfPixels 10 ;
    fits:referencePixel 424.5 ;
    a fits:PixelAxis .

    fits:axisNumber 3 ;
    fits:numberOfPixels 4 ;
    fits:referencePixel 0 ;
    a fits:PixelAxis .

    fits:axisNumber 1 ;
    fits:coordinateType ctype:RA---TAN ;
    fits:projectionParameters (1 2 ) ;
    fits:referenceCoordinate 182.631 ;
    a fits:WorldAxis .

    fits:axisNumber 2 ;
    fits:coordinateType ctype:DEC--TAN ;
    fits:projectionParameterStrings ("foo" "bar" ) ;
    fits:referenceCoordinate 39.3963 ;
    a fits:WorldAxis .

    fits:axisNumber 3 ;
    fits:coordinateType ctype:GROUP_NUMBER ;
    a fits:WorldAxis .

The ontology is available at fits-core.ttl, and has the namespace – that PURL doesn't resolve, as yet.


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.

Norman, 2010 November 6

Updated 2011 June 3: Add links and clarifications