#include "machdefs.h" #include "sopnamsp.h" #include #include #include #include #include "datatable.h" #include "fitsblkrw.h" #include "fitshandler.h" #include "swfitsdtable.h" DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */ int FitsHandler::CheckReadability(FitsInOutFile& is) { if (is.CurrentHDUType() == IMAGE_HDU ) return 0; string key = "SOPCLSNM"; string clsnm = is.KeyValue(key); if ( (clsnm == "SOPHYA::DataTable") || (clsnm == "SOPHYA::SwFitsDataTable") ) return 2; else return 1; } DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */ void FitsHandler::Write(FitsInOutFile& os) { if (dobj == NULL) throw NullPtrError("FitsHandler::Write() NULL dobj pointer "); DataTable* dt = dynamic_cast< DataTable *> (dobj); SwFitsDataTable* swfdt = dynamic_cast< SwFitsDataTable *> (dobj); int tbltyp = os.GetDef_TableType(); if ( swfdt && (tbltyp == ASCII_TBL) ) throw FitsIOException("FitsHandler::Write() ASCII_TBL not supported for SwFitsDataTable"); // On ne reecrit pas la definition d'une SwFitsDataTable dans son fichier de swap if (swfdt && (swfdt->mSwF.FitsPtr()==os.FitsPtr()) && swfdt->NRows() ) return; string strcoltag; long strwidth = os.GetDef_StrColWidth(); if (strwidth < 1) strwidth = 16; char buff[32]; if (tbltyp == ASCII_TBL) sprintf(buff, "A%ld",strwidth); else sprintf(buff, "%ldA",strwidth); strcoltag = buff; vector colnames, tform, tunit; for(sa_size_t k=0; kNVar(); k++) { bool fgoknm = true; bool fgoktun = true; switch ( dobj->GetColumType(k) ) { case BaseDataTable::IntegerField : if (tbltyp == ASCII_TBL) tform.push_back("I9"); else tform.push_back("J"); break; case BaseDataTable::LongField : if (tbltyp == ASCII_TBL) tform.push_back("I12"); else tform.push_back("K"); break; case BaseDataTable::FloatField : if (tbltyp == ASCII_TBL) tform.push_back("E12.5"); else tform.push_back("E"); break; case BaseDataTable::DoubleField : case BaseDataTable::DateTimeField : if (tbltyp == ASCII_TBL) tform.push_back("D15.8"); else tform.push_back("D"); if (dobj->GetColumType(k) == BaseDataTable::DateTimeField ) { tunit.push_back("Days (DateTimeField)"); fgoktun = false; } break; case BaseDataTable::ComplexField : if (tbltyp == ASCII_TBL) { cout << "FitsHandler::Write()/Warning ComplexField not supported for ASCII_TBL " << endl; fgoknm = false; } else tform.push_back("C"); break; case BaseDataTable::DoubleComplexField : if (tbltyp == ASCII_TBL) { cout << "FitsHandler::Write()/Warning DoubleComplexField not supported for ASCII_TBL " << endl; fgoknm = false; } else tform.push_back("M"); break; case BaseDataTable::StringField : tform.push_back(strcoltag); break; default: throw IOExc("FitsHandler::Write() unknown column type "); break; } if (fgoknm) { colnames.push_back(dobj->GetColumName(k)); if (fgoktun) tunit.push_back(""); } } // On cree la table string extname = os.NextExtensionName(); os.CreateTable(os.GetDef_TableType(), extname, colnames, tform, tunit); // On n'ecrit pas les donnees d'une table SwFitsDataTable ds son fichier de swap if (swfdt && (swfdt->mSwF.FitsPtr()==os.FitsPtr()) ) return; // Ecriture des donnees des colonnes for(sa_size_t l=0; lNEntry(); l+=dobj->SegmentSize()) { sa_size_t icol = 0; sa_size_t sz = dobj->SegmentSize(); sa_size_t iseg = l/sz; if ((l+sz) > dobj->NEntry()) sz = dobj->NEntry()-l; for(sa_size_t k=0; kNVar(); k++) { sa_size_t sk = dobj->mNames[k].ser; //DBG cout << "DBG-A k= " << k << " nom=" << dobj->mNames[k].nom << " ser=" << sk //DBG << " type=" << dobj->GetColumType(k) << endl; switch ( dobj->GetColumType(k) ) { case BaseDataTable::IntegerField : icol++; FitsBlockRW::WriteColumnData(os, icol, l+1, 1, dobj->mIColsP[sk]->GetCstSegment(iseg), sz); break; case BaseDataTable::LongField : icol++; FitsBlockRW::WriteColumnData(os, icol, l+1, 1, dobj->mLColsP[sk]->GetCstSegment(iseg), sz); break; case BaseDataTable::FloatField : icol++; FitsBlockRW::WriteColumnData(os, icol, l+1, 1, dobj->mFColsP[sk]->GetCstSegment(iseg), sz); break; case BaseDataTable::DoubleField : case BaseDataTable::DateTimeField : icol++; FitsBlockRW::WriteColumnData(os, icol, l+1, 1, dobj->mDColsP[sk]->GetCstSegment(iseg), sz); break; case BaseDataTable::ComplexField : if (tbltyp == BINARY_TBL) { icol++; FitsBlockRW< complex >::WriteColumnData(os, icol, l+1, 1, dobj->mYColsP[sk]->GetCstSegment(iseg), sz); } break; case BaseDataTable::DoubleComplexField : if (tbltyp == BINARY_TBL) { icol++; FitsBlockRW< complex >::WriteColumnData(os, icol, l+1, 1, dobj->mZColsP[sk]->GetCstSegment(iseg), sz); } break; case BaseDataTable::StringField : icol++; FitsBlockRW::WriteColumnData(os, icol, l+1, 1, dobj->mSColsP[sk]->GetCstSegment(iseg), sz); break; default: break; } } } // Ecriture de SegmentSize et autre elements de DVList os.WriteHeaderRecords(dobj->Info()); MuTyV mtv = dobj->SegmentSize(); os.WriteKey("SEGMSIZE",mtv," SOPHYA::DataTable SegmentSize"); mtv = "SOPHYA::DataTable"; os.WriteKey("SOPCLSNM",mtv," Object class name "); } DECL_TEMP_SPEC /* equivalent a template <> , pour SGI-CC en particulier */ void FitsHandler::Read(FitsInOutFile& is) { int hdutyp = is.CurrentHDUType(); if ( (hdutyp != BINARY_TBL ) && (hdutyp != ASCII_TBL) ) throw FitsIOException("FitsHandler::Read() Not a binary or ascii table HDU"); // Determination de la taille de segment sa_size_t segsz = is.GetNbRows() / 16; // Taille de segment par defaut if (segsz > 2048) segsz = 2048; string key = "SEGMSIZE"; bool knex = false; string ssegsz = is.KeyValue(key, knex); if (!knex && (ssegsz.length() > 0)) segsz = atoi(ssegsz.c_str()); if (segsz < 16) segsz = 16; // Nb de lignes et de colonnes vector colnames; vector coltypes; vector repcnt, width; vector colpos; is.GetColInfo(colnames, coltypes, repcnt, width); long nbrows = is.GetNbRows(); if (dobj == NULL) { // On cree la table si besoin string key = "SOPCLSNM"; string clsnm = is.KeyValue(key); if ( (clsnm == "SOPHYA::SwFitsDataTable") || (nbrows*colnames.size() < 10000000) ) dobj = new DataTable(segsz); else dobj = new SwFitsDataTable(is, segsz, false); } else { dobj->Clear(); // On efface la table sinon dobj->mSegSz = segsz; } // Type reel de table DataTable* dt = dynamic_cast< DataTable *> (dobj); SwFitsDataTable* swfdt = dynamic_cast< SwFitsDataTable *> (dobj); vector swpos; // Initialize the fits swap stream for SwFitsDataTable if necessary if (swfdt) { if ( swfdt->FitsSwapFile().FitsPtr() != is.FitsPtr() ) swfdt->FitsSwapFile().ShareFitsPtr(is); int_8 swp = 1; while (swp < nbrows) { swpos.push_back(swp); swp += segsz; } } // --ATTENTION-- repcnt (contenu=vecteur) pas pris en compte pour le moment for(sa_size_t k=0; kAddColRd(BaseDataTable::IntegerField, colnames[k], k+1, &swpos); else dobj->AddIntegerColumn(colnames[k]); colpos.push_back(k+1); break; case TUINT: case TLONG : case TULONG : #ifdef TLONGLONG case TLONGLONG : #endif if (swfdt) swfdt->AddColRd(BaseDataTable::LongField, colnames[k], k+1, &swpos); else dobj->AddLongColumn(colnames[k]); colpos.push_back(k+1); break; case TFLOAT : if (swfdt) swfdt->AddColRd(BaseDataTable::FloatField, colnames[k], k+1, &swpos); else dobj->AddFloatColumn(colnames[k]); colpos.push_back(k+1); break; case TDOUBLE : if (swfdt) swfdt->AddColRd(BaseDataTable::DoubleField, colnames[k], k+1, &swpos); else dobj->AddDoubleColumn(colnames[k]); colpos.push_back(k+1); break; case TCOMPLEX : if (swfdt) swfdt->AddColRd(BaseDataTable::ComplexField, colnames[k], k+1, &swpos); else dobj->AddComplexColumn(colnames[k]); colpos.push_back(k+1); break; case TDBLCOMPLEX : if (swfdt) swfdt->AddColRd(BaseDataTable::DoubleComplexField, colnames[k], k+1, &swpos); else dobj->AddDoubleComplexColumn(colnames[k]); colpos.push_back(k+1); break; case TSTRING : if (swfdt) swfdt->AddColRd(BaseDataTable::StringField, colnames[k], k+1, &swpos); else dobj->AddStringColumn(colnames[k]); colpos.push_back(k+1); break; default: cout << "FitsHandler::Read() NOT handled field type " << coltypes[k] << endl; break; } } // ------- Mise a jour des champs Nb d'entrees, nb segments ... dobj->mNEnt = is.GetNbRows(); // Lecture DVList (=entete FITS) is.GetHeaderRecords(dobj->Info()); // On ne doit pas lire les donnees de la table pour un SwFitsDataTable if (swfdt) return; while ((dobj->SegmentSize()*dobj->NbSegments()) < dobj->NEntry()) dobj->Extend(); //DBG cout << " DBG2 -- dobj->mNSeg = " << dobj->NbSegments() << " SegSize=" //DBG << dobj->SegmentSize() << " NEntry=" << dobj->NEntry() << endl; // Lecture des donnees des colonnes for(sa_size_t l=0; lNEntry(); l+=dobj->SegmentSize()) { sa_size_t icol = 0; sa_size_t sz = dobj->SegmentSize(); sa_size_t iseg = l/sz; if ((l+sz) > dobj->NEntry()) sz = dobj->NEntry()-l; for(sa_size_t k=0; kNVar(); k++) { sa_size_t sk = dobj->mNames[k].ser; icol = colpos[k]; // cout << " DBG-3 , k=" << k << " icol=" << icol << endl; switch ( dobj->GetColumType(k) ) { case BaseDataTable::IntegerField : FitsBlockRW::ReadColumnData(is, icol, l+1, 1, dobj->mIColsP[sk]->GetSegment(iseg), sz); break; case BaseDataTable::LongField : FitsBlockRW::ReadColumnData(is, icol, l+1, 1, dobj->mLColsP[sk]->GetSegment(iseg), sz); break; case BaseDataTable::FloatField : FitsBlockRW::ReadColumnData(is, icol, l+1, 1, dobj->mFColsP[sk]->GetSegment(iseg), sz); break; case BaseDataTable::DoubleField : case BaseDataTable::DateTimeField : FitsBlockRW::ReadColumnData(is, icol, l+1, 1, dobj->mDColsP[sk]->GetSegment(iseg), sz); break; case BaseDataTable::ComplexField : FitsBlockRW< complex >::ReadColumnData(is, icol, l+1, 1, dobj->mYColsP[sk]->GetSegment(iseg), sz); break; case BaseDataTable::DoubleComplexField : FitsBlockRW< complex >::ReadColumnData(is, icol, l+1, 1, dobj->mZColsP[sk]->GetSegment(iseg), sz); break; case BaseDataTable::StringField : FitsBlockRW::ReadColumnData(is, icol, l+1, 1, dobj->mSColsP[sk]->GetSegment(iseg), sz); break; default: break; } } } }