LCOV - code coverage report
Current view: top level - components/ComponentModels - DiskShape.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 200 0.0 %
Date: 2024-10-04 16:51:10 Functions: 0 25 0.0 %

          Line data    Source code
       1             : //# DiskShape.cc:
       2             : //# Copyright (C) 1998,1999,2000
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This library is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU Library General Public License as published by
       7             : //# the Free Software Foundation; either version 2 of the License, or (at your
       8             : //# option) any later version.
       9             : //#
      10             : //# This library is distributed in the hope that it will be useful, but WITHOUT
      11             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
      13             : //# License for more details.
      14             : //#
      15             : //# You should have received a copy of the GNU Library General Public License
      16             : //# along with this library; if not, write to the Free Software Foundation,
      17             : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      18             : //#
      19             : //# Correspondence concerning AIPS++ should be addressed as follows:
      20             : //#        Internet email: casa-feedback@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : //#
      26             : //# $Id: DiskShape.cc 21130 2011-10-18 07:39:05Z gervandiepen $
      27             : 
      28             : #include <components/ComponentModels/DiskShape.h>
      29             : #include <components/ComponentModels/Flux.h>
      30             : #include <casacore/casa/Arrays/Matrix.h>
      31             : #include <casacore/casa/Arrays/Vector.h>
      32             : #include <casacore/casa/Arrays/VectorIter.h>
      33             : #include <casacore/casa/Arrays/ArrayMath.h>
      34             : #include <casacore/casa/Arrays/Array.h>
      35             : #include <casacore/casa/Exceptions/Error.h>
      36             : #include <casacore/casa/Logging/LogIO.h>
      37             : #include <casacore/casa/Logging/LogOrigin.h>
      38             : #include <casacore/casa/BasicSL/Constants.h>
      39             : #include <casacore/casa/BasicMath/Math.h>
      40             : #include <casacore/measures/Measures/MCDirection.h>
      41             : #include <casacore/measures/Measures/MDirection.h>
      42             : #include <casacore/measures/Measures/MeasConvert.h>
      43             : #include <casacore/measures/Measures/MeasRef.h>
      44             : #include <casacore/casa/Quanta/MVAngle.h>
      45             : #include <casacore/casa/Quanta/MVDirection.h>
      46             : #include <casacore/casa/Quanta/Quantum.h>
      47             : #include <casacore/casa/Utilities/Assert.h>
      48             : #include <casacore/casa/BasicSL/String.h>
      49             : #include <cmath>
      50             : 
      51             : using namespace casacore;
      52             : namespace casa { //# NAMESPACE CASA - BEGIN
      53             : 
      54           0 : DiskShape::DiskShape()
      55             :   :TwoSidedShape(),
      56           0 :    _majorAxis(Quantity(1,"'").getValue("rad")),
      57           0 :    _minorAxis(Quantity(1,"'").getValue("rad")),
      58           0 :    _pa(Quantity(0,"deg").getValue("rad")),
      59           0 :    _recipArea(1.0/_area())
      60             : {
      61           0 :   DebugAssert(ok(), AipsError);
      62           0 : }
      63             : 
      64           0 : DiskShape::DiskShape(const MDirection& direction, 
      65             :              const Quantum<Double>& majorAxis,
      66             :              const Quantum<Double>& minorAxis,
      67           0 :              const Quantum<Double>& positionAngle)
      68           0 :   :TwoSidedShape(direction, majorAxis.getFullUnit(),
      69           0 :          minorAxis.getFullUnit(), positionAngle.getFullUnit()),
      70           0 :    _majorAxis(majorAxis.getValue("rad")),
      71           0 :    _minorAxis(minorAxis.getValue("rad")),
      72           0 :    _pa(positionAngle.getValue("rad")),
      73           0 :    _recipArea(1.0/_area())
      74             : {
      75           0 :   DebugAssert(ok(), AipsError);
      76           0 : }
      77             : 
      78           0 : DiskShape::DiskShape(const MDirection& direction,
      79             :              const Quantum<Double>& width,
      80             :              const Double axialRatio,
      81           0 :              const Quantum<Double>& positionAngle) 
      82           0 :   :TwoSidedShape(direction, width.getFullUnit(),
      83           0 :          width.getFullUnit(), positionAngle.getFullUnit()),
      84           0 :    _majorAxis(width.getValue("rad")),
      85           0 :    _minorAxis(_majorAxis*axialRatio),
      86           0 :    _pa(positionAngle.getValue("rad")),
      87           0 :    _recipArea(1.0/_area())
      88             : {
      89           0 :   DebugAssert(ok(), AipsError);
      90           0 : }
      91             : 
      92           0 : DiskShape::DiskShape(const DiskShape& other) 
      93             :   :TwoSidedShape(other),
      94           0 :    _majorAxis(other._majorAxis),
      95           0 :    _minorAxis(other._minorAxis),
      96           0 :    _pa(other._pa),
      97           0 :    _recipArea(other._recipArea)
      98             : {
      99           0 :   DebugAssert(ok(), AipsError);
     100           0 : }
     101             : 
     102           0 : DiskShape::~DiskShape() {
     103           0 :   DebugAssert(ok(), AipsError);
     104           0 : }
     105             : 
     106           0 : DiskShape& DiskShape::operator=(const DiskShape& other) {
     107           0 :   if (this != &other) {
     108           0 :     TwoSidedShape::operator=(other);
     109           0 :     _majorAxis = other._majorAxis;
     110           0 :     _minorAxis = other._minorAxis;
     111           0 :     _pa = other._pa;
     112           0 :     _recipArea = other._recipArea;
     113             :   }
     114           0 :   DebugAssert(ok(), AipsError);
     115           0 :   return *this;
     116             : }
     117             : 
     118           0 : ComponentType::Shape DiskShape::type() const {
     119           0 :   DebugAssert(ok(), AipsError);
     120           0 :   return ComponentType::DISK;
     121             : }
     122             : 
     123           0 : void DiskShape::setWidthInRad(const Double majorAxis,
     124             :                   const Double minorAxis, 
     125             :                   const Double positionAngle) {
     126             :   static const double epsilon = 1.0e-17;
     127           0 :   _majorAxis = majorAxis;
     128           0 :   _minorAxis = minorAxis;
     129           0 :   _minorAxis = std::abs(majorAxis-minorAxis) < epsilon ? majorAxis : minorAxis;
     130           0 :   _pa = positionAngle;
     131           0 :   AlwaysAssert(_majorAxis > 0 && _minorAxis > 0 && _majorAxis >=_minorAxis,
     132             :             AipsError);
     133           0 :   _recipArea = 1.0/_area();
     134           0 :   DebugAssert(ok(), AipsError);
     135           0 : }
     136             : 
     137           0 : Double DiskShape::majorAxisInRad() const {
     138           0 :   DebugAssert(ok(), AipsError);
     139           0 :   return _majorAxis;
     140             : }
     141             : 
     142           0 : Double DiskShape::minorAxisInRad() const {
     143           0 :   DebugAssert(ok(), AipsError);
     144           0 :   return _minorAxis;
     145             : }
     146             : 
     147           0 : Double DiskShape::positionAngleInRad() const {
     148           0 :   DebugAssert(ok(), AipsError);
     149           0 :   return _pa;
     150             : }
     151             : 
     152           0 : Double DiskShape::sample(const MDirection& direction, 
     153             :              const MVAngle& pixelLatSize,
     154             :              const MVAngle& pixelLongSize) const {
     155           0 :   DebugAssert(ok(), AipsError);
     156           0 :   const MDirection& compDir(refDirection());
     157           0 :   const MDirection::Ref& compDirFrame(compDir.getRef());
     158           0 :   const MDirection::MVType* compDirValue = &(compDir.getValue());
     159           0 :   Bool deleteValue = false;
     160             :   // Convert direction to the same frame as the reference direction
     161           0 :   if (ComponentShape::differentRefs(direction.getRef(), compDirFrame)) {
     162           0 :     compDirValue = new MDirection::MVType
     163           0 :       (MDirection::Convert(compDir, direction.getRef())().getValue());
     164           0 :     deleteValue = true;
     165             :   }
     166           0 :   Double retVal = _calcSample(*compDirValue, direction.getValue(),
     167           0 :                  _majorAxis/2.0, _minorAxis/2.0, 
     168           0 :                  _recipArea*pixelLatSize.radian()*
     169           0 :                  pixelLongSize.radian());
     170           0 :   if (deleteValue) delete compDirValue;
     171           0 :   return retVal;
     172           0 : }
     173             : 
     174           0 : void DiskShape::sample(Vector<Double>& scale, 
     175             :                const Vector<MVDirection>& directions, 
     176             :                const MDirection::Ref& refFrame,
     177             :                const MVAngle& pixelLatSize,
     178             :                const MVAngle& pixelLongSize) const {
     179           0 :   DebugAssert(ok(), AipsError);
     180           0 :   const uInt nSamples = directions.nelements();
     181           0 :   DebugAssert(scale.nelements() == nSamples, AipsError);
     182             : 
     183           0 :   const MDirection& compDir(refDirection());
     184           0 :   const MDirection::Ref& compDirFrame(compDir.getRef());
     185           0 :   const MDirection::MVType* compDirValue = &(compDir.getValue());
     186           0 :   Bool deleteValue = false;
     187             :   // Convert direction to the same frame as the reference direction
     188           0 :   if (refFrame != compDirFrame) {
     189           0 :     compDirValue = new MDirection::MVType
     190           0 :       (MDirection::Convert(compDir, refFrame)().getValue());
     191           0 :     deleteValue = true;
     192             :   }
     193           0 :   const Double majRad = _majorAxis/2.0; 
     194           0 :   const Double minRad = _minorAxis/2.0; 
     195           0 :   const Double pixValue = _recipArea * 
     196           0 :     pixelLatSize.radian() * pixelLongSize.radian();
     197           0 :   for (uInt i = 0; i < nSamples; i++) {
     198           0 :     scale(i) = _calcSample(*compDirValue, directions(i), 
     199             :               majRad, minRad, pixValue);
     200             :   }
     201           0 :   if (deleteValue) delete compDirValue;
     202           0 : }
     203             : 
     204           0 : DComplex DiskShape::visibility(const Vector<Double>& uvw,
     205             :                    const Double& frequency) const {
     206           0 :   DebugAssert(uvw.nelements() == 3, AipsError);
     207           0 :   DebugAssert(frequency > 0, AipsError);
     208           0 :   DebugAssert(ok(), AipsError);
     209           0 :   Double u = uvw(0);
     210           0 :   Double v = uvw(1);
     211           0 :   if (near(u + v, 0.0)) return DComplex(1.0, 0.0);
     212           0 :   if (!nearAbs(_pa, 0.0)) {
     213           0 :     _rotateVis(u, v, cos(_pa), sin(_pa));
     214             :   }
     215           0 :   return DComplex(_calcVis(u, v, C::pi * frequency/C::c), 0.0);
     216             : }
     217             : 
     218           0 : void DiskShape::visibility(Matrix<DComplex>& scale,
     219             :                const Matrix<Double>& uvw,
     220             :                const Vector<Double>& frequency) const {
     221             : 
     222           0 :   scale.resize(uvw.ncolumn(), frequency.nelements());
     223             : 
     224           0 :   VectorIterator<DComplex> iter(scale, 0);
     225           0 :   for ( uInt k =0 ; k < frequency.nelements() ; ++k){
     226           0 :     visibility(iter.vector(), uvw, frequency(k));
     227           0 :     iter.next(); 
     228             :   }
     229           0 : }
     230             : 
     231           0 : void DiskShape::visibility(Vector<DComplex>& scale,
     232             :                const Matrix<Double>& uvw,
     233             :                const Double& frequency) const {
     234           0 :   DebugAssert(ok(), AipsError);
     235           0 :   const uInt nSamples = scale.nelements();
     236           0 :   DebugAssert(uvw.ncolumn() == nSamples, AipsError);
     237           0 :   DebugAssert(uvw.nrow() == 3, AipsError);
     238           0 :   DebugAssert(frequency > 0, AipsError);
     239             :   
     240           0 :   Bool doRotation = false;
     241           0 :   Double cpa = 1.0, spa = 0.0;
     242           0 :   if (!nearAbs(_pa, 0.0)) {
     243           0 :     doRotation = true;
     244           0 :     cpa = cos(_pa);
     245           0 :     spa = sin(_pa);
     246             :   }
     247             : 
     248           0 :   const Double factor = C::pi * frequency/C::c;
     249             :   Double u, v;
     250           0 :   for (uInt i = 0; i < nSamples; i++) {
     251           0 :     u = uvw(0, i);
     252           0 :     v = uvw(1, i);
     253             :     // DComplex& thisVis = scale(i);
     254             :     ///    thisVis.imag() = 0.0;
     255           0 :     if (near(u + v, 0.0)) {
     256             :       ///      thisVis.real() = 1.0; // avoids dividing by zero in _calcVis(...)
     257           0 :       scale[i] = DComplex(1.0, 0.0); // avoids dividing by zero
     258             :       // in _calcVis(...)
     259             :     } else {
     260           0 :       if (doRotation) _rotateVis(u, v, cpa, spa);
     261             :       ///      thisVis.real() = _calcVis(u, v, factor);
     262           0 :       scale[i] = DComplex(_calcVis(u, v, factor), 0.0);
     263             :     }
     264             :   }
     265           0 : }
     266             : 
     267           0 : ComponentShape* DiskShape::clone() const {
     268           0 :   DebugAssert(ok(), AipsError);
     269           0 :   ComponentShape* tmpPtr = new DiskShape(*this);
     270           0 :   AlwaysAssert(tmpPtr != 0, AipsError);
     271           0 :   return tmpPtr;
     272             : }
     273             : 
     274           0 : Bool DiskShape::ok() const {
     275             :   // The LogIO class is only constructed if an error is detected for
     276             :   // performance reasons. Both function static and file static variables
     277             :   // where considered and rejected for this purpose.
     278           0 :   if (!TwoSidedShape::ok()) return false; 
     279           0 :   if (_majorAxis <= 0) {
     280           0 :     LogIO logErr(LogOrigin("DiskCompRep", "ok()"));
     281             :     logErr << LogIO::SEVERE << "The major axis width is zero or negative"
     282           0 :            << LogIO::POST;
     283           0 :     return false;
     284           0 :   }
     285           0 :   if (_minorAxis <= 0) {
     286           0 :     LogIO logErr(LogOrigin("DiskCompRep", "ok()"));
     287             :     logErr << LogIO::SEVERE << "The minor axis width is zero or negative"
     288           0 :            << LogIO::POST;
     289           0 :     return false;
     290           0 :   }
     291           0 :   if (_minorAxis > _majorAxis) {
     292           0 :     LogIO logErr(LogOrigin("DiskCompRep", "ok()"));
     293             :     logErr << LogIO::SEVERE << "The minor axis width is larger than "
     294             :        << "the major axis width"
     295           0 :            << LogIO::POST;
     296           0 :     return false;
     297           0 :   }
     298           0 :   if (!near(_recipArea, 1.0/_area(), 2*C::dbl_epsilon)) {
     299           0 :     LogIO logErr(LogOrigin("DiskCompRep", "ok()"));
     300             :     logErr << LogIO::SEVERE << "The disk shape does not have"
     301             :        << " unit area"
     302           0 :            << LogIO::POST;
     303           0 :     return false;
     304           0 :   }
     305           0 :   return true;
     306             : }
     307             : 
     308           0 : const ComponentShape* DiskShape::getPtr() const {
     309           0 :     return this;
     310             : }
     311             : 
     312           0 : Double DiskShape::_calcVis(Double u, Double v, const Double factor) const {
     313           0 :   u *= _minorAxis;
     314           0 :   v *= _majorAxis;
     315           0 :   const Double r = hypot(u, v) * factor;
     316           0 :   return 2.0 * j1(r)/r;
     317             : }
     318             : 
     319           0 : void DiskShape::_rotateVis(Double& u, Double& v, 
     320             :               const Double cpa, const Double spa) {
     321           0 :   const Double utemp = u;
     322           0 :   u = u * cpa - v * spa;
     323           0 :   v = utemp * spa + v * cpa;
     324           0 : }
     325             : 
     326           0 : Double DiskShape::_area() const {
     327           0 :     return C::pi_4 * _majorAxis * _minorAxis; 
     328             : }
     329             : 
     330           0 : Double DiskShape::_calcSample(const MDirection::MVType& compDirValue, 
     331             :                  const MDirection::MVType& dirVal, 
     332             :                  const Double majRad, const Double minRad, 
     333             :                  const Double pixValue) const {
     334           0 :   const Double separation = compDirValue.separation(dirVal);
     335           0 :   if (separation <= majRad) {
     336           0 :     const Double pa = compDirValue.positionAngle(dirVal) - _pa;
     337           0 :     const Double x = abs(separation*cos(pa));
     338           0 :     const Double y = abs(separation*sin(pa));
     339           0 :     if ((x <= majRad) && 
     340           0 :     (y <= minRad) && 
     341           0 :     (y <= minRad * sqrt(1 - square(x/majRad)))) {
     342           0 :       return pixValue;
     343             :     }
     344             :   }
     345           0 :   return 0.0;
     346             : }
     347             : 
     348           0 : String DiskShape::sizeToString() const {
     349             :     return TwoSidedShape::sizeToString(
     350           0 :         Quantity(_majorAxis, "rad"),
     351           0 :         Quantity(_minorAxis, "rad"),
     352           0 :         Quantity(_pa, "rad"),
     353             :         false
     354           0 :     );
     355             : }
     356             : 
     357             : } 
     358             : 

Generated by: LCOV version 1.16