CCfits 2.7

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

Creating and Writing to a Binary Table Extension

The Binary Table interface is more complex because there is an additional parameter, the vector size of each `cell' in the table, the need to support variable width columns, and the desirability of supporting the input of data in various formats.

The interface supports writing to vector tables the following data structures: C-arrays (T*), std::vector<T> objects, std::valarray<T> objects, and std::vector<valarray<T> >. The last of these is the internal representation of the data.

The function below exercises the following functionality:

- Create a BinTable extension
- Write vector rows to the table
- Insert table rows
- Write complex data to both scalar and vector columns.
- Insert Table columns
- Delete Table rows
- Write HISTORY and COMMENT cards to the Table

    int writeBinary ()

    //*********************************************************************
    // Create a BINARY table extension and write and manipulate vector rows
    //*********************************************************************
    {
        std::auto_ptr<FITS> pFits(0);

        try
        {

            const std::string fileName("atestfil.fit");
            pFits.reset( new FITS(fileName,Write) );
        }
        catch (CCfits::FITS::CantOpen)
        {
              return -1;
        }

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

        colName[0] = "numbers";
        colName[1] = "sequences";
        colName[2] = "powers";
        colName[3] = "big-integers";
        colName[4] = "dcomplex-roots";
        colName[5] = "fcomplex-roots";
        colName[6] = "scalar-complex";

        colForm[0] = "8A";
        colForm[1] = "20J";
        colForm[2] = "20D";
        colForm[3] = "20V";
        colForm[4] = "20M";
        colForm[5] = "20C";
        colForm[6] = "1M";

        colUnit[0] = "magnets";
        colUnit[1] = "bulbs";
        colUnit[2] = "batteries";
        colUnit[3] = "mulberries";
        colUnit[4] = "";
        colUnit[5] = "";
        colUnit[6] = "pico boo";

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

        const string num("NUMBER-");
        for (size_t j = 0; j < rows; ++j)
        {
    #ifdef HAVE_STRSTREAM
            std::ostrstream pStr;
    #else
            std::ostringstream pStr;
    #endif
            pStr << num << j+1;
            numbers[j] = string(pStr.str());
        }

        const size_t OFFSET(20);

        // write operations take in data as valarray<T>, vector<T> , and
        // vector<valarray<T> >, and T* C-arrays. Create arrays to exercise the C++
        // containers. Check complex I/O for both float and double complex types.

        std::valarray<long> sequence(60);
        std::vector<long> sequenceVector(60);
        std::vector<std::valarray<long> > sequenceVV(3);

        for (size_t j = 0; j < rows; ++j)
        {
            sequence[OFFSET*j] = 1 + j;
            sequence[OFFSET*j+1] = 1 + j;
            sequenceVector[OFFSET*j] = sequence[OFFSET*j];
            sequenceVector[OFFSET*j+1] = sequence[OFFSET*j+1];
            // generate Fibonacci numbers.
            for (size_t i = 2; i < OFFSET; ++i)
            {
                size_t elt (OFFSET*j +i);
                sequence[elt] = sequence[elt-1] + sequence[elt - 2];
                sequenceVector[elt] = sequence[elt] ;
            }
            sequenceVV[j].resize(OFFSET);
            sequenceVV[j] = sequence[std::slice(OFFSET*j,OFFSET,1)];

        }

        std::valarray<unsigned long> unsignedData(60);
        unsigned long base (1 << 31);
        std::valarray<double> powers(60);
        std::vector<double> powerVector(60);
        std::vector<std::valarray<double> > powerVV(3);
        std::valarray<std::complex<double> > croots(60);
        std::valarray<std::complex<float> > fcroots(60);
        std::vector<std::complex<float> > fcroots_vector(60);
        std::vector<std::valarray<std::complex<float> > > fcrootv(3);

        // create complex data as 60th roots of unity.
        double PIBY = M_PI/30.;

        for (size_t j = 0; j < rows; ++j)
        {
            for (size_t i = 0; i < OFFSET; ++i)
            {
                size_t elt (OFFSET*j+i);
                unsignedData[elt] = sequence[elt];
                croots[elt] = std::complex<double>(std::cos(PIBY*elt),std::sin(PIBY*elt));
                fcroots[elt] = std::complex<float>(croots[elt].real(),croots[elt].imag());
                double x = i+1;
                powers[elt] = pow(x,j+1);
                powerVector[elt] = powers[elt];
            }
            powerVV[j].resize(OFFSET);
            powerVV[j] = powers[std::slice(OFFSET*j,OFFSET,1)];
          }

        FITSUtil::fill(fcroots_vector,fcroots[std::slice(0,20,1)]);

        unsignedData += base;
        // syntax identical to Binary Table

        Table* newTable = pFits->addTable(hduName,rows,colName,colForm,colUnit);

        // numbers is a scalar column

        newTable->column(colName[0]).write(numbers,1);

        // write valarrays to vector column: note signature change

        newTable->column(colName[1]).write(sequence,rows,1);
        newTable->column(colName[2]).write(powers,rows,1);
        newTable->column(colName[3]).write(unsignedData,rows,1);
        newTable->column(colName[4]).write(croots,rows,1);
        newTable->column(colName[5]).write(fcroots,rows,3);
        newTable->column(colName[6]).write(fcroots_vector,1);

        // write vectors to column: note signature change

        newTable->column(colName[1]).write(sequenceVector,rows,4);
        newTable->column(colName[2]).write(powerVector,rows,4);

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

        for (size_t j = 0; j < 3 ;  ++j)
        {
            fcrootv[j].resize(20);
            fcrootv[j] = fcroots[std::slice(20*j,20,1)];
        }

        // write vector<valarray> object to column.

        newTable->column(colName[1]).writeArrays(sequenceVV,7);
        newTable->column(colName[2]).writeArrays(powerVV,7);

        // create a new vector column in the Table

        newTable->addColumn(Tfloat,"powerSeq",20,"none");

        // add data entries to it.

        newTable->column("powerSeq").writeArrays(powerVV,1);
        newTable->column("powerSeq").write(powerVector,rows,4);
        newTable->column("dcomplex-roots").write(croots,rows,4);
        newTable->column("powerSeq").write(sequenceVector,rows,7);

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

        // delete one of the original columns.

        newTable->deleteColumn(colName[2]);

        // add a new set of rows starting after row 3. So we'll have 14 with
        // rows 4,5,6,7,8 blank

        newTable->insertRows(3,5);

        // now, in the new column, write 3 rows (sequenceVV.size() = 3). This
        // will place data in rows 3,4,5 of this column,overwriting them.

        newTable->column("powerSeq").writeArrays(sequenceVV,3);
        newTable->column("fcomplex-roots").writeArrays(fcrootv,3);

        // delete 3 rows starting with row 2. A Table:: method, so the same
        // code is called for all Table objects. We should now have 11 rows.

        newTable->deleteRows(2,3);

        //add a history string. This function call is in HDU:: so is identical
        //for all HDUs

        string hist("This file was created for testing CCfits write functionality");
        hist += " it serves no other useful purpose. This particular part of the file was ";
        hist += " constructed to test the writeHistory() and writeComment() functionality" ;

        newTable->writeHistory(hist);

        // add a comment string. Use std::string method to change the text in the message
        // and write the previous junk as a comment.

        hist.insert(0, " COMMENT TEST ");

        newTable->writeComment(hist);

        // ... print the result.

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

        return 0;
    }