CCfits  2.4
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:

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;
}