| [806] | 1 | //
 | 
|---|
 | 2 | // C++ Implementation: STFrequencies
 | 
|---|
 | 3 | //
 | 
|---|
 | 4 | // Description:
 | 
|---|
 | 5 | //
 | 
|---|
 | 6 | //
 | 
|---|
 | 7 | // Author: Malte Marquarding <asap@atnf.csiro.au>, (C) 2006
 | 
|---|
 | 8 | //
 | 
|---|
 | 9 | // Copyright: See COPYING file that comes with this distribution
 | 
|---|
 | 10 | //
 | 
|---|
 | 11 | //
 | 
|---|
 | 12 | #include <casa/iostream.h>
 | 
|---|
 | 13 | #include <casa/iomanip.h>
 | 
|---|
 | 14 | #include <casa/Exceptions/Error.h>
 | 
|---|
 | 15 | #include <casa/Containers/RecordField.h>
 | 
|---|
 | 16 | #include <casa/Arrays/IPosition.h>
 | 
|---|
 | 17 | 
 | 
|---|
 | 18 | #include <tables/Tables/TableDesc.h>
 | 
|---|
 | 19 | #include <tables/Tables/SetupNewTab.h>
 | 
|---|
 | 20 | #include <tables/Tables/ScaColDesc.h>
 | 
|---|
 | 21 | #include <tables/Tables/TableRecord.h>
 | 
|---|
 | 22 | #include <tables/Tables/TableParse.h>
 | 
|---|
 | 23 | #include <tables/Tables/TableRow.h>
 | 
|---|
 | 24 | 
 | 
|---|
 | 25 | #include <coordinates/Coordinates/CoordinateSystem.h>
 | 
|---|
 | 26 | #include <coordinates/Coordinates/CoordinateUtil.h>
 | 
|---|
 | 27 | 
 | 
|---|
 | 28 | #include "STFrequencies.h"
 | 
|---|
 | 29 | 
 | 
|---|
 | 30 | 
 | 
|---|
 | 31 | using namespace casa;
 | 
|---|
 | 32 | 
 | 
|---|
 | 33 | namespace asap {
 | 
|---|
 | 34 | 
 | 
|---|
| [847] | 35 | const String STFrequencies::name_ = "FREQUENCIES";
 | 
|---|
| [806] | 36 | 
 | 
|---|
| [847] | 37 | STFrequencies::STFrequencies(Table::TableType tt) :
 | 
|---|
| [806] | 38 |   STSubTable( name_, tt )
 | 
|---|
 | 39 | {
 | 
|---|
 | 40 |   setup();
 | 
|---|
 | 41 | }
 | 
|---|
 | 42 | 
 | 
|---|
 | 43 | 
 | 
|---|
 | 44 | STFrequencies::~STFrequencies()
 | 
|---|
 | 45 | {
 | 
|---|
 | 46 | }
 | 
|---|
 | 47 | 
 | 
|---|
 | 48 | void STFrequencies::setup( )
 | 
|---|
 | 49 | {
 | 
|---|
 | 50 |   // add to base class table
 | 
|---|
 | 51 |   table_.addColumn(ScalarColumnDesc<Double>("REFPIX"));
 | 
|---|
 | 52 |   table_.addColumn(ScalarColumnDesc<Double>("REFVAL"));
 | 
|---|
 | 53 |   table_.addColumn(ScalarColumnDesc<Double>("INCREMENT"));
 | 
|---|
 | 54 | 
 | 
|---|
| [847] | 55 |   table_.rwKeywordSet().define("FRAME", String("TOPO"));
 | 
|---|
 | 56 |   table_.rwKeywordSet().define("BASEFRAME", String("TOPO"));
 | 
|---|
| [806] | 57 |   table_.rwKeywordSet().define("EQUINOX",String( "J2000"));
 | 
|---|
 | 58 |   table_.rwKeywordSet().define("UNIT", String("Hz"));
 | 
|---|
 | 59 |   table_.rwKeywordSet().define("DOPPLER", String("RADIO"));
 | 
|---|
 | 60 | 
 | 
|---|
 | 61 |   // new cached columns
 | 
|---|
 | 62 |   refpixCol_.attach(table_,"REFPIX");
 | 
|---|
 | 63 |   refvalCol_.attach(table_,"REFVAL");
 | 
|---|
 | 64 |   incrCol_.attach(table_,"INCREMENT");
 | 
|---|
 | 65 | }
 | 
|---|
 | 66 | 
 | 
|---|
 | 67 | uInt STFrequencies::addEntry( Double refpix, Double refval, Double inc )
 | 
|---|
 | 68 | {
 | 
|---|
 | 69 |   // test if this already exists
 | 
|---|
 | 70 |   Table result = table_( near(table_.col("REFVAL"), refval)
 | 
|---|
 | 71 |                     && near(table_.col("REFPIX"), refpix)
 | 
|---|
 | 72 |                     && near(table_.col("INCREMENT"), inc) );
 | 
|---|
 | 73 |   uInt resultid = 0;
 | 
|---|
 | 74 |   if ( result.nrow() > 0) {
 | 
|---|
 | 75 |     ROScalarColumn<uInt> c(result, "ID");
 | 
|---|
 | 76 |     c.get(0, resultid);
 | 
|---|
 | 77 | 
 | 
|---|
 | 78 |   } else {
 | 
|---|
 | 79 |     uInt rno = table_.nrow();
 | 
|---|
 | 80 |     table_.addRow();
 | 
|---|
 | 81 |     // get last assigned freq_id and increment
 | 
|---|
 | 82 |     if ( rno > 0 ) {
 | 
|---|
 | 83 |       idCol_.get(rno-1, resultid);
 | 
|---|
 | 84 |       resultid++;
 | 
|---|
 | 85 |     }
 | 
|---|
 | 86 |     refpixCol_.put(rno, refpix);
 | 
|---|
 | 87 |     refvalCol_.put(rno, refval);
 | 
|---|
 | 88 |     incrCol_.put(rno, inc);
 | 
|---|
 | 89 |     idCol_.put(rno, resultid);
 | 
|---|
 | 90 |   }
 | 
|---|
 | 91 |   return resultid;
 | 
|---|
 | 92 | }
 | 
|---|
 | 93 | 
 | 
|---|
 | 94 | 
 | 
|---|
| [830] | 95 | 
 | 
|---|
 | 96 | void STFrequencies::getEntry( Double& refpix, Double& refval, Double& inc,
 | 
|---|
 | 97 |                               uInt id )
 | 
|---|
 | 98 | {
 | 
|---|
 | 99 |   Table t = table_(table_.col("ID") == Int(id) );
 | 
|---|
 | 100 |   if (t.nrow() == 0 ) {
 | 
|---|
 | 101 |     throw(AipsError("STFrequencies::getEntry - freqID out of range"));
 | 
|---|
 | 102 |   }
 | 
|---|
 | 103 |   ROTableRow row(t);
 | 
|---|
 | 104 |   // get first row - there should only be one matching id
 | 
|---|
 | 105 |   const TableRecord& rec = row.get(0);
 | 
|---|
 | 106 |   refpix = rec.asDouble("REFPIX");
 | 
|---|
 | 107 |   refval = rec.asDouble("REFVAL");
 | 
|---|
 | 108 |   inc = rec.asDouble("INCREMENT");
 | 
|---|
 | 109 | }
 | 
|---|
 | 110 | 
 | 
|---|
| [847] | 111 | SpectralCoordinate STFrequencies::getSpectralCoordinate( uInt id ) const
 | 
|---|
| [806] | 112 | {
 | 
|---|
| [847] | 113 |   Table t = table_(table_.col("ID") == Int(id) );
 | 
|---|
| [806] | 114 | 
 | 
|---|
 | 115 |   if (t.nrow() == 0 ) {
 | 
|---|
| [847] | 116 |     throw(AipsError("STFrequencies::getSpectralCoordinate - ID out of range"));
 | 
|---|
| [806] | 117 |   }
 | 
|---|
 | 118 | 
 | 
|---|
 | 119 |   // get the data
 | 
|---|
 | 120 |   ROTableRow row(t);
 | 
|---|
 | 121 |   // get first row - there should only be one matching id
 | 
|---|
 | 122 |   const TableRecord& rec = row.get(0);
 | 
|---|
 | 123 | 
 | 
|---|
| [847] | 124 |   return SpectralCoordinate( getFrame(true), rec.asDouble("REFVAL"),
 | 
|---|
| [806] | 125 |                              rec.asDouble("INCREMENT"),
 | 
|---|
 | 126 |                              rec.asDouble("REFPIX"));
 | 
|---|
 | 127 | }
 | 
|---|
 | 128 | 
 | 
|---|
| [847] | 129 | SpectralCoordinate
 | 
|---|
 | 130 |   asap::STFrequencies::getSpectralCoordinate( const MDirection& md,
 | 
|---|
 | 131 |                                               const MPosition& mp,
 | 
|---|
 | 132 |                                               const MEpoch& me,
 | 
|---|
 | 133 |                                               Double restfreq, uInt id ) const
 | 
|---|
| [806] | 134 | {
 | 
|---|
| [847] | 135 |   SpectralCoordinate spc = getSpectralCoordinate(id);
 | 
|---|
 | 136 |   spc.setRestFrequency(restfreq, True);
 | 
|---|
 | 137 |   if ( !spc.setReferenceConversion(getFrame(), me, mp, md) ) {
 | 
|---|
 | 138 |     throw(AipsError("Couldn't convert frequency frame."));
 | 
|---|
 | 139 |   }
 | 
|---|
 | 140 |   String unitstr = getUnitString();
 | 
|---|
 | 141 |   if ( !unitstr.empty() ) {
 | 
|---|
 | 142 |     Unit unitu(unitstr);
 | 
|---|
 | 143 |     if ( unitu == Unit("Hz") ) {
 | 
|---|
 | 144 |     } else {
 | 
|---|
 | 145 |       spc.setVelocity(unitstr, getDoppler());
 | 
|---|
 | 146 |     }
 | 
|---|
 | 147 |   }
 | 
|---|
 | 148 |   return spc;
 | 
|---|
 | 149 | }
 | 
|---|
 | 150 | 
 | 
|---|
 | 151 | 
 | 
|---|
 | 152 | void STFrequencies::rescale( Float factor, const std::string& mode )
 | 
|---|
 | 153 | {
 | 
|---|
| [806] | 154 |   TableRow row(table_);
 | 
|---|
 | 155 |   TableRecord& outrec = row.record();
 | 
|---|
 | 156 |   RecordFieldPtr<Double> rv(outrec, "REFVAL");
 | 
|---|
 | 157 |   RecordFieldPtr<Double> rp(outrec, "REFPIX");
 | 
|---|
 | 158 |   RecordFieldPtr<Double> inc(outrec, "INCREMENT");
 | 
|---|
 | 159 |   for (uInt i=0; i<table_.nrow(); ++i) {
 | 
|---|
 | 160 | 
 | 
|---|
 | 161 |     const TableRecord& rec = row.get(i);
 | 
|---|
 | 162 | 
 | 
|---|
| [847] | 163 |     SpectralCoordinate sc ( getFrame(true), rec.asDouble("REFVAL"),
 | 
|---|
| [806] | 164 |                             rec.asDouble("INCREMENT"), rec.asDouble("REFPIX") );
 | 
|---|
 | 165 | 
 | 
|---|
 | 166 |     SpectralCoordinate scout;
 | 
|---|
 | 167 |     if (mode == "BIN") {
 | 
|---|
 | 168 |       scout = binCsys(sc, Int(factor));
 | 
|---|
 | 169 |     } else if (mode == "RESAMPLE") {
 | 
|---|
 | 170 |       scout = resampleCsys(sc, factor);
 | 
|---|
 | 171 |     }
 | 
|---|
 | 172 |     *rv = scout.referenceValue()[0];
 | 
|---|
 | 173 |     *rp = scout.referencePixel()[0];
 | 
|---|
 | 174 |     *inc = scout.increment()[0];
 | 
|---|
 | 175 |     row.put(i);
 | 
|---|
 | 176 |   }
 | 
|---|
 | 177 | }
 | 
|---|
 | 178 | 
 | 
|---|
 | 179 | SpectralCoordinate STFrequencies::binCsys(const SpectralCoordinate& sc,
 | 
|---|
 | 180 |                                           Int factor)
 | 
|---|
 | 181 | {
 | 
|---|
 | 182 |   CoordinateSystem csys;
 | 
|---|
 | 183 |   csys.addCoordinate(sc);
 | 
|---|
 | 184 |   IPosition factors(1, factor);
 | 
|---|
 | 185 |   CoordinateSystem binnedcs =
 | 
|---|
 | 186 |     CoordinateUtil::makeBinnedCoordinateSystem(factors, csys, False);
 | 
|---|
 | 187 |   return binnedcs.spectralCoordinate(0);
 | 
|---|
 | 188 | }
 | 
|---|
 | 189 | 
 | 
|---|
 | 190 | SpectralCoordinate STFrequencies::resampleCsys(const SpectralCoordinate& sc,
 | 
|---|
 | 191 |                                                Float width)
 | 
|---|
 | 192 | {
 | 
|---|
 | 193 |   Vector<Float> offset(1,0.0);
 | 
|---|
 | 194 |   Vector<Float> factors(1,1.0/width);
 | 
|---|
 | 195 |   Vector<Int> newshape;
 | 
|---|
 | 196 |   CoordinateSystem csys;
 | 
|---|
 | 197 |   csys.addCoordinate(sc);
 | 
|---|
 | 198 |   CoordinateSystem csys2 = csys.subImage(offset, factors, newshape);
 | 
|---|
 | 199 |   return csys2.spectralCoordinate(0);
 | 
|---|
 | 200 | }
 | 
|---|
 | 201 | 
 | 
|---|
 | 202 | 
 | 
|---|
| [847] | 203 | MFrequency::Types STFrequencies::getFrame(bool base) const
 | 
|---|
| [806] | 204 | {
 | 
|---|
 | 205 |   // get the ref frame
 | 
|---|
| [847] | 206 |   String rf = table_.keywordSet().asString("BASEFRAME");
 | 
|---|
| [806] | 207 | 
 | 
|---|
 | 208 |   // Create SpectralCoordinate (units Hz)
 | 
|---|
 | 209 |   MFrequency::Types mft;
 | 
|---|
 | 210 |   if (!MFrequency::getType(mft, rf)) {
 | 
|---|
 | 211 |     ostringstream oss;
 | 
|---|
 | 212 |     pushLog("WARNING: Frequency type unknown assuming TOPO");
 | 
|---|
 | 213 |     mft = MFrequency::TOPO;
 | 
|---|
 | 214 |   }
 | 
|---|
 | 215 | 
 | 
|---|
 | 216 |   return mft;
 | 
|---|
 | 217 | }
 | 
|---|
 | 218 | 
 | 
|---|
| [847] | 219 | std::string asap::STFrequencies::getFrameString( bool base ) const
 | 
|---|
 | 220 | {
 | 
|---|
 | 221 |   if ( base ) return table_.keywordSet().asString("BASEFRAME");
 | 
|---|
 | 222 |   else return table_.keywordSet().asString("FRAME");
 | 
|---|
 | 223 | }
 | 
|---|
 | 224 | 
 | 
|---|
 | 225 | std::string asap::STFrequencies::getUnitString( ) const
 | 
|---|
 | 226 | {
 | 
|---|
 | 227 |   return table_.keywordSet().asString("UNIT");
 | 
|---|
 | 228 | }
 | 
|---|
 | 229 | 
 | 
|---|
 | 230 | Unit asap::STFrequencies::getUnit( ) const
 | 
|---|
 | 231 | {
 | 
|---|
 | 232 |   return Unit(table_.keywordSet().asString("UNIT"));
 | 
|---|
 | 233 | }
 | 
|---|
 | 234 | 
 | 
|---|
 | 235 | std::string asap::STFrequencies::getDopplerString( ) const
 | 
|---|
 | 236 | {
 | 
|---|
 | 237 |   return table_.keywordSet().asString("DOPPLER");
 | 
|---|
 | 238 | }
 | 
|---|
 | 239 | 
 | 
|---|
 | 240 | MDoppler::Types asap::STFrequencies::getDoppler( ) const
 | 
|---|
 | 241 | {
 | 
|---|
 | 242 |   String dpl = table_.keywordSet().asString("DOPPLER");
 | 
|---|
 | 243 | 
 | 
|---|
 | 244 |   // Create SpectralCoordinate (units Hz)
 | 
|---|
 | 245 |   MDoppler::Types mdt;
 | 
|---|
 | 246 |   if (!MDoppler::getType(mdt, dpl)) {
 | 
|---|
 | 247 |     throw(AipsError("Doppler type unknown"));
 | 
|---|
 | 248 |   }
 | 
|---|
 | 249 |   return mdt;
 | 
|---|
 | 250 | }
 | 
|---|
 | 251 | 
 | 
|---|
| [806] | 252 | std::string asap::STFrequencies::print( int id )
 | 
|---|
 | 253 | {
 | 
|---|
 | 254 |   Table t;
 | 
|---|
 | 255 |   ostringstream oss;
 | 
|---|
 | 256 |   if ( id < 0 ) t = table_;
 | 
|---|
 | 257 |   else  t = table_(table_.col("ID") == Int(id) );
 | 
|---|
 | 258 |   ROTableRow row(t);
 | 
|---|
 | 259 |   for (uInt i=0; i<t.nrow(); ++i) {
 | 
|---|
 | 260 |     const TableRecord& rec = row.get(i);
 | 
|---|
 | 261 |     oss <<  setw(8)
 | 
|---|
 | 262 |     << "frame" << setw(16) << setprecision(8)
 | 
|---|
 | 263 |     << rec.asDouble("REFVAL") << setw(10)
 | 
|---|
 | 264 |     << rec.asDouble("REFPIX") << setw(12)
 | 
|---|
 | 265 |     << rec.asDouble("INCREMENT") << endl;
 | 
|---|
 | 266 |   }
 | 
|---|
 | 267 |   return String(oss);
 | 
|---|
 | 268 | }
 | 
|---|
 | 269 | 
 | 
|---|
 | 270 | float STFrequencies::getRefFreq( uInt id, uInt channel )
 | 
|---|
 | 271 | {
 | 
|---|
 | 272 |   Table t = table_(table_.col("ID") == Int(id) );
 | 
|---|
 | 273 |   if ( t.nrow() == 0 ) throw(AipsError("Selected Illegal frequency id"));
 | 
|---|
 | 274 |   ROTableRow row(t);
 | 
|---|
 | 275 |   const TableRecord& rec = row.get(0);
 | 
|---|
 | 276 |   return (Double(channel/2) - rec.asDouble("REFPIX"))
 | 
|---|
 | 277 |           * rec.asDouble("INCREMENT") + rec.asDouble("REFVAL");
 | 
|---|
 | 278 | }
 | 
|---|
 | 279 | 
 | 
|---|
| [840] | 280 | bool asap::STFrequencies::conformant( const STFrequencies& other ) const
 | 
|---|
 | 281 | {
 | 
|---|
 | 282 |   const Record& r = table_.keywordSet();
 | 
|---|
 | 283 |   const Record& ro = other.table_.keywordSet();
 | 
|---|
| [847] | 284 |   return ( r.asString("FRAME") == ro.asString("FRAME") &&
 | 
|---|
| [840] | 285 |            r.asString("EQUINOX") == ro.asString("EQUINOX") &&
 | 
|---|
 | 286 |            r.asString("UNIT") == ro.asString("UNIT") &&
 | 
|---|
 | 287 |            r.asString("DOPPLER") == ro.asString("DOPPLER")
 | 
|---|
 | 288 |           );
 | 
|---|
 | 289 | }
 | 
|---|
 | 290 | 
 | 
|---|
| [847] | 291 | std::vector< std::string > asap::STFrequencies::getInfo( ) const
 | 
|---|
 | 292 | {
 | 
|---|
 | 293 |   const Record& r = table_.keywordSet();
 | 
|---|
 | 294 |   std::vector<std::string> out;
 | 
|---|
 | 295 |   out.push_back(r.asString("UNIT"));
 | 
|---|
 | 296 |   out.push_back(r.asString("FRAME"));
 | 
|---|
 | 297 |   out.push_back(r.asString("DOPPLER"));
 | 
|---|
 | 298 | }
 | 
|---|
 | 299 | 
 | 
|---|
 | 300 | void asap::STFrequencies::setInfo( const std::vector< std::string >& theinfo )
 | 
|---|
 | 301 | {
 | 
|---|
 | 302 |   if ( theinfo.size() != 3 ) throw(AipsError("setInfo needs three parameters"));
 | 
|---|
 | 303 |   String un,rfrm,dpl;
 | 
|---|
 | 304 |   un = theinfo[0];rfrm = theinfo[1];dpl = theinfo[2];
 | 
|---|
 | 305 |   TableRecord& r = table_.rwKeywordSet();
 | 
|---|
 | 306 |   setFrame(rfrm);
 | 
|---|
 | 307 |   MDoppler::Types dtype;
 | 
|---|
 | 308 |   dpl.upcase();
 | 
|---|
 | 309 |   if (!MDoppler::getType(dtype, dpl)) {
 | 
|---|
 | 310 |     throw(AipsError("Doppler type unknown"));
 | 
|---|
 | 311 |   } else {
 | 
|---|
 | 312 |     r.define("DOPPLER",dpl);
 | 
|---|
 | 313 |   }
 | 
|---|
 | 314 | }
 | 
|---|
 | 315 | void asap::STFrequencies::setFrame( const std::string & frame )
 | 
|---|
 | 316 | {
 | 
|---|
 | 317 |   MFrequency::Types mdr;
 | 
|---|
 | 318 |   if (!MFrequency::getType(mdr, frame)) {
 | 
|---|
 | 319 |     Int a,b;const uInt* c;
 | 
|---|
 | 320 |     const String* valid = MFrequency::allMyTypes(a, b, c);
 | 
|---|
 | 321 |     String pfix = "Please specify a legal frame type. Types are\n";
 | 
|---|
 | 322 |     throw(AipsError(pfix+(*valid)));
 | 
|---|
 | 323 |   } else {
 | 
|---|
 | 324 |     table_.rwKeywordSet().define("FRAME", frame);
 | 
|---|
 | 325 |   }
 | 
|---|
 | 326 | }
 | 
|---|
 | 327 | 
 | 
|---|
| [806] | 328 | } // namespace
 | 
|---|