//#--------------------------------------------------------------------------- //# SDPol.cc: Polarimetric functionality //#--------------------------------------------------------------------------- //# Copyright (C) 2004 //# ATNF //# //# This program is free software; you can redistribute it and/or modify it //# under the terms of the GNU General Public License as published by the Free //# Software Foundation; either version 2 of the License, or (at your option) //# any later version. //# //# This program is distributed in the hope that it will be useful, but //# WITHOUT ANY WARRANTY; without even the implied warranty of //# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General //# Public License for more details. //# //# You should have received a copy of the GNU General Public License along //# with this program; if not, write to the Free Software Foundation, Inc., //# 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning this software should be addressed as follows: //# Internet email: Malte.Marquarding@csiro.au //# Postal address: Malte Marquarding, //# Australia Telescope National Facility, //# P.O. Box 76, //# Epping, NSW, 2121, //# AUSTRALIA //# //# $Id: //#--------------------------------------------------------------------------- #include "SDPol.h" #include "SDDefs.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace casa; using namespace asap; SDStokesEngine::SDStokesEngine (const String& outputColumnName, const String& inputColumnName) : BaseMappedArrayEngine (outputColumnName, inputColumnName) { setWritable(False); } SDStokesEngine::SDStokesEngine (const Record& spec) : BaseMappedArrayEngine () { setWritable(False); if (spec.isDefined("OUTPUTNAME") && spec.isDefined("INPUTNAME")) { setNames (spec.asString("OUTPUTNAME"), spec.asString("INPUTNAME")); } } SDStokesEngine::SDStokesEngine (const SDStokesEngine& that) : BaseMappedArrayEngine (that) {} SDStokesEngine::~SDStokesEngine() {} DataManager* SDStokesEngine::clone() const { DataManager* dmPtr = new SDStokesEngine (*this); return dmPtr; } String SDStokesEngine::dataManagerType() const { return className(); } String SDStokesEngine::className() { return "SDStokesEngine"; } String SDStokesEngine::dataManagerName() const { return virtualName(); } Record SDStokesEngine::dataManagerSpec() const { Record spec; spec.define ("OUTPUTNAME", virtualName()); spec.define ("INPUTNAME", storedName()); return spec; } DataManager* SDStokesEngine::makeObject (const String&, const Record& spec) { DataManager* dmPtr = new SDStokesEngine(spec); return dmPtr; } void SDStokesEngine::registerClass() { DataManager::registerCtor (className(), makeObject); } void SDStokesEngine::create (uInt initialNrrow) { BaseMappedArrayEngine::create (initialNrrow); } void SDStokesEngine::prepare() { BaseMappedArrayEngine::prepare(); } Bool SDStokesEngine::canAccessArrayColumnCells (Bool& reask) const { reask = False; return True; } void SDStokesEngine::getArray (uInt rownr, Array& output) { Array input; roColumn().get(rownr, input); // computeOnGet (output, input); } void SDStokesEngine::putArray (uInt rownr, const Array& input) { throw(AipsError("This Virtual Column is not writable")); } IPosition SDStokesEngine::shape (uInt rownr) { IPosition inputShape = roColumn().shape (rownr); return findOutputShape(inputShape); } void SDStokesEngine::computeOnGet(Array& output, const Array& input) // // array of shape (nBeam,nIF,nPol,nChan) // // We use the scaling convention I=(XX+YY)/2 { // Checks const uInt nDim = input.ndim(); AlwaysAssert(nDim==4,AipsError); AlwaysAssert(output.ndim()==4,AipsError); // const IPosition inputShape = input.shape(); const uInt polAxis = asap::PolAxis; const uInt nPol = inputShape(polAxis); AlwaysAssert(nPol==1 || nPol==2 || nPol==4, AipsError); // The silly Array slice operator does not give me back // a const reference so have to caste it away Array& input2 = const_cast&>(input); // Slice coordnates IPosition start(nDim,0); IPosition end(input.shape()-1); // Generate Slices start(polAxis) = 0; end(polAxis) = 0; Array C1 = input2(start,end); // Input : C1 // start(polAxis) = 0; end(polAxis) = 0; Array I = output(start,end); // Output : I // if (nPol==1) { I = C1; return; } // start(polAxis) = 1; end(polAxis) = 1; Array C2 = input2(start,end); // Input : C1 // I = Float(0.5) * (C1 + C2); if (nPol <= 2) return; // start(polAxis) = 2; end(polAxis) = 2; Array C3 = input2(start,end); // Input : C3 // start(polAxis) = 3; end(polAxis) = 3; Array C4 = input2(start,end); // Input : C4 // start(polAxis) = 1; end(polAxis) = 1; Array Q = output(start,end); // Output : Q Q = Float(0.5) * (C1 - C2); // start(polAxis) = 2; end(polAxis) = 2; Array U = output(start,end); // Output : U U = C3; // start(polAxis) = 3; end(polAxis) = 3; Array V = output(start,end); // Output : V V = C4; } IPosition SDStokesEngine::findOutputShape (const IPosition& inputShape) const { uInt axis = 2; uInt nPol = inputShape(axis); IPosition outputShape = inputShape; if (nPol==1) { outputShape(axis) = 1; // XX -> I } else if (nPol==2) { outputShape(axis) = 1; // XX YY -> I } else if (nPol==4) { outputShape(axis) = 4; // XX YY R(XY) I(XY) -> I Q U V } return outputShape; } // SDPolUtil Array SDPolUtil::polarizedIntensity (const Array& Q, const Array& U) { Array t1 = pow(Q,Double(2.0)); Array t2 = pow(U,Double(2.0)); return sqrt(t1+t2); } Array SDPolUtil::positionAngle (const Array& Q, const Array& U) { return Float(180.0/C::pi/2.0)*atan2(U,Q); // Degrees } void SDPolUtil::rotatePhase (Array& R, Array& I, Float phase) // // Apply phase rotation to Z = (R + iI) // { Float cosVal = cos(C::pi/180.0*phase); Float sinVal = sin(C::pi/180.0*phase); // Array R2 = R*cosVal - I*sinVal; I = R*sinVal + I*cosVal; R = R2; } void SDPolUtil::rotateLinPolPhase (Array& C1, Array& C2, Array& C3, Array& I, Array& Q, Array& U, Float phase) // // Rotate P = Q + iU but do it directly on the linear // correlations. // // We are using I=(XX+YY)/2 convention // C1 = XX; C2 = YY, C3 = Real(XY) // { // Rotate Q & U (factor of 2 for polarization) rotatePhase(Q, U, 2.0*phase); // Now recompute C1,C2,C3 // C4 unchanged C1 = I + Q; C2 = I - Q; C3 = U; } Array SDPolUtil::getStokesSlice (Array& in, const IPosition& start, const IPosition& end, const String& stokes) { IPosition s(start); IPosition e(end); // if (stokes=="I") { s(asap::PolAxis) = 0; e(asap::PolAxis) = 0; } else if (stokes=="Q") { s(asap::PolAxis) = 1; e(asap::PolAxis) = 1; } else if (stokes=="U") { s(asap::PolAxis) = 2; e(asap::PolAxis) = 2; } else if (stokes=="V") { s(asap::PolAxis) = 3; e(asap::PolAxis) = 3; } // return in(s,e); } Array SDPolUtil::circularPolarizationFromStokes (Array& I, Array& V, Bool doRR) // // We use the convention // I = (RR+LL)/2 // { if (doRR) { return I + V; } else { return I - V; } } Stokes::StokesTypes SDPolUtil::convertStokes(Int val, Bool toStokes, Bool linear) { Stokes::StokesTypes stokes = Stokes::Undefined; if (toStokes) { if (val==0) { stokes = Stokes::I; } else if (val==1) { stokes = Stokes::Q; } else if (val==2) { stokes = Stokes::U; } else if (val==3) { stokes = Stokes::V; } } else if (linear) { if (val==0) { stokes = Stokes::XX; } else if (val==1) { stokes = Stokes::YY; } else if (val==2) { stokes = Stokes::XY; // Real(XY) } else if (val==3) { stokes = Stokes::XY; // Imag(XY) } } else { if (val==0) { stokes = Stokes::RR; } else if (val==1) { stokes = Stokes::LL; } else if (val==2) { stokes = Stokes::RL; } else if (val==3) { stokes = Stokes::RL; } } // return stokes; } String SDPolUtil::polarizationLabel (uInt polIdx, Bool linear, Bool stokes, Bool linPol) { Stokes::StokesTypes type = Stokes::Undefined; if (stokes) { switch (polIdx) { case 0: { type = Stokes::I; } break; case 1: { if (linPol) { type = Stokes::Plinear; } else { type = Stokes::Q; } } break; case 2: { if (linPol) { type = Stokes::Pangle; } else { type = Stokes::U; } } break; case 3: { type = Stokes::V; } break; default: { throw(AipsError("Unknown Stokes type")); } } } else { if (linear) { switch (polIdx) { case 0: { type = Stokes::XX; } break; case 1: { type = Stokes::YY; } break; case 2: { type = Stokes::XY; // Really Real(XY) return String("Real(XY)"); } break; case 3: { type = Stokes::YX; // Really Imag(XY) return String("Imag(XY)"); } break; default: { throw(AipsError("Unknown linear polarization type")); } } } else { switch (polIdx) { case 0: { type = Stokes::RR; } break; case 1: { type = Stokes::LL; } case 2: { type = Stokes::RL; // Really Real(RL) return String("Real(RL)"); } break; case 3: { type = Stokes::LR; // Really Imag(RL) return String("Imag(RL)"); } break; default: { throw(AipsError("Unknown circular polarization type")); } } } } // return SDPolUtil::stokesString(type); } // private String SDPolUtil::stokesString (Stokes::StokesTypes type) { return Stokes::name (type); } Array SDPolUtil::andArrays (const Array& in1, const Array& in2) { Array out(in1.shape()); // Array::const_iterator in1Iter; Array::const_iterator in2Iter; Array::iterator outIter; // for (in1Iter=in1.begin(),in2Iter=in2.begin(),outIter=out.begin(); in1Iter!=in1.end(); ++in1Iter,++in2Iter,++outIter) { *outIter = *in1Iter & *in2Iter; } return out; } Array SDPolUtil::extractStokesForWriter (Array& in, const IPosition& start, const IPosition& end) // // start/end must already have applied the cursor selection of beam and IF // Extract specified Stokes for beam/IF and flip nChan and nPol for bloody SDwriter // { IPosition shapeIn = in.shape(); uInt nChan = shapeIn(asap::ChanAxis); uInt nPol = shapeIn(asap::PolAxis); // IPosition shapeOut(2,nChan,nPol); Array out(shapeOut); // Array sliceRef = in(start,end); // Beam and IF now degenerate axes ReadOnlyVectorIterator itIn(sliceRef, asap::ChanAxis); VectorIterator itOut(out,0); while (!itIn.pastEnd()) { itOut.vector() = itIn.vector(); // itIn.next(); itOut.next(); } // return out; }