CCfits: Creating and Writing to an Ascii Table Extension

CCfits 2.7

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

Creating and Writing to an Ascii Table Extension

In this section of the program we create a new Table extension of type AsciiTbl, and write three columns with 6 rows. Then we add another copy of the data two rows down (starting from row 3) thus overwriting values and creating new rows. We test the use of null values, and writing a date string. Implicit data conversion, as illustrated for images above, is supported. However, writing numeric data as character data, supported by cfitsio, is not supported by CCfits.

Note the basic pattern of CCfits operations: they are performed on an object of type FITS. Access to HDU extension is provided by FITS:: member functions that return references or pointers to objects representing HDUs. Extension are never created directly (all extension ctors are protected), but only through the functions FITS::addTable and FITS::addImage which add extensions to an existing FITS object, performing the necessary cfitsio calls.

The FITS::addTable function takes as one of its last arguments a HDU Type parameter, which needs to be AsciiTbl or BinTbl. The default is to create a BinTable (see next function).

Similarly, access to column data is provided through the functions ExtHDU::Column, which return references to columns specified by name or index number - see the documentation for the class ExtHDU for details.

addTable returns a pointer to Table, which is the abstract immediate superclass of the concrete classes AsciiTable and BinTable, whereas addImage returns a pointer to ExtHDU, which is the abstract base class of all FITS extensions. These base classes implement the public interface necessary to avoid the user of the library needing to downcast to a concrete type.

    int writeAscii ()

    //******************************************************************
    // Create an ASCII Table extension containing 3 columns and 6 rows *
    //******************************************************************
    {
        // declare auto-pointer to FITS at function scope. Ensures no resources
        // leaked if something fails in dynamic allocation.
        std::auto_ptr<FITS> pFits(0);

        try
        {

            const std::string fileName("atestfil.fit");

            // append the new extension to file created in previous function call.
            // CCfits writing constructor.

            // if this had been a new file, then the following code would create
            // a dummy primary array with BITPIX=8 and NAXIS=0.

            pFits.reset( new FITS(fileName,Write) );
        }
        catch (CCfits::FITS::CantOpen)
        {
              // ... or not, as the case may be.
              return -1;
        }

        unsigned long rows(6);
        string hduName("PLANETS_ASCII");
        std::vector<string> colName(3,"");
        std::vector<string> colForm(3,"");
        std::vector<string> colUnit(3,"");

        /* define the name, datatype, and physical units for the 3 columns */
        colName[0] = "Planet";
        colName[1] = "Diameter";
        colName[2] = "Density";

        colForm[0] = "a8";
        colForm[1] = "i6";
        colForm[2] = "f4.2";

        colUnit[0] = "";
        colUnit[1] = "km";
        colUnit[2] = "g/cm^-3";

        std::vector<string> planets(rows);

        const char *planet[] = {"Mercury","Venus","Earth","Mars","Jupiter","Saturn"};
        const char *mnemoy[] = {"Many","Volcanoes","Erupt","Mulberry","Jam","Sandwiches",
                                "Under","Normal","Pressure"};

        long diameter[] = {  4880,    12112,      12742,   6800,    143000,   121000};
        float density[]  = { 5.1f,     5.3f,      5.52f,   3.94f,    1.33f,    0.69f};

        // append a new ASCII table to the fits file. Note that the user
        // cannot call the Ascii or Bin Table constructors directly as they
        // are protected.

        Table* newTable = pFits->addTable(hduName,rows,colName,colForm,colUnit,AsciiTbl);
        size_t j = 0;
        for ( ; j < rows; ++j) planets[j] = string(planet[j]);

        // Table::column(const std::string& name) returns a reference to a Column object

        try
        {

            newTable->column(colName[0]).write(planets,1);
            newTable->column(colName[1]).write(diameter,rows,1);
            newTable->column(colName[2]).write(density,rows,1);

        }
        catch (FitsException&)
        {
             // ExtHDU::column could in principle throw a NoSuchColumn exception,
             // or some other fits error may ensue.
             std::cerr << " Error in writing to columns - check e.g. that columns of specified name "
                       << " exist in the extension \n";

        }

        //  FITSUtil::auto_array_ptr<T> is provided to counter resource leaks that
        //  may arise from C-arrays. It is a std::auto_ptr<T> analog that calls
        //  delete[] instead of delete.

        FITSUtil::auto_array_ptr<long>  pDiameter(new long[rows]);
        FITSUtil::auto_array_ptr<float>  pDensity(new float[rows]);
        long* Cdiameter = pDiameter.get();
        float*  Cdensity = pDensity.get();

        Cdiameter[0] = 4880; Cdiameter[1] = 12112; Cdiameter[2] = 12742; Cdiameter[3] = 6800;
        Cdiameter[4] = 143000; Cdiameter[5] = 121000;

        Cdensity[0] = 5.1f;  Cdensity[1] = 5.3f;  Cdensity[2] = 5.52f;
        Cdensity[3] = 3.94f; Cdensity[4] = 1.33f; Cdensity[5] = 0.69;

        // this << operator outputs everything that has been read.

        std::cout << *newTable << std::endl;

        pFits->pHDU().addKey("NEWVALUE",42," Test of adding keyword to different extension");

        pFits->pHDU().addKey("STRING",std::string(" Rope "),"trailing blank test 1 ");

        pFits->pHDU().addKey("STRING2",std::string("Cord"),"trailing blank test 2 ");
        // demonstrate increaing number of rows and null values.
        long ignoreVal(12112);
        long nullNumber(-999);
        try
        {
            // add a TNULLn value to column 2.
            newTable->column(colName[1]).addNullValue(nullNumber);
            // test that writing new data properly expands the number of rows
            // in both the file]).write(planets,rows-3);
            newTable->column(colName[2]).write(density,rows,rows-3);
            // test the undefined value functionality. Undefineds are replaced on
            // disk but not in the memory copy.
            newTable->column(colName[1]).write(diameter,rows,rows-3,&ignoreVal);
        }
        catch (FitsException&)
        {
            // this time we're going to ignore problems in these operations

        }

        // output header information to check that everything we did so far
        // hasn't corrupted the file.

        std::cout << pFits->pHDU() << std::endl;

        std::vector<string> mnemon(9);
        for ( j = 0; j < 9; ++j) mnemon[j] = string(mnemoy[j]);

        // Add a new column of string type to the Table.
        // type,  columnName, width, units. [optional - decimals, column number]
        // decimals is only relevant for floatingpoint data in ascii columns.
        newTable->addColumn(Tstring,"Mnemonic",10," words ");
        newTable->column("Mnemonic").write(mnemon,1);

        // write the data string.
        newTable->writeDate();

        // and see if it all worked right.
        std::cout << *newTable << std::endl;

        return 0;
    }