LCOV - code coverage report
Current view: top level - components/ComponentModels - LimbDarkenedDiskShape.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 218 0.0 %
Date: 2024-12-11 20:54:31 Functions: 0 28 0.0 %

          Line data    Source code
       1             : //# LimbDarkenedDiskShape.cc: implementation of LimbDarkenedDiskShape.h which defines LimbDarkened Disk shape
       2             : //
       3             : //#  CASA - Common Astronomy Software Applications (http://casa.nrao.edu/)
       4             : //# Copyright (C) 2012
       5             : //# Associated Universities, Inc. Washington DC, USA.
       6             : //#
       7             : //# This library is free software; you can redistribute it and/or modify it
       8             : //# under the terms of the GNU Lesser General Public License as published by
       9             : //# the Free Software Foundation; either version 2.1 of the License, or (at your
      10             : //# option) any later version.
      11             : //#
      12             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      13             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
      15             : //# License for more details.
      16             : //#
      17             : //# You should have received a copy of the GNU Lesser General Public License
      18             : //# along with this library; if not, write to the Free Software Foundation,
      19             : //# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
      20             : //#
      21             : //#
      22             : //#
      23             : //# $Id$
      24             : 
      25             : #include <components/ComponentModels/LimbDarkenedDiskShape.h>
      26             : //#include <components/ComponentModels/Flux.h>
      27             : #include <casacore/casa/Arrays/Matrix.h>
      28             : #include <casacore/casa/Arrays/Vector.h>
      29             : #include <casacore/casa/Arrays/VectorIter.h>
      30             : #include <casacore/casa/Arrays/ArrayMath.h>
      31             : #include <casacore/casa/Arrays/Array.h>
      32             : #include <casacore/casa/Exceptions/Error.h>
      33             : #include <casacore/casa/Logging/LogIO.h>
      34             : #include <casacore/casa/Logging/LogOrigin.h>
      35             : #include <casacore/casa/BasicSL/Constants.h>
      36             : #include <casacore/casa/BasicMath/Math.h>
      37             : #include <casacore/measures/Measures/MCDirection.h>
      38             : #include <casacore/measures/Measures/MDirection.h>
      39             : #include <casacore/measures/Measures/MeasConvert.h>
      40             : #include <casacore/measures/Measures/MeasRef.h>
      41             : #include <casacore/casa/Quanta/MVAngle.h>
      42             : #include <casacore/casa/Quanta/MVDirection.h>
      43             : #include <casacore/casa/Quanta/Quantum.h>
      44             : #include <casacore/casa/Utilities/Assert.h>
      45             : #include <casacore/casa/BasicSL/String.h>
      46             : 
      47             : #include <gsl/gsl_sf_bessel.h>
      48             : 
      49             : using namespace casacore;
      50             : namespace casa { //# NAMESPACE CASA - BEGIN
      51             : 
      52           0 : LimbDarkenedDiskShape::LimbDarkenedDiskShape()
      53             :   :TwoSidedShape(),
      54           0 :    itsMajValue(Quantity(1,"'").getValue("rad")),
      55           0 :    itsMinValue(Quantity(1,"'").getValue("rad")),
      56           0 :    itsPaValue(Quantity(0,"deg").getValue("rad")),
      57           0 :    itsHeight(1.0/(C::pi*itsMajValue*itsMinValue)),
      58           0 :    itsAttnFactor(0.05)
      59             : {
      60           0 :   DebugAssert(ok(), AipsError);
      61           0 : }
      62             : 
      63           0 : LimbDarkenedDiskShape::LimbDarkenedDiskShape(const MDirection& direction,
      64             :                                          const Quantum<Double>& majorAxis,
      65             :                                          const Quantum<Double>& minorAxis,
      66             :                                          const Quantum<Double>& positionAngle,
      67           0 :                                          const Float& n)
      68           0 :   :TwoSidedShape(direction, majorAxis.getFullUnit(), minorAxis.getFullUnit(), positionAngle.getFullUnit()),
      69           0 :    itsMajValue(majorAxis.getValue("rad")),
      70           0 :    itsMinValue(minorAxis.getValue("rad")),
      71           0 :    itsPaValue(positionAngle.getValue("rad")),
      72           0 :    itsHeight(1.0/(C::pi*itsMajValue*itsMinValue)),
      73           0 :    itsAttnFactor(n)
      74             : {
      75           0 :   DebugAssert(ok(), AipsError);
      76           0 : }
      77             : 
      78             : 
      79           0 : LimbDarkenedDiskShape::LimbDarkenedDiskShape(const MDirection& direction, 
      80             :                     const Quantum<Double>& width,
      81             :                     const Double axialRatio,
      82             :                     const Quantum<Double>& positionAngle, 
      83           0 :                     const Float& n)
      84           0 :   :TwoSidedShape(direction, width.getFullUnit(),
      85           0 :                     width.getFullUnit(), positionAngle.getFullUnit()),
      86           0 :    itsMajValue(width.getValue("rad")),
      87           0 :    itsMinValue(itsMajValue*axialRatio),
      88           0 :    itsPaValue(positionAngle.getValue("rad")),
      89           0 :    itsHeight(1.0/(C::pi*itsMajValue*itsMinValue)),
      90           0 :    itsAttnFactor(n)
      91             : {
      92           0 :   DebugAssert(ok(), AipsError);
      93           0 : }
      94             : 
      95           0 : LimbDarkenedDiskShape::LimbDarkenedDiskShape(const LimbDarkenedDiskShape& other)
      96             :   :TwoSidedShape(other),
      97           0 :    itsMajValue(other.itsMajValue),
      98           0 :    itsMinValue(other.itsMinValue),
      99           0 :    itsPaValue(other.itsPaValue),
     100           0 :    itsHeight(other.itsHeight),
     101           0 :    itsAttnFactor(other.itsAttnFactor)
     102             : {
     103           0 :   DebugAssert(ok(), AipsError);
     104           0 : }
     105             : 
     106             :   // The destructor
     107           0 : LimbDarkenedDiskShape::~LimbDarkenedDiskShape() {
     108           0 :   DebugAssert(ok(), AipsError);
     109           0 : }
     110             :   //#! Operators
     111             :   //The assignment operator
     112           0 : LimbDarkenedDiskShape& LimbDarkenedDiskShape::operator=(const LimbDarkenedDiskShape& other) {
     113           0 :   if (this != &other) {
     114           0 :     TwoSidedShape::operator=(other);
     115           0 :     itsMajValue = other.itsMajValue;
     116           0 :     itsMinValue = other.itsMinValue;
     117           0 :     itsPaValue = other.itsPaValue;
     118           0 :     itsHeight = other.itsHeight;
     119           0 :     itsAttnFactor = other.itsAttnFactor;
     120             :   }
     121           0 :   DebugAssert(ok(), AipsError);
     122           0 :   return *this;
     123             : }
     124             : 
     125             : //#! General Member Functions
     126             : // get the type of the shape (always returns ComponentType::LimbDakenDisk)
     127           0 : ComponentType::Shape LimbDarkenedDiskShape::type() const {
     128           0 :     DebugAssert(ok(), AipsError);
     129           0 :     return ComponentType::LDISK;
     130             : }
     131             : 
     132             : 
     133             : // use diskshape ones?
     134           0 : void LimbDarkenedDiskShape::setWidthInRad(const Double majorAxis,
     135             :                              const Double minorAxis,
     136             :                              const Double positionAngle) {
     137           0 :     itsMajValue = majorAxis;
     138           0 :     itsMinValue = minorAxis;
     139           0 :     itsPaValue = positionAngle;
     140           0 :     AlwaysAssert(itsMajValue > 0 && itsMinValue > 0 && itsMajValue >=itsMinValue,
     141             :                  AipsError);
     142           0 :     itsHeight = 1.0/(C::pi*itsMajValue*itsMinValue);
     143           0 :     DebugAssert(ok(), AipsError);
     144           0 : }
     145             : //
     146           0 : Double LimbDarkenedDiskShape::majorAxisInRad() const {
     147           0 :   DebugAssert(ok(), AipsError);
     148           0 :   return itsMajValue;
     149             : }
     150             : 
     151           0 : Double LimbDarkenedDiskShape::minorAxisInRad() const {
     152           0 :   DebugAssert(ok(), AipsError);
     153           0 :   return itsMinValue;
     154             : }
     155             : 
     156           0 : Double LimbDarkenedDiskShape::positionAngleInRad() const {
     157           0 :   DebugAssert(ok(), AipsError);
     158           0 :   return itsPaValue;
     159             : }
     160             : 
     161           0 : Float LimbDarkenedDiskShape::getAttnFactor() const {
     162           0 :   DebugAssert(ok(), AipsError);
     163           0 :   return itsAttnFactor;
     164             : }
     165             :   //set n factor in darkening equation, I=I0(1-rho^2)^n/2
     166           0 : void LimbDarkenedDiskShape::setAttnFactor(const Float attnFactor) {
     167           0 :   itsAttnFactor=attnFactor;  
     168           0 : }
     169             : 
     170           0 : Vector<Double> LimbDarkenedDiskShape::optParameters() const {
     171           0 :   DebugAssert(ok(), AipsError);
     172           0 :   Vector<Double> optparm(1);
     173           0 :   optparm(0) = (Double)getAttnFactor();
     174           0 :   return optparm;
     175           0 : }
     176             : 
     177           0 : void LimbDarkenedDiskShape::setOptParameters(const Vector<Double>& newOptParms) {
     178           0 :   DebugAssert(ok(), AipsError);
     179           0 :   setAttnFactor((Float)newOptParms(0));
     180           0 : }
     181             : 
     182             :   // Calculate the proportion of the flux that is in a pixel of specified size
     183             :   // centered in the specified direction. The returned value will always be
     184             :   // between zero and one (inclusive).
     185           0 : Double LimbDarkenedDiskShape::sample(const MDirection& direction,
     186             :                         const MVAngle& pixelLatSize,
     187             :                         const MVAngle& pixelLongSize) const {
     188           0 :   DebugAssert(ok(), AipsError);
     189           0 :   const MDirection& compDir(refDirection());
     190           0 :   const MDirection::Ref& compDirFrame(compDir.getRef());
     191           0 :   const MDirection::MVType* compDirValue = &(compDir.getValue());
     192           0 :   Bool deleteValue = false;
     193             :   // Convert direction to the same frame as the reference direction
     194           0 :   if (ComponentShape::differentRefs(direction.getRef(), compDirFrame)) {
     195           0 :     compDirValue = new MDirection::MVType
     196           0 :       (MDirection::Convert(compDir, direction.getRef())().getValue());
     197           0 :     deleteValue = true;
     198             :   }
     199           0 :   Double retVal = calcSample(*compDirValue, direction.getValue(),
     200           0 :                              itsMajValue/2.0, itsMinValue/2.0,
     201           0 :                              itsHeight*pixelLatSize.radian()*
     202           0 :                              pixelLongSize.radian());
     203           0 :   if (deleteValue) delete compDirValue;
     204           0 :   return retVal;
     205           0 : }
     206             : 
     207             : 
     208             :   // Same as the previous function except that many directions can be sampled
     209             :   // at once. The reference frame and pixel size must be the same for all the
     210             :   // specified directions.
     211           0 : void LimbDarkenedDiskShape::sample(Vector<Double>& scale,
     212             :                       const Vector<MDirection::MVType>& directions,
     213             :                       const MDirection::Ref& refFrame,
     214             :                       const MVAngle& pixelLatSize,
     215             :                       const MVAngle& pixelLongSize) const {
     216           0 :   DebugAssert(ok(), AipsError);
     217           0 :   const uInt nSamples = directions.nelements();
     218           0 :   DebugAssert(scale.nelements() == nSamples, AipsError);
     219             : 
     220           0 :   const MDirection& compDir(refDirection());
     221           0 :   const MDirection::Ref& compDirFrame(compDir.getRef());
     222           0 :   const MDirection::MVType* compDirValue = &(compDir.getValue());
     223           0 :   Bool deleteValue = false;
     224             :   // Convert direction to the same frame as the reference direction
     225           0 :   if (refFrame != compDirFrame) {
     226           0 :     compDirValue = new MDirection::MVType
     227           0 :       (MDirection::Convert(compDir, refFrame)().getValue());
     228           0 :     deleteValue = true;
     229             :   }
     230           0 :   const Double majRad = itsMajValue/2.0;
     231           0 :   const Double minRad = itsMinValue/2.0;
     232           0 :   const Double pixValue = itsHeight *
     233           0 :     pixelLatSize.radian() * pixelLongSize.radian();
     234           0 :   for (uInt i = 0; i < nSamples; i++) {
     235           0 :     scale(i) = calcSample(*compDirValue, directions(i),
     236             :                           majRad, minRad, pixValue);
     237             :   }
     238           0 :   if (deleteValue) delete compDirValue;
     239           0 : }
     240             : 
     241           0 : DComplex LimbDarkenedDiskShape::visibility(const Vector<Double>& uvw,
     242             :                               const Double& frequency) const {
     243           0 :  DebugAssert(uvw.nelements() == 3, AipsError);
     244           0 :   DebugAssert(frequency > 0, AipsError);
     245           0 :   DebugAssert(ok(), AipsError);
     246           0 :   Double u = uvw(0);
     247           0 :   Double v = uvw(1);
     248           0 :   if (near(u + v, 0.0)) return DComplex(1.0, 0.0);
     249           0 :   if (!nearAbs(itsPaValue, 0.0)) {
     250           0 :     rotateVis(u, v, cos(itsPaValue), sin(itsPaValue));
     251             :   }
     252           0 :   return DComplex(calcVis(u, v, C::pi * frequency/C::c), 0.0);
     253             : }
     254             : 
     255           0 : void LimbDarkenedDiskShape::visibility(Matrix<DComplex>& scale,
     256             :                            const Matrix<Double>& uvw,
     257             :                            const Vector<Double>& frequency) const {
     258             : 
     259           0 :   scale.resize(uvw.ncolumn(), frequency.nelements());
     260             : 
     261           0 :   VectorIterator<DComplex> iter(scale, 0);
     262           0 :   for ( uInt k =0 ; k < frequency.nelements() ; ++k){
     263           0 :     visibility(iter.vector(), uvw, frequency(k));
     264           0 :     iter.next();
     265             :   }
     266           0 : }
     267             : 
     268           0 : void LimbDarkenedDiskShape::visibility(Vector<DComplex>& scale,
     269             :                            const Matrix<Double>& uvw,
     270             :                            const Double& frequency) const {
     271           0 :   DebugAssert(ok(), AipsError);
     272           0 :   const uInt nSamples = scale.nelements();
     273           0 :   DebugAssert(uvw.ncolumn() == nSamples, AipsError);
     274           0 :   DebugAssert(uvw.nrow() == 3, AipsError);
     275           0 :   DebugAssert(frequency > 0, AipsError);
     276             : 
     277           0 :   Bool doRotation = false;
     278           0 :   Double cpa = 1.0, spa = 0.0;
     279           0 :   if (!nearAbs(itsPaValue, 0.0)) {
     280           0 :     doRotation = true;
     281           0 :     cpa = cos(itsPaValue);
     282           0 :     spa = sin(itsPaValue);
     283             :   }
     284             : 
     285           0 :   const Double factor = C::pi * frequency/C::c;
     286             :   Double u, v;
     287           0 :   for (uInt i = 0; i < nSamples; i++) {
     288           0 :     u = uvw(0, i);
     289           0 :     v = uvw(1, i);
     290             :     // DComplex& thisVis = scale(i);
     291             :     ///    thisVis.imag() = 0.0;
     292           0 :     if (near(u + v, 0.0)) {
     293             :       ///      thisVis.real() = 1.0; // avoids dividing by zero in calcVis(...)
     294           0 :       scale[i] = DComplex(1.0, 0.0); // avoids dividing by zero
     295             :       // in calcVis(...)
     296             :     } else {
     297           0 :       if (doRotation) rotateVis(u, v, cpa, spa);
     298             :       ///      thisVis.real() = calcVis(u, v, factor);
     299           0 :       scale[i] = DComplex(calcVis(u, v, factor), 0.0);
     300             :     }
     301             :   }
     302           0 : }
     303             : 
     304             : 
     305           0 : ComponentShape* LimbDarkenedDiskShape::clone() const {
     306           0 :   DebugAssert(ok(), AipsError);
     307           0 :   ComponentShape* tmpPtr = new LimbDarkenedDiskShape(*this);
     308           0 :   AlwaysAssert(tmpPtr != 0, AipsError);
     309           0 :   return tmpPtr;
     310             : }
     311             : 
     312           0 : Bool LimbDarkenedDiskShape::ok() const {
     313             :   // The LogIO class is only constructed if an error is detected for
     314             :   // performance reasons. Both function static and file static variables
     315             :   // where considered and rejected for this purpose.
     316           0 :   if (!TwoSidedShape::ok()) return false;
     317           0 :   if (itsMajValue <= 0) {
     318           0 :     LogIO logErr(LogOrigin("DiskCompRep", "ok()"));
     319             :     logErr << LogIO::SEVERE << "The major axis width is zero or negative"
     320           0 :            << LogIO::POST;
     321           0 :     return false;
     322           0 :   }
     323           0 :   if (itsMinValue <= 0) {
     324           0 :     LogIO logErr(LogOrigin("DiskCompRep", "ok()"));
     325             :     logErr << LogIO::SEVERE << "The minor axis width is zero or negative"
     326           0 :            << LogIO::POST;
     327           0 :     return false;
     328           0 :   }
     329           0 :   if (itsMinValue > itsMajValue) {
     330           0 :     LogIO logErr(LogOrigin("DiskCompRep", "ok()"));
     331             :     logErr << LogIO::SEVERE << "The minor axis width is larger than "
     332             :            << "the major axis width"
     333           0 :            << LogIO::POST;
     334           0 :     return false;
     335           0 :   }
     336           0 :   if (!near(itsHeight, 1.0/(C::pi*itsMajValue*itsMinValue), 2*C::dbl_epsilon)) {
     337           0 :     LogIO logErr(LogOrigin("DiskCompRep", "ok()"));
     338             :     logErr << LogIO::SEVERE << "The disk shape does not have"
     339             :            << " unit area"
     340           0 :            << LogIO::POST;
     341           0 :     return false;
     342           0 :   }
     343           0 :   return true;
     344             : }
     345             : 
     346             : 
     347             :   // return a pointer to this object.
     348           0 : const ComponentShape* LimbDarkenedDiskShape::getPtr() const {
     349           0 :     return this;
     350             : }
     351             : 
     352           0 : String LimbDarkenedDiskShape::sizeToString() const {
     353             :         return TwoSidedShape::sizeToString(
     354           0 :                 Quantity(itsMajValue, "rad"),
     355           0 :                 Quantity(itsMinValue, "rad"),
     356           0 :                 Quantity(itsPaValue, "rad"),
     357             :                 false
     358           0 :         );
     359             : }
     360             : 
     361             : //need to modify here
     362           0 : Double LimbDarkenedDiskShape::calcSample(const MDirection::MVType& compDirValue,
     363             :                     const MDirection::MVType& dirVal,
     364             :                     const Double majRad, const Double minRad,
     365             :                     const Double pixValue) const {
     366           0 :   const Double separation = compDirValue.separation(dirVal);
     367           0 :   if (separation <= majRad) {
     368           0 :     const Double pa = compDirValue.positionAngle(dirVal) - itsPaValue;
     369           0 :     const Double x = abs(separation*cos(pa));
     370           0 :     const Double y = abs(separation*sin(pa));
     371           0 :     if ((x <= majRad) &&
     372           0 :         (y <= minRad) &&
     373           0 :         (y <= minRad * sqrt(1 - square(x/majRad)))) {
     374           0 :       return pixValue;
     375             :     }
     376             :   }
     377           0 :   return 0.0;
     378             : }
     379             : 
     380           0 : Double LimbDarkenedDiskShape::calcVis(Double u, Double v, const Double factor) const {
     381           0 :   u *= itsMinValue;
     382           0 :   v *= itsMajValue;
     383           0 :   const double r = hypot(u, v) * factor;
     384           0 :   const double eta = 1 + itsAttnFactor/2.0;
     385             :   //return 2.0 * j1(r)/r;
     386             :   // Vi(u,v) for the limb-darkened disk from ALMA memo #594 
     387             :   // assume u, v are != 0.0 (in such case Vi(u,v)=Vo, handled in visibility())
     388           0 :   return pow(C::e,lgamma(eta + 1))*pow(2.0/r,eta)*gsl_sf_bessel_Jnu(eta,r); 
     389             : }
     390             : 
     391             : 
     392           0 : void LimbDarkenedDiskShape::rotateVis(Double& u, Double& v,
     393             :                         const Double cpa, const Double spa) {
     394           0 :   const Double utemp = u;
     395           0 :   u = u * cpa - v * spa;
     396           0 :   v = utemp * spa + v * cpa;
     397           0 : }
     398             : 
     399             : } //# NAMESPACE CASA - END

Generated by: LCOV version 1.16