#include <stdcasa/StdCasa/CasacSupport.h> #include <casacore/casa/Arrays/ArrayMath.h> #include <casacore/casa/Exceptions/Error.h> #include <casacore/casa/Containers/Record.h> #include <casacore/casa/Containers/ValueHolder.h> #include <casacore/casa/Quanta/QuantumHolder.h> #include <casacore/casa/Quanta/MVAngle.h> #include <casacore/measures/Measures/MeasureHolder.h> #include <casacore/measures/Measures/MeasTable.h> #include <algorithm> using namespace casacore; namespace casa { Vector<String> toVectorString(const std::vector<std::string> &theVec){ Vector<String> b(theVec.size()); for(unsigned int i=0; i<theVec.size(); i++) b[i] = String(theVec[i]); return(b); } String toCasaString(const casac::variant& var){ String out; //Going around a bug of toString when its a string vector if(var.type()==::casac::variant::STRINGVEC){ Vector<String> outvec=toVectorString(var.toStringVec()); if(outvec.nelements() >0) out=outvec[0]; for (uInt k =1; k < outvec.nelements(); ++k){ out=out+String(",")+outvec[k]; } } else{ out=String(var.toString()); } // [] protection if (out.length()>1 && out.firstchar()=='[' && out.lastchar()==']') out = out.substr(1,out.length()-2); return out; } std::vector<string> fromVectorString(const Vector<String> &theVec){ std::vector<string> b(theVec.size()); for(unsigned int i=0; i<theVec.size(); i++) b[i] = theVec[i].c_str(); return(b); } casac::Quantity casacQuantity(const Quantity &quant){ casac::Quantity cquant(std::vector<double>(1,0.0), ""); cquant.value[0] = quant.getValue(); cquant.units = quant.getUnit().c_str(); return cquant; } Quantity casaQuantity(const casac::Quantity &cquant){ if(cquant.value.size() < 1) throw(AipsError("Bad quantity conversion")); return Quantity(cquant.value[0], Unit(cquant.units)); } Quantity casaQuantity(const casac::variant &theVar){ casacore::QuantumHolder qh; String error; // Strange "defaults" like BOOLVECs can come in are expected to go out as // 0.0. Therefore unhandled types should produce a default Quantity, not an // exception. Bool triedAndFailed = false; const ::casac::variant::TYPE theType = theVar.type(); if(theType == ::casac::variant::STRING || theType == ::casac::variant::STRINGVEC){ triedAndFailed = !qh.fromString(error, theVar.toString()); } else if(theType == ::casac::variant::RECORD){ //NOW the record has to be compatible with QuantumHolder::toRecord ::casac::variant localvar(theVar); // Because theVar is const. std::unique_ptr<Record> ptrRec(toRecord(localvar.asRecord())); triedAndFailed = !qh.fromRecord(error, *ptrRec); } else if(::casac::variant::compatible_type(theType, ::casac::variant::DOUBLE) == ::casac::variant::DOUBLE){ const casacore::Unit unitless("_"); // Dimensionless //qh = casacore::QuantumHolder(casacore::Quantity(const_cast<Double &>(const_cast<casac::variant &>(theVar).asDouble()), //unitless)); qh = casacore::QuantumHolder(casacore::Quantity(const_cast<Double &>(const_cast<casac::variant &>(theVar).asDouble()))); triedAndFailed = false; } else if(::casac::variant::compatible_type(theType, ::casac::variant::COMPLEX) == ::casac::variant::COMPLEX){ const casacore::Unit unitless("_"); // Dimensionless const casacore::Complex casaVal(const_cast<casac::variant &>(theVar).asComplex()); //qh = casacore::QuantumHolder(casacore::Quantum<casacore::Complex>(casaVal, //unitless)); qh = casacore::QuantumHolder(casacore::Quantum<casacore::Complex>(casaVal)); triedAndFailed = false; } if(triedAndFailed){ ostringstream oss; oss << "Error " << error << " in converting quantity"; throw(AipsError(oss.str())); } if(qh.isQuantum()){ // Remember casac::Quantity is a broader class return qh.asQuantity(); // than casacore::Quantity, so use qh.isQuantum(). } else{ // Probably variant's type was not handled above. casacore::Quantity retval; // Defaults to 0.0. return retval; } } Quantum<Vector<Double> > casaQuantumVector(const casac::variant& thevar){ Quantum<Vector<Double> > retval(Vector<Double> (), Unit("")); //For now we know (at least till we have more time) how to deal with records only if(thevar.type() != ::casac::variant::RECORD){ return retval; } ::casac::variant localvar(thevar); //cause its const std::unique_ptr<Record> ptrRec(toRecord(localvar.asRecord())); QuantumHolder qh; String error; if(qh.fromRecord(error, *ptrRec)){ try { if(qh.isQuantumVectorDouble()){ Quantum<Vector<Double> >retval1=qh.asQuantumVectorDouble(); return retval1; } } catch(...){ return retval; } } return retval; } Bool toCasaVectorQuantity(const ::casac::variant& theval, casacore::Vector<casacore::Quantity>& theQuants){ casacore::Vector<casacore::String> lesStrings; if (theval.type()== ::casac::variant::STRING){ sepCommaEmptyToVectorStrings(lesStrings, theval.toString()); } else if(theval.type()== ::casac::variant::STRINGVEC){ //Force resize as toStringVec sometimes give the wrong length (bug?) Vector<Int> leShape(theval.arrayshape()); lesStrings=toVectorString(theval.toStringVec()); lesStrings.resize(product(leShape), true); } casacore::QuantumHolder qh; String error; theQuants.resize(lesStrings.nelements()); for (uInt k=0; k < lesStrings.nelements(); ++k){ //Drat QuantumHolder does not handle pix if(lesStrings[k].contains("pix")){ lesStrings[k]=lesStrings[k].before("pix"); Double value=atof(lesStrings[k].chars()); theQuants[k]=casacore::Quantity(value, "pix"); } else{ if(!qh.fromString(error, lesStrings[k])){ ostringstream oss; oss << "Error " << error << " In converting quantity " << lesStrings[k]; throw( AipsError(oss.str())); } theQuants[k]=qh.asQuantity(); } } return true; } ::casac::record* recordFromQuantity(const Quantity q) { ::casac::record *r=0; try{ String error; Record R; if(QuantumHolder(q).toRecord(error, R)) r = fromRecord(R); else throw(AipsError("Could not convert quantity to record.")); } catch(AipsError x){ ostringstream oss; oss << "Exception Reported: " << x.getMesg(); RETHROW(x); } return r; } ::casac::record* recordFromQuantity(const Quantum<Vector<Double> >& q) { ::casac::record *r=0; try { String error; casacore::Record R; if(QuantumHolder(q).toRecord(error, R)) r = fromRecord(R); else throw(AipsError("Could not convert quantity to record.")); } catch(AipsError x){ ostringstream oss; oss << "Exception Reported: " << x.getMesg(); RETHROW(x); } return r; } /* * Note to self, asArrayDouble doesn't cut it. We'll have to do asType and convert element by element, * sigh..... */ ::casac::record *fromRecord(const Record &theRec){ ::casac::record *transcribedRec = new ::casac::record(); for(uInt i=0; i<theRec.nfields(); i++){ // std::cerr << theRec.name(i) << " " << theRec.dataType(i) << std::endl; switch(theRec.dataType(i)){ case TpBool : transcribedRec->insert(theRec.name(i).c_str(), theRec.asBool(i)); break; case TpChar : case TpUChar : transcribedRec->insert(theRec.name(i).c_str(), long(theRec.asuChar(i))); break; case TpShort : case TpUShort : transcribedRec->insert(theRec.name(i).c_str(), long(theRec.asShort(i))); break; case TpUInt : transcribedRec->insert(theRec.name(i).c_str(), (unsigned long) theRec.asuInt(i)); break; case TpInt : transcribedRec->insert(theRec.name(i).c_str(), long(theRec.asInt(i))); break; case TpInt64 : { casac::variant val((long)theRec.asInt64(i)); transcribedRec->insert(theRec.name(i).c_str(), val); } break; case TpFloat : transcribedRec->insert(theRec.name(i).c_str(), double(theRec.asFloat(i))); break; case TpDouble : transcribedRec->insert(theRec.name(i).c_str(), theRec.asDouble(i)); break; case TpComplex : transcribedRec->insert(theRec.name(i).c_str(), DComplex(theRec.asComplex(i))); break; case TpDComplex : transcribedRec->insert(theRec.name(i).c_str(), theRec.asDComplex(i)); break; case TpString : transcribedRec->insert(theRec.name(i).c_str(), theRec.asString(i)); break; case TpTable : transcribedRec->insert(theRec.name(i).c_str(), theRec.asString(i)); break; case TpArrayBool : { Array<Bool> tmpArray = theRec.asArrayBool(i); //Vector<ssize_t> tmpShape = (tmpArray.shape()).asVector(); Vector<ssize_t> tmpShape(tmpArray.shape( ).begin( ),tmpArray.shape( ).end( )); //std::cerr << "Vector Shape " << tmpShape << std::endl; std::vector<ssize_t> vecShape; tmpShape.tovector(vecShape); //std::cerr << "vector shape "; //for(int i=0;i<vecShape.size();i++) //std::cerr << vecShape[i] << " "; //std::cerr << std::endl; std::vector<bool> tmpVec; tmpArray.tovector(tmpVec); transcribedRec->insert(theRec.name(i).c_str(), casac::variant(tmpVec, vecShape)); } break; case TpArrayChar : case TpArrayUChar : case TpArrayShort : case TpArrayUShort : case TpArrayInt : { Array<int> tmpArray = theRec.asArrayInt(i); Vector<Int> tmpShape = (tmpArray.shape()).asVector(); std::vector<ssize_t> vecShape(tmpShape.begin(),tmpShape.end()); std::vector<long> tmpVec; std::for_each( tmpArray.begin( ), tmpArray.end( ), [&](int v){tmpVec.push_back((long)v);} ); transcribedRec->insert(theRec.name(i).c_str(), casac::variant(tmpVec, vecShape)); } break; case TpArrayUInt : { Array<uInt> tmpArray = theRec.asArrayuInt(i); Vector<Int> tmpShape = (tmpArray.shape()).asVector(); std::vector<ssize_t> vecShape(tmpShape.begin( ),tmpShape.end( )); std::vector<unsigned long> tmpVec; std::for_each( tmpArray.begin( ), tmpArray.end( ), [&](uInt v){tmpVec.push_back((unsigned long)v);} ); transcribedRec->insert(theRec.name(i).c_str(), casac::variant(tmpVec, vecShape)); } break; case TpArrayInt64 : { Array<Int64> tmpArray = theRec.asArrayInt64(i); Vector<Int> tmpShape = (tmpArray.shape()).asVector(); std::vector<ssize_t> vecShape(tmpShape.begin( ),tmpShape.end( )); std::vector<long> tmpVec(tmpArray.begin(),tmpArray.end()); transcribedRec->insert(theRec.name(i).c_str(), casac::variant(tmpVec, vecShape)); } break; case TpArrayFloat : { Array<Float> tmpArray = theRec.asArrayFloat(i); Vector<Int> tmpShape = (tmpArray.shape()).asVector(); //std::cerr << "Vector Shape " << tmpShape << std::endl; std::vector<ssize_t> vecShape(tmpShape.begin( ),tmpShape.end( )); std::vector<Float> tmpVec; tmpArray.tovector(tmpVec); std::vector<Double> dtmpVec(tmpVec.size()); for(unsigned int j=0;j<tmpVec.size();j++) dtmpVec[j] = tmpVec[j]; transcribedRec->insert(theRec.name(i).c_str(), casac::variant(dtmpVec, vecShape)); } break; case TpArrayDouble : { Array<Double> tmpArray = theRec.asArrayDouble(i); Vector<Int> tmpShape = (tmpArray.shape()).asVector(); //std::cerr << "Vector Shape " << tmpShape << std::endl; std::vector<ssize_t> vecShape(tmpShape.begin( ),tmpShape.end( )); std::vector<Double> tmpVec; tmpArray.tovector(tmpVec); transcribedRec->insert(theRec.name(i).c_str(), casac::variant(tmpVec, vecShape)); } break; case TpArrayComplex : { Array<casacore::Complex> tmpArray = theRec.asArrayComplex(i); Vector<Int> tmpShape = (tmpArray.shape()).asVector(); std::vector<ssize_t> vecShape(tmpShape.begin( ),tmpShape.end( )); std::vector<casacore::Complex> tmpVec; tmpArray.tovector(tmpVec); std::vector<std::complex<double> > dtmpVec(tmpVec.size()); for(unsigned int j=0;j<tmpVec.size();j++) dtmpVec[j] = tmpVec[j]; transcribedRec->insert(theRec.name(i).c_str(), casac::variant(dtmpVec, vecShape)); } break; case TpArrayDComplex : { Array<DComplex> tmpArray = theRec.asArrayDComplex(i); Vector<Int> tmpShape = (tmpArray.shape()).asVector(); std::vector<ssize_t> vecShape(tmpShape.begin( ),tmpShape.end( )); std::vector<DComplex> tmpVec; tmpArray.tovector(tmpVec); std::vector<std::complex <double> > dtmpVec(tmpVec.size()); for(unsigned int j=0;j<tmpVec.size();j++) dtmpVec[j] = tmpVec[j]; transcribedRec->insert(theRec.name(i).c_str(), casac::variant(dtmpVec, vecShape)); } break; case TpArrayString : { Array<String> tmpArray = theRec.asArrayString(i); Vector<Int> tmpShape = (tmpArray.shape()).asVector(); std::vector<ssize_t> vecShape(tmpShape.begin( ),tmpShape.end( )); std::vector<casacore::String> tmpVec; tmpArray.tovector(tmpVec); std::vector<std::string> dtmpVec(tmpVec.size()); for(unsigned int j=0;j<tmpVec.size();j++) dtmpVec[j] = tmpVec[j].c_str(); transcribedRec->insert(theRec.name(i).c_str(), casac::variant(dtmpVec, vecShape)); } break; case TpRecord : { //std::cerr << "fromRecord is Record" << std::endl; casac::record *dummy = fromRecord(theRec.asRecord(i)); casac::variant dum2(dummy); transcribedRec->insert(theRec.name(i).c_str(), dum2); } break; case TpOther : std::cerr << "casac::fromRecord TpOther, oops" << std::endl; break; case TpQuantity : std::cerr << "casac::fromRecord TpQuantity, oops" << std::endl; break; case TpArrayQuantity : std::cerr << "casac::fromRecord TpArrayQuantity, oops" << std::endl; break; default : std::cerr << "casac::fromRecord unknown type, oops" << std::endl; break; } } return transcribedRec; } Record *toRecord(const ::casac::record &theRec){ Record *transcribedRec = new Record(); casac::rec_map::const_iterator rec_end = theRec.end(); for(::casac::rec_map::const_iterator rec_it = theRec.begin(); rec_it != rec_end; ++rec_it){ //std::cerr << (*rec_it).first << " type is: " << (*rec_it).second.type() << std::endl; switch((*rec_it).second.type()){ case ::casac::variant::RECORD : { std::unique_ptr<Record> tmpRecord(toRecord((*rec_it).second.getRecord())); transcribedRec->defineRecord(RecordFieldId((*rec_it).first), *tmpRecord); } break; case ::casac::variant::BOOL : {transcribedRec->define(RecordFieldId((*rec_it).first), (*rec_it).second.toBool());} break; case ::casac::variant::INT : {transcribedRec->define(RecordFieldId((*rec_it).first), Int((*rec_it).second.getInt()));} break; case ::casac::variant::UINT : {transcribedRec->define(RecordFieldId((*rec_it).first), Int((*rec_it).second.getuInt()));} break; case ::casac::variant::DOUBLE : transcribedRec->define(RecordFieldId((*rec_it).first), (*rec_it).second.getDouble()); break; case ::casac::variant::COMPLEX : transcribedRec->define(RecordFieldId((*rec_it).first), (*rec_it).second.getComplex()); break; case ::casac::variant::STRING : transcribedRec->define(RecordFieldId((*rec_it).first), (*rec_it).second.getString()); break; case ::casac::variant::BOOLVEC : { Vector<Int> shapeVec((*rec_it).second.arrayshape()); Vector<Bool>boolVec((*rec_it).second.getBoolVec()); IPosition tshape(shapeVec); Array<Bool> boolArr(tshape); int i(0); Array<Bool>::iterator boolArrend = boolArr.end(); for(Array<Bool>::iterator iter = boolArr.begin(); iter != boolArrend; ++iter) *iter = boolVec[i++]; transcribedRec->define(RecordFieldId((*rec_it).first), boolArr); } break; case ::casac::variant::INTVEC : { Vector<Int> shapeVec((*rec_it).second.arrayshape()); Vector<Int> intVec((*rec_it).second.getIntVec()); IPosition tshape(shapeVec); Array<Int> intArr(tshape); int i(0); Array<Int>::iterator intArrend = intArr.end(); for(Array<Int>::iterator iter = intArr.begin(); iter != intArrend; ++iter) *iter = intVec[i++]; transcribedRec->define(RecordFieldId((*rec_it).first), intArr); } break; case ::casac::variant::UINTVEC : { Vector<Int> shapeVec((*rec_it).second.arrayshape()); Vector<uInt> uintVec((*rec_it).second.getuIntVec()); IPosition tshape(shapeVec); Array<uInt> intArr(tshape); int i(0); Array<uInt>::iterator intArrend = intArr.end(); for(Array<uInt>::iterator iter = intArr.begin(); iter != intArrend; ++iter) *iter = uintVec[i++]; transcribedRec->define(RecordFieldId((*rec_it).first), intArr); } break; case ::casac::variant::DOUBLEVEC : { Vector<Double> doubleVec((*rec_it).second.getDoubleVec()); Vector<Int> shapeVec((*rec_it).second.arrayshape()); IPosition tshape(shapeVec); Array<Double> doubleArr(tshape); int i(0); Array<Double>::iterator doubleArrEnd = doubleArr.end(); for(Array<Double>::iterator iter = doubleArr.begin(); iter != doubleArrEnd; ++iter) *iter = doubleVec[i++]; transcribedRec->define(RecordFieldId((*rec_it).first), doubleArr); } break; case ::casac::variant::COMPLEXVEC : { Vector<DComplex> complexVec((*rec_it).second.getComplexVec()); Vector<Int> shapeVec((*rec_it).second.arrayshape()); IPosition tshape(shapeVec); Array<DComplex> complexArr(tshape); Array<DComplex>::iterator complexArrEnd = complexArr.end(); int i(0); for(Array<DComplex>::iterator iter = complexArr.begin(); iter != complexArrEnd; ++iter) *iter = complexVec[i++]; transcribedRec->define(RecordFieldId((*rec_it).first), complexArr); } break; case ::casac::variant::STRINGVEC : { Vector<Int> shapeVec((*rec_it).second.arrayshape()); std::vector<std::string> tmp = (*rec_it).second.getStringVec(); const Array<String> &stringArr(toVectorString(tmp)); //stringArr.reform(IPosition(shapeVec)); transcribedRec->define(RecordFieldId((*rec_it).first), stringArr); //transcribedRec->define((*rec_it).first, Vector<String>((*rec_it).second.getStringVec())); } break; default : std::cerr << "Unknown type: " << (*rec_it).second.type() << std::endl; break; } } return transcribedRec; } casac::variant *fromValueHolder(const ValueHolder &theVH){ casac::variant *theV(0); if(!theVH.isNull()){ switch(theVH.dataType()){ case TpBool : theV = new casac::variant(theVH.asBool()); break; case TpUChar : theV = new casac::variant((long)theVH.asuChar()); break; case TpShort : theV = new casac::variant((long)theVH.asShort()); break; case TpUShort : theV = new casac::variant((long)theVH.asuShort()); break; case TpInt : theV = new casac::variant((long)theVH.asInt()); break; case TpUInt : theV = new casac::variant((unsigned long)theVH.asuInt()); break; case TpInt64 : theV = new casac::variant((long)theVH.asInt64()); break; case TpFloat : theV = new casac::variant(theVH.asFloat()); break; case TpDouble : theV = new casac::variant(theVH.asDouble()); break; case TpComplex : theV = new casac::variant(theVH.asComplex()); break; case TpDComplex : theV = new casac::variant(theVH.asDComplex()); break; case TpString : theV = new casac::variant(theVH.asString().c_str()); break; case TpArrayBool : { Array<Bool> tArr(theVH.asArrayBool()); Vector<Int> ts = tArr.shape().asVector(); std::vector<ssize_t> tShape(ts.begin( ),ts.end( )); std::vector<bool> tData; tArr.tovector(tData); theV = new casac::variant(tData, tShape); } break; case TpArrayUChar : { Array<uChar> tArr(theVH.asArrayuChar()); Vector<Int> ts = tArr.shape().asVector(); std::vector<ssize_t> tShape(ts.begin( ),ts.end( )); std::vector<uChar> tData; tArr.tovector(tData); std::vector<long> tD(tData.size()); for(unsigned int i=0;i<tData.size();i++) tD[i] = tData[i]; theV = new casac::variant(tD, tShape); } break; case TpArrayShort : { Array<Short> tArr(theVH.asArrayShort()); Vector<Int> ts = tArr.shape().asVector(); std::vector<ssize_t> tShape(ts.begin( ),ts.end( )); std::vector<Short> tData; tArr.tovector(tData); std::vector<long> tD(tData.size()); for(unsigned int i=0;i<tData.size();i++) tD[i] = tD[i]; theV = new casac::variant(tD, tShape); } break; case TpArrayUShort : { Array<uShort> tArr(theVH.asArrayuShort()); Vector<Int> ts = tArr.shape().asVector(); std::vector<ssize_t> tShape(ts.begin( ),ts.end( )); std::vector<uShort> tData; tArr.tovector(tData); std::vector<long> tD(tData.size()); for(unsigned int i=0;i<tData.size();i++) tD[i] = tData[i]; theV = new casac::variant(tD, tShape); } break; case TpArrayInt : { Array<Int> tArr(theVH.asArrayInt()); Vector<Int> ts = tArr.shape().asVector(); //std::cerr << "Vector Shape " << ts << std::endl; std::vector<ssize_t> tShape(ts.begin( ),ts.end( )); std::vector<long> tData; std::for_each( tArr.begin( ), tArr.end( ), [&](Int v){tData.push_back((long)v);} ); theV = new casac::variant(tData, tShape); } break; case TpArrayUInt : { Array<uInt> tArr(theVH.asArrayuInt()); Vector<Int> ts = tArr.shape().asVector(); std::vector<ssize_t> tShape(ts.begin( ),ts.end( )); std::vector<unsigned long> tData; std::for_each( tArr.begin( ), tArr.end( ), [&](Int v){tData.push_back((unsigned long)v);} ); theV = new casac::variant(tData, tShape); } break; case TpArrayFloat : { Array<Float> tArr(theVH.asArrayFloat()); Vector<Int> ts = tArr.shape().asVector(); //std::cerr << ts << std::endl; //std::cerr << "Vector Shape " << ts << std::endl; std::vector<ssize_t> tShape(ts.begin( ),ts.end( )); std::vector<float> tData; tArr.tovector(tData); std::vector<double> tD(tData.size()); for(unsigned int i=0;i<tData.size();i++) tD[i] = tData[i]; theV = new casac::variant(tD, tShape); } break; case TpArrayDouble : { Array<Double> tArr(theVH.asArrayDouble()); Vector<Int> ts = tArr.shape().asVector(); //std::cerr << "Vector Shape " << ts << std::endl; std::vector<ssize_t> tShape(ts.begin( ),ts.end( )); std::vector<double> tData; tArr.tovector(tData); theV = new casac::variant(tData, tShape); } break; case TpArrayComplex : { Array<Complex> tArr(theVH.asArrayComplex()); Vector<Int> ts = tArr.shape().asVector(); std::vector<ssize_t> tShape(ts.begin( ),ts.end( )); std::vector<std::complex<float> > tData; tArr.tovector(tData); std::vector<std::complex<double> > tD(tData.size()); for(unsigned int i=0;i<tData.size();i++) tD[i] = tData[i]; theV = new casac::variant(tD, tShape); } break; case TpArrayDComplex : { Array<DComplex> tArr(theVH.asArrayDComplex()); Vector<Int> ts = tArr.shape().asVector(); std::vector<ssize_t> tShape(ts.begin( ),ts.end( )); std::vector<std::complex<double> > tData; tArr.tovector(tData); theV = new casac::variant(tData, tShape); } break; case TpArrayString : { // Truly ugly... Array<String> tArr(theVH.asArrayString()); Vector<Int> ts = tArr.shape().asVector(); std::vector<ssize_t> tShape(ts.begin( ),ts.end( )); std::vector<String> tData; tArr.tovector(tData); std::vector<string> tData2(tData.size()); for(unsigned int i=0; i<tData.size(); i++) tData2[i] = tData[i].c_str(); theV = new casac::variant(tData2, tShape); } break; case TpRecord : theV = new casac::variant(fromRecord(theVH.asRecord())); break; default : throw(AipsError("Unknown casa DataType!")); break; } } return theV; } // I have some doubts about this, we may need to avoid the const ness of the variant // if we run into some speed issues. // ValueHolder *toValueHolder(const casac::variant &theV){ ValueHolder *theVH(0); std::unique_ptr<Record> tmpRec; switch(theV.type()){ case casac::variant::RECORD : tmpRec.reset(toRecord(theV.getRecord())); theVH = new ValueHolder(*tmpRec); break; case casac::variant::BOOL : theVH = new ValueHolder(theV.getBool()); break; case casac::variant::INT : /*** need range check ***/ theVH = new ValueHolder((int)theV.getInt()); break; case casac::variant::DOUBLE : theVH = new ValueHolder(theV.getDouble()); break; case casac::variant::COMPLEX : theVH = new ValueHolder(theV.getComplex()); break; case casac::variant::STRING : theVH = new ValueHolder(theV.getString()); break; case casac::variant::BOOLVEC : { Vector<Bool> boolVec(theV.getBoolVec()); Vector<Int>shapeVec(theV.arrayshape()); IPosition tshape(shapeVec); Array<Bool> tVec(tshape); int i(0); Array<Bool>::iterator tVecEnd = tVec.end(); for(Array<Bool>::iterator iter = tVec.begin(); iter != tVecEnd; ++iter) *iter = boolVec[i++]; theVH = new ValueHolder(tVec); } break; case casac::variant::INTVEC : { Vector<Int> intVec(theV.getIntVec()); Vector<Int>shapeVec(theV.arrayshape()); IPosition tshape(shapeVec); Array<Int> tVec(tshape); int i(0); Array<Int>::iterator tVecEnd = tVec.end(); for(Array<Int>::iterator iter = tVec.begin(); iter != tVecEnd; ++iter) *iter = intVec[i++]; theVH = new ValueHolder(tVec); } break; case casac::variant::DOUBLEVEC : { Vector<Double> doubleVec(theV.getDoubleVec()); Vector<Int>shapeVec(theV.arrayshape()); IPosition tshape(shapeVec); Array<Double> tVec(tshape); Array<Double>::iterator tVecEnd = tVec.end(); int i(0); for(Array<Double>::iterator iter = tVec.begin(); iter != tVecEnd; ++iter) *iter = doubleVec[i++]; theVH = new ValueHolder(tVec); } break; case casac::variant::COMPLEXVEC : { Vector<DComplex> complexVec(theV.getComplexVec()); Vector<Int>shapeVec(theV.arrayshape()); IPosition tshape(shapeVec); Array<DComplex> tVec(tshape); Array<DComplex>::iterator tVecEnd = tVec.end(); int i(0); for(Array<DComplex>::iterator iter = tVec.begin(); iter != tVecEnd; ++iter) *iter = complexVec[i++]; theVH = new ValueHolder(tVec); } break; case casac::variant::STRINGVEC : // Unclear whether this may leak { std::vector<std::string> tmp = theV.getStringVec(); Vector<String> stringArr(toVectorString(tmp)); Vector<Int>shapeVec(theV.arrayshape()); IPosition tshape(shapeVec); Array<String> tVec(tshape); int i(0); Array<String>::iterator tVecEnd = tVec.end(); for(Array<String>::iterator iter = tVec.begin(); iter != tVecEnd; ++iter) *iter = stringArr[i++]; theVH = new ValueHolder(tVec); } break; default : throw(AipsError("Unknown variant type!")); break; } return theVH; } Bool casaMDirection(const ::casac::variant& theVar, MDirection& theMeas){ casacore::MeasureHolder mh; casacore::QuantumHolder qh; String error; if(theVar.type()== ::casac::variant::RECORD){ ::casac::variant localvar(theVar); //cause its const std::unique_ptr<Record> ptrRec(toRecord(localvar.asRecord())); if(mh.fromRecord(error, *ptrRec)){ theMeas=mh.asMDirection(); return true; } else{ ostringstream oss; oss << "Error " << error << " in converting Direction parameter"; throw( AipsError(oss.str())); return false; } } if(theVar.type()== ::casac::variant::STRING || theVar.type()== ::casac::variant::STRINGVEC){ Vector<String> str; //In case of compound strings with commas or empty space if (theVar.type()== ::casac::variant::STRING){ sepCommaEmptyToVectorStrings(str, theVar.toString()); } else{ str=toVectorString(theVar.toStringVec()); } if(str.nelements()==3){ qh.fromString(error, str[1]); casacore::Quantity val1=qh.asQuantity(); qh.fromString(error, str[2]); casacore::Quantity val2=qh.asQuantity(); if(val2.getFullUnit()==Unit("deg") && str[2].contains(":")){ ostringstream oss; oss << "NOTE: you provided the Declination/Latitude value \""<< str[2] << "\" which is understood to be in units of hours.\n" << " If you meant degrees, please replace \":\" by \".\"."; cerr << oss.str() << endl; } MDirection::Types tp; if(!MDirection::getType(tp, str[0])){ ostringstream oss; oss << "Could not understand Direction frame...defaulting to J2000 " ; cerr << oss.str() << endl; tp=MDirection::J2000; } theMeas=MDirection(val1,val2, tp); return true; } else if(str.nelements()==2){ qh.fromString(error, str[0]); casacore::Quantity val1=qh.asQuantity(); qh.fromString(error, str[1]); casacore::Quantity val2=qh.asQuantity(); if(val2.getFullUnit()==Unit("deg") && str[1].contains(":")){ ostringstream oss; oss << "NOTE: you provided the Declination/Latitude value \""<< str[2] << "\" which is understood to be in units of hours.\n" << " If you meant degrees, please replace \":\" by \".\"."; cerr << oss.str() << endl; } theMeas=MDirection(val1, val2); return true; } else if(str.nelements()==1){ //Must be a string like sun, moon, jupiter casacore::Quantity val1(0.0, "deg"); casacore::Quantity val2(90.0, "deg"); theMeas=MDirection(val1, val2); MDirection::Types ref; Int numAll; Int numExtra; const uInt *dum; const String *allTypes=MDirection::allMyTypes(numAll, numExtra, dum); //if it is SUN moon etc if(MDirection::getType(ref,str[0])){ theMeas=MDirection(val1, val2, ref); return true; } if(MeasTable::Source(theMeas, str[0])){ return true; } if(!MDirection::getType(ref, str[0])){ Vector<String> all(numExtra); for(Int k =0; k < numExtra; ++k){ all[k]=*(allTypes+numAll-k-1); } ostringstream oss; oss << "Could not understand Direction string " <<str[0] << "\n" ; oss << "Valid ones are " << all; cerr << oss.str() << " or one of the valid known sources in the data repos" << endl; theMeas=MDirection(val1, val2); return false; } } } ///If i am here i don't know how to interprete this return false; } //Bool ang_as_formatted_str(string& out, const casacore::Quantity& qang, // const std::string& format) //{ // return ang_as_formatted_str(out,qang,format,precision=2); //} Bool ang_as_formatted_str(string& out, const casacore::Quantity& qang, const std::string& format, const Int precision=2) { Bool retval = true; try{ //hms, dms, deg, rad, +deg. casacore::String form(format); form.downcase(); Int ndig=6+precision; MVAngle ang(qang); if(form == "dms"){ out = ang(-0.5).string(MVAngle::ANGLE, ndig+1).c_str(); } else if(form == "hms"){ out = ang.string(MVAngle::TIME, ndig).c_str(); } else if(form == "deg"){ ostringstream os; os << ang().degree(); out = os.str(); } else if(form == "rad"){ ostringstream os; os << ang().radian(); out = os.str(); } else if(form == "+deg"){ ostringstream os; os << ang(0.0).degree(); out = os.str(); } else{ retval = false; // Format not understood - return false instead of // throwing an exception. } } catch(AipsError x){ retval = false; RETHROW(x); } return retval; } Bool MDirection2str(const MDirection& in, std::string& out) { Quantum<Vector<Double> > lonlat(in.getAngle()); Vector<Double> lonlatval(lonlat.getValue()); Unit inunit(lonlat.getUnit()); string refcode(in.getRefString()); casacore::Quantity qlon(lonlatval[0], inunit); casacore::Quantity qlat(lonlatval[1], inunit); string lon(""); string lat(""); Bool success; if(refcode == "J2000" || refcode[0] == 'B'){ success = ang_as_formatted_str(lon, qlon, "hms", 2); success = success && ang_as_formatted_str(lat, qlat, "dms", 2); } else{ success = ang_as_formatted_str(lon, qlon, "deg", 2); success = success && ang_as_formatted_str(lat, qlat, "deg", 2); } if(success) out = refcode + " " + lon + " " + lat; return success; } Bool casaMFrequency(const ::casac::variant& theVar, MFrequency& theMeas){ casacore::MeasureHolder mh; casacore::QuantumHolder qh; String error; if(theVar.type()== ::casac::variant::RECORD){ ::casac::variant localvar(theVar); //cause its const std::unique_ptr<Record> ptrRec(toRecord(localvar.asRecord())); if(mh.fromRecord(error, *ptrRec)){ theMeas=mh.asMFrequency(); return true; } else{//could be a quantity if(qh.fromRecord(error, *ptrRec)){ theMeas=MFrequency(qh.asQuantity()); return true; } else{ ostringstream oss; oss << "Error " << error << "In converting Frequency parameter"; throw( AipsError(oss.str())); return false; } } } if(theVar.type()== ::casac::variant::STRING || theVar.type()== ::casac::variant::STRINGVEC){ Vector<String> str; if (theVar.type()== ::casac::variant::STRING){ sepCommaEmptyToVectorStrings(str, theVar.toString()); } else{ str=toVectorString(theVar.toStringVec()); } if(str.nelements()==2){ qh.fromString(error, str[1]); casacore::Quantity val=qh.asQuantity(); MFrequency::Types tp; if(!MFrequency::getType(tp, str[0])){ cerr << "Could not understand frequency frame..defaulting to LSRK " << endl; tp=MFrequency::LSRK; qh.fromString(error, str[0]+str[1]); val=qh.asQuantity(); } theMeas=MFrequency(val, tp); return true; } else if(str.nelements()==1){ if(str[0]=="") return false; qh.fromString(error, str[0]); theMeas=MFrequency(qh.asQuantity()); return true; } } ///If i am here then it can be an integer or double then using Hz theMeas=MFrequency(casacore::Quantity(theVar.toDouble(), "Hz")); return true; } Bool casaMPosition(const ::casac::variant& theVar, MPosition& theMeas){ casacore::MeasureHolder mh; casacore::QuantumHolder qh; String error; if(theVar.type()== ::casac::variant::RECORD){ ::casac::variant localvar(theVar); //cause its const std::unique_ptr<Record> ptrRec(toRecord(localvar.asRecord())); if(mh.fromRecord(error, *ptrRec)){ theMeas=mh.asMPosition(); return true; } else{ ostringstream oss; oss << "Error " << error << "In converting Position parameter"; throw( AipsError(oss.str())); return false; } } if(theVar.type()== ::casac::variant::STRING || theVar.type()== ::casac::variant::STRINGVEC){ Vector<String> str; if (theVar.type()== ::casac::variant::STRING){ sepCommaEmptyToVectorStrings(str, theVar.toString()); } else{ str=toVectorString(theVar.toStringVec()); } if(str.nelements()==4){ qh.fromString(error, str[1]); casacore::Quantity val1=qh.asQuantity(); qh.fromString(error, str[2]); casacore::Quantity val2=qh.asQuantity(); qh.fromString(error, str[3]); casacore::Quantity val3=qh.asQuantity(); MPosition::Types tp; if(!MPosition::getType(tp, str[0])){ cerr << "Could not understand Position frame...defaulting to ITRF" << endl; tp=MPosition::ITRF; } theMeas=MPosition(val1, val2, val3, tp); return true; } else if(str.nelements()==3){ qh.fromString(error, str[0]); casacore::Quantity val1=qh.asQuantity(); qh.fromString(error, str[1]); casacore::Quantity val2=qh.asQuantity(); qh.fromString(error, str[2]); casacore::Quantity val3=qh.asQuantity(); theMeas=MPosition(val1, val2, val3); return true; } else if(str.nelements()==1){ //must be an observatory string hopefully str[0].upcase(); if(casacore::MeasTable::Observatory(theMeas, str[0])){ return true; } else{ throw( AipsError("Could not understand Position parameter")); return false; } } } ///If i am here i don't know how to interprete this return false; } Bool casaMRadialVelocity(const ::casac::variant& theVar, MRadialVelocity& theMeas){ casacore::MeasureHolder mh; casacore::QuantumHolder qh; String error; if(theVar.type()== ::casac::variant::RECORD){ ::casac::variant localvar(theVar); //cause its const std::unique_ptr<Record> ptrRec(toRecord(localvar.asRecord())); if(mh.fromRecord(error, *ptrRec)){ theMeas=mh.asMRadialVelocity(); return true; } else{//could be a quantity if(qh.fromRecord(error, *ptrRec)){ theMeas=MRadialVelocity(qh.asQuantity()); return true; } else{ ostringstream oss; oss << "Error " << error << "In converting Radial velocity parameter"; throw( AipsError(oss.str())); return false; } } } if(theVar.type()== ::casac::variant::STRING || theVar.type()== ::casac::variant::STRINGVEC){ Vector<String> str; if (theVar.type()== ::casac::variant::STRING){ sepCommaEmptyToVectorStrings(str, theVar.toString()); } else{ str=toVectorString(theVar.toStringVec()); } if(str.nelements()==2){ qh.fromString(error, str[1]); casacore::Quantity val=qh.asQuantity(); MRadialVelocity::Types tp; if(!MRadialVelocity::getType(tp, str[0])){ cerr << "Could not understand velocity frame..defaulting to LSRK " << endl; tp=MRadialVelocity::LSRK; } theMeas=MRadialVelocity(val, tp); return true; } else if(str.nelements()==1){ if(str[0]=="") return false; qh.fromString(error, str[0]); theMeas=MRadialVelocity(qh.asQuantity()); return true; } } ///If i am here then it can be an integer or double then using m/s theMeas=MRadialVelocity(casacore::Quantity(theVar.toDouble(), "m/s")); return true; } Bool casaMEpoch(const ::casac::variant& theVar, MEpoch& theMeas){ casacore::MeasureHolder mh; casacore::QuantumHolder qh; String error; if(theVar.type()== ::casac::variant::RECORD){ ::casac::variant localvar(theVar); //cause its const std::unique_ptr<Record> ptrRec(toRecord(localvar.asRecord())); if(mh.fromRecord(error, *ptrRec)){ theMeas=mh.asMEpoch(); return true; } else{//could be a quantity if(qh.fromRecord(error, *ptrRec)){ theMeas=MEpoch(qh.asQuantity()); return true; } else{ ostringstream oss; oss << "Error " << error << "In converting Epoch parameter"; throw( AipsError(oss.str())); return false; } } } if(theVar.type()== ::casac::variant::STRING || theVar.type()== ::casac::variant::STRINGVEC){ Vector<String> str; if (theVar.type()== ::casac::variant::STRING){ sepCommaEmptyToVectorStrings(str, theVar.toString()); } else{ str=toVectorString(theVar.toStringVec()); } if(str.nelements()==2){ qh.fromString(error, str[1]); casacore::Quantity val=qh.asQuantity(); MEpoch::Types tp; if(!MEpoch::getType(tp, str[0])){ cerr << "Could not understand epoch frame...defaulting to UTC " << endl; tp=MEpoch::UTC; } theMeas=MEpoch(val, tp); return true; } else if(str.nelements()==1){ if(str[0]=="") return false; qh.fromString(error, str[0]); theMeas=MEpoch(qh.asQuantity()); return true; } } ///If i am here then it can be an integer or double then using days theMeas=MEpoch(casacore::Quantity(theVar.toDouble(), "d")); return true; } Int sepCommaEmptyToVectorStrings(Vector<String>& lesStrings, const std::string& str){ casacore::String oneStr=String(str); Int nsep=0; // decide if its comma seperated or empty space seperated casacore::String sep; if((nsep=oneStr.freq(",")) > 0){ sep=","; } else { nsep=oneStr.freq(" "); sep=" "; } if(nsep == 0){ lesStrings.resize(1); lesStrings=oneStr; nsep=1; } else{ String *splitstrings = new String[nsep+1]; nsep=split(oneStr, splitstrings, nsep+1, sep); lesStrings.resize(nsep); Int index=0; for (Int k=0; k < nsep; ++k){ if((String(splitstrings[k]) == String("")) || (String(splitstrings[k]) == String(" "))){ lesStrings.resize(lesStrings.nelements()-1, true); } else{ lesStrings[index]=splitstrings[k]; ++index; } } delete [] splitstrings; } return nsep; } Int sepCommaToVectorStrings(Vector<String>& lesStrings, const std::string& str){ casacore::String oneStr=String(str); // decide if its comma seperated or empty space seperated String sep=","; Int nsep=oneStr.freq(sep); if(nsep == 0){ lesStrings.resize(1); lesStrings=oneStr; nsep=1; } else{ String *splitstrings = new String[nsep+1]; nsep=split(oneStr, splitstrings, nsep+1, sep); lesStrings.resize(nsep); Int index=0; for (Int k=0; k < nsep; ++k){ if((String(splitstrings[k]) == String("")) || (String(splitstrings[k]) == String(" "))){ lesStrings.resize(lesStrings.nelements()-1, true); } else{ lesStrings[index]=splitstrings[k]; ++index; } } delete [] splitstrings; } return nsep; } vector<double> toVectorDouble(const casac::variant& v, const String& varName) { vector<double> ret(0); switch (v.type()) { case casac::variant::BOOLVEC: return ret; case casac::variant::INT: case casac::variant::DOUBLE: ret.push_back(v.toDouble()); return ret; case casac::variant::INTVEC: case casac::variant::DOUBLEVEC: return v.toDoubleVec(); case casac::variant::STRING: if (v.toString().size() > 0) { throw AipsError(varName + " cannot be a non-empty string"); } else { return ret; } default: ostringstream os; os << "Illegal type for " << varName << ": " << v.type(); throw AipsError(os.str()); } } vector<string> toVectorString(const ::casac::variant& v, const String& varName) { vector<string> ret(0); switch (v.type()) { case casac::variant::BOOLVEC: return ret; case casac::variant::STRING: if (v.toString().size() > 0) { ret.push_back(v.toString()); } return ret; case casac::variant::STRINGVEC: return v.toStringVec(); default: ostringstream os; os << "Illegal type for " << varName; throw AipsError(os.str()); } } vector<int> toVectorInt(const ::casac::variant& v, const String& varName) { vector<int> ret(0); switch (v.type()) { case casac::variant::BOOLVEC: return ret; case casac::variant::INT: ret.push_back(v.toInt()); return ret; case casac::variant::INTVEC: { auto input = v.toIntVec( ); std::vector<int> ret; std::for_each( input.begin( ), input.end( ), [&](long x){ret.push_back((int)x);} ); return ret; } case casac::variant::STRING: if (v.toString().size() > 0) { throw AipsError(varName + " cannot be a non-empty string"); } else { return ret; } default: ostringstream os; os << "Illegal type for " << varName << ": " << v.type(); throw AipsError(os.str()); } } vector<bool> toVectorBool(const ::casac::variant& v, const String& varName) { vector<bool> ret(0); switch (v.type()) { case casac::variant::BOOLVEC: return v.toBoolVec(); case casac::variant::BOOL: ret.push_back(v.toBool()); return ret; case casac::variant::STRING: if (v.toString().size() > 0) { throw AipsError(varName + " cannot be a non-empty string"); } else { return ret; } default: ostringstream os; os << "Illegal type for " << varName << ": " << v.type(); throw AipsError(os.str()); } } Vector<String> toCasaVectorString(const vector<string>& vs) { Vector<String> res(vs.size()); vector<string>::const_iterator vsiter = vs.begin(); Vector<String>::iterator resiter = res.begin(); vector<string>::const_iterator end = vs.end(); while (vsiter != end) { *resiter = *vsiter; resiter++; vsiter++; } return res; } using namespace casacore; } // End namespace casa