LCOV - code coverage report
Current view: top level - imageanalysis/ImageAnalysis - MomentClip.tcc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 196 0.0 %
Date: 2024-12-11 20:54:31 Functions: 0 5 0.0 %

          Line data    Source code
       1             : //# MomentClip.cc:
       2             : //# Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003,2004
       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: MomentCalculator.tcc 19940 2007-02-27 05:35:22Z Malte.Marquarding $
      27             : //
      28             : 
      29             : #include <imageanalysis/ImageAnalysis/MomentClip.h>
      30             : 
      31             : namespace casa {
      32             : 
      33           0 : template <class T> MomentClip<T>::MomentClip(
      34             :     shared_ptr<casacore::Lattice<T>> pAncilliaryLattice, MomentsBase<T>& iMom,
      35             :     casacore::LogIO& os, const casacore::uInt nLatticeOut
      36           0 : ) : _ancilliaryLattice(pAncilliaryLattice), iMom_p(iMom), os_p(os) {
      37           0 :     selectMoments_p = this->selectMoments(iMom_p);
      38           0 :     constructorCheck(calcMoments_p, calcMomentsMask_p, selectMoments_p, nLatticeOut);
      39           0 :     casacore::Int momAxis = this->momentAxis(iMom_p);
      40           0 :     if (_ancilliaryLattice) {
      41           0 :         sliceShape_p.resize(_ancilliaryLattice->ndim());
      42           0 :         sliceShape_p = 1;
      43           0 :         sliceShape_p(momAxis) = _ancilliaryLattice->shape()(momAxis);
      44             :     }
      45             :     //this->yAutoMinMax(yMinAuto_p, yMaxAuto_p, iMom_p);
      46             : 
      47           0 :     this->selectRange(range_p, doInclude_p, doExclude_p, iMom_p);
      48             : 
      49           0 :     this->costlyMoments(iMom_p, doMedianI_p, doMedianV_p, doAbsDev_p);
      50             : 
      51             :     // Are we computing coordinate-dependent moments.  If so
      52             :     // precompute coordinate vector if moment axis separable
      53             : 
      54           0 :     this->setCoordinateSystem (cSys_p, iMom_p);
      55           0 :     this->doCoordCalc(doCoordProfile_p, doCoordRandom_p, iMom_p);
      56           0 :     this->setUpCoords(
      57           0 :         iMom_p, pixelIn_p, worldOut_p, sepWorldCoord_p, os_p,
      58           0 :         integratedScaleFactor_p, cSys_p, doCoordProfile_p,
      59           0 :         doCoordRandom_p
      60             :     );
      61             : 
      62             :     // What is the axis type of the moment axis
      63             : 
      64           0 :     momAxisType_p = this->momentAxisName(cSys_p, iMom_p);
      65             : 
      66             :     // Number of failed Gaussian fits
      67           0 :     nFailed_p = 0;
      68           0 : }
      69             : 
      70           0 : template <class T> MomentClip<T>::~MomentClip() {}
      71             : 
      72           0 : template <class T> void MomentClip<T>::process(
      73             :     T&, casacore::Bool&, const casacore::Vector<T>&, const casacore::Vector<casacore::Bool>&,
      74             :     const casacore::IPosition&
      75             : ) {
      76           0 :     ThrowCc("MomentClip<T>::process(Vector<T>&, IPosition&): not implemented");
      77             : }
      78             : 
      79           0 : template <class T> void MomentClip<T>::multiProcess(
      80             :     casacore::Vector<T>& moments, casacore::Vector<casacore::Bool>& momentsMask,
      81             :     const casacore::Vector<T>& profileIn, const casacore::Vector<casacore::Bool>& profileInMask,
      82             :     const casacore::IPosition& inPos
      83             : ) {
      84             :     // The profile comes with its own mask (or a null mask
      85             :     // which means all good).  In addition, we create
      86             :     // a further mask by applying the clip range to either
      87             :     // the primary lattice, or the ancilliary lattice (e.g.
      88             :     // the smoothed lattice)
      89             : 
      90             :     // Fish out the ancilliary image slice if needed.  Stupid slice functions
      91             :     // require me to create the slice empty every time so degenerate
      92             :     // axes can be chucked out.  We set up a pointer to the primary or
      93             :     // ancilliary vector object  that we can use for fast access
      94             : 
      95           0 :     const T* pProfileSelect = nullptr;
      96           0 :     auto deleteIt = false;
      97           0 :     if (_ancilliaryLattice && (doInclude_p || doExclude_p)) {
      98           0 :         casacore::Array<T> ancilliarySlice;
      99           0 :         casacore::IPosition stride(_ancilliaryLattice->ndim(),1);
     100           0 :         _ancilliaryLattice->getSlice(
     101           0 :             ancilliarySlice, inPos, sliceShape_p, stride, true
     102             :         );
     103           0 :         ancilliarySliceRef_p.reference(ancilliarySlice);
     104           0 :         pProfileSelect_p = &ancilliarySliceRef_p;
     105           0 :         pProfileSelect = ancilliarySliceRef_p.getStorage(deleteIt);
     106           0 :     }
     107             :     else {
     108           0 :         pProfileSelect_p = &profileIn;
     109           0 :         pProfileSelect = profileIn.getStorage(deleteIt);
     110             :     }
     111             :     // Resize array for median.  Is resized correctly later
     112           0 :     auto nPts = profileIn.size();
     113           0 :     selectedData_p.resize(nPts);
     114           0 :     selectedDataIndex_p.resize(nPts);
     115             : 
     116             :     // Were the profile coordinates precomputed ?
     117             : 
     118           0 :     auto preComp = sepWorldCoord_p.nelements() > 0;
     119             : 
     120             :     // We must fill in the input pixel coordinate if we need
     121             :     // coordinates, but did not pre compute them
     122           0 :     if (! preComp && (doCoordRandom_p || doCoordProfile_p)) {
     123           0 :         for (casacore::uInt i=0; i<inPos.size(); ++i) {
     124           0 :             pixelIn_p[i] = casacore::Double(inPos[i]);
     125             :         }
     126             :     }
     127             :     // Compute moments.  The actual moment computation always done with
     128             :     // the original data, regardless of whether the pixel selection is
     129             :     // done with the primary or ancilliary data.
     130             : 
     131           0 :     typename casacore::NumericTraits<T>::PrecisionType s0  = 0.0;
     132           0 :     typename casacore::NumericTraits<T>::PrecisionType s0Sq = 0.0;
     133           0 :     typename casacore::NumericTraits<T>::PrecisionType s1  = 0.0;
     134           0 :     typename casacore::NumericTraits<T>::PrecisionType s2  = 0.0;
     135           0 :     casacore::Int iMin = -1;
     136           0 :     casacore::Int iMax = -1;
     137           0 :     T dMin =  1.0e30;
     138           0 :     T dMax = -1.0e30;
     139           0 :     casacore::Double coord = 0.0;
     140             :     casacore::uInt i, j;
     141           0 :     if (profileInMask.empty()) {
     142             :         // No mask included.
     143           0 :         if (doInclude_p) {
     144           0 :             for (i=0,j=0; i<nPts; ++i) {
     145           0 :                 if (
     146           0 :                     pProfileSelect[i] >= range_p[0]
     147           0 :                     && pProfileSelect[i] <= range_p[1]
     148             :                 ) {
     149           0 :                     if (preComp) {
     150           0 :                         coord = sepWorldCoord_p(i);
     151             :                     }
     152           0 :                     else if (doCoordProfile_p) {
     153           0 :                         coord = this->getMomentCoord(
     154           0 :                             iMom_p, pixelIn_p,
     155           0 :                             worldOut_p, casacore::Double(i)
     156             :                         );
     157             :                     }
     158           0 :                     this->accumSums(
     159             :                         s0, s0Sq, s1, s2, iMin, iMax,
     160           0 :                         dMin, dMax, i, profileIn(i), coord
     161             :                     );
     162           0 :                     selectedData_p[j] = profileIn[i];
     163           0 :                     selectedDataIndex_p[j] = i;
     164           0 :                     ++j;
     165             :                 }
     166             :             }
     167           0 :             nPts = j;
     168             :         }
     169           0 :         else if (doExclude_p) {
     170           0 :             for (i=0,j=0; i<nPts; ++i) {
     171           0 :                 if (
     172           0 :                     pProfileSelect[i] <= range_p[0]
     173           0 :                     || pProfileSelect[i] >= range_p[1]
     174             :                 ) {
     175           0 :                     if (preComp) {
     176           0 :                         coord = sepWorldCoord_p[i];
     177             :                     }
     178           0 :                     else if (doCoordProfile_p) {
     179           0 :                         coord = this->getMomentCoord(
     180           0 :                             iMom_p, pixelIn_p,
     181           0 :                             worldOut_p, casacore::Double(i)
     182             :                         );
     183             :                     }
     184           0 :                     this->accumSums(
     185             :                         s0, s0Sq, s1, s2, iMin, iMax,
     186           0 :                         dMin, dMax, i, profileIn[i], coord
     187             :                     );
     188           0 :                     selectedData_p[j] = profileIn[i];
     189           0 :                     selectedDataIndex_p[j] = i;
     190           0 :                     ++j;
     191             :                 }
     192             :             }
     193           0 :             nPts = j;
     194             :         }
     195             :         else {
     196           0 :             for (i=0; i<nPts; ++i) {
     197           0 :                 if (preComp) {
     198           0 :                     coord = sepWorldCoord_p[i];
     199             :                 }
     200           0 :                 else if (doCoordProfile_p) {
     201           0 :                     coord = this->getMomentCoord(
     202           0 :                         iMom_p, pixelIn_p,
     203           0 :                         worldOut_p, casacore::Double(i)
     204             :                     );
     205             :                 }
     206           0 :                 this->accumSums(
     207             :                     s0, s0Sq, s1, s2, iMin, iMax,
     208           0 :                     dMin, dMax, i, profileIn[i], coord
     209             :                 );
     210           0 :                 selectedData_p[i] = profileIn[i];
     211           0 :                 selectedDataIndex_p[i] = i;
     212             :             }
     213             :         }
     214             :     }
     215             :     else {
     216             :         // Set up a pointer for faster access to the profile mask
     217           0 :         auto deleteIt2 = false;
     218           0 :         const auto* pProfileInMask = profileInMask.getStorage(deleteIt2);
     219             : 
     220           0 :         if (doInclude_p) {
     221           0 :             for (i=0, j=0; i<nPts; ++i) {
     222           0 :                 if (
     223           0 :                     pProfileInMask[i]
     224           0 :                     && pProfileSelect[i] >= range_p(0)
     225           0 :                     && pProfileSelect[i] <= range_p(1)
     226             :                 ) {
     227           0 :                     if (preComp) {
     228           0 :                         coord = sepWorldCoord_p[i];
     229             :                     }
     230           0 :                     else if (doCoordProfile_p) {
     231           0 :                         coord = this->getMomentCoord(
     232           0 :                             iMom_p, pixelIn_p, worldOut_p, casacore::Double(i)
     233             :                         );
     234             :                     }
     235           0 :                     this->accumSums(
     236             :                         s0, s0Sq, s1, s2, iMin, iMax,
     237           0 :                         dMin, dMax, i, profileIn(i), coord
     238             :                     );
     239           0 :                     selectedData_p[j] = profileIn[i];
     240           0 :                     selectedDataIndex_p[j] = i;
     241           0 :                     ++j;
     242             :                 }
     243             :             }
     244             :         }
     245           0 :         else if (doExclude_p) {
     246           0 :             for (i=0, j=0; i<nPts; ++i) {
     247           0 :                 if (
     248           0 :                     pProfileInMask[i]
     249           0 :                     && (
     250           0 :                         pProfileSelect[i] <= range_p[0]
     251           0 :                         || pProfileSelect[i] >= range_p[1]
     252             :                     )
     253             :                 ) {
     254           0 :                     if (preComp) {
     255           0 :                         coord = sepWorldCoord_p(i);
     256             :                     }
     257           0 :                     else if (doCoordProfile_p) {
     258           0 :                         coord = this->getMomentCoord(
     259           0 :                             iMom_p, pixelIn_p,
     260           0 :                             worldOut_p, casacore::Double(i)
     261             :                         );
     262             :                     }
     263           0 :                     this->accumSums(
     264             :                         s0, s0Sq, s1, s2, iMin, iMax,
     265           0 :                         dMin, dMax, i, profileIn[i], coord
     266             :                     );
     267           0 :                     selectedData_p[j] = profileIn[i];
     268           0 :                     selectedDataIndex_p[j] = i;
     269           0 :                     ++j;
     270             :                 }
     271             :             }
     272             :         } else {
     273           0 :             for (i=0,j=0; i<nPts; ++i) {
     274           0 :                 if (pProfileInMask[i]) {
     275           0 :                     if (preComp) {
     276           0 :                         coord = sepWorldCoord_p[i];
     277             :                     }
     278           0 :                     else if (doCoordProfile_p) {
     279           0 :                         coord = this->getMomentCoord(
     280           0 :                             iMom_p, pixelIn_p,
     281           0 :                             worldOut_p, casacore::Double(i)
     282             :                         );
     283             :                     }
     284           0 :                     this->accumSums(
     285             :                         s0, s0Sq, s1, s2, iMin, iMax,
     286           0 :                         dMin, dMax, i, profileIn[i], coord
     287             :                     );
     288           0 :                     selectedData_p[j] = profileIn[i];
     289           0 :                     selectedDataIndex_p[j] = i;
     290           0 :                     ++j;
     291             :                 }
     292             :             }
     293             :         }
     294           0 :         nPts = j;
     295           0 :         profileInMask.freeStorage(pProfileInMask, deleteIt2);
     296             :     }
     297             :     // Delete pointer memory
     298           0 :     if (_ancilliaryLattice && (doInclude_p || doExclude_p)) {
     299           0 :         ancilliarySliceRef_p.freeStorage(pProfileSelect, deleteIt);
     300             :     }
     301             :     else {
     302           0 :         profileIn.freeStorage(pProfileSelect, deleteIt);
     303             :     }
     304             :     // If no points make moments zero and mask
     305           0 :     if (nPts == 0) {
     306           0 :         moments = 0.0;
     307           0 :         momentsMask = false;
     308           0 :         return;
     309             :     }
     310             :     // Absolute deviations of I from mean needs an extra pass.
     311           0 :     typename casacore::NumericTraits<T>::PrecisionType sumAbsDev = 0;
     312           0 :     if (doAbsDev_p) {
     313           0 :         T iMean = s0 / nPts;
     314           0 :         for (i=0; i<nPts; ++i) {
     315           0 :             sumAbsDev += abs(selectedData_p(i) - iMean);
     316             :         }
     317             :     }
     318             :     // Median of I
     319           0 :     T dMedian = 0.0;
     320           0 :     if (doMedianI_p) {
     321           0 :         selectedData_p.resize(nPts,true);
     322           0 :         dMedian = median(selectedData_p);
     323             :     }
     324             :     // Median coordinate.  ImageMoments will only be allowing this if
     325             :     // we are not offering the ancilliary lattice, and with an include
     326             :     // or exclude range.   Pretty dodgy
     327           0 :     T vMedian(0.0);
     328           0 :     if (doMedianV_p) {
     329           0 :         if (doInclude_p || doExclude_p) {
     330             :             // Treat spectrum as a probability distribution for velocity
     331             :             // and generate cumulative probability (it's already sorted
     332             :             // of course).
     333           0 :             selectedData_p.resize(nPts,true);
     334           0 :             selectedData_p(0) = abs(selectedData_p[0]);
     335           0 :             auto dataMax = selectedData_p[0];
     336           0 :             for (i=1; i<nPts; ++i) {
     337           0 :                 selectedData_p[i] += abs(selectedData_p[i-1]);
     338           0 :                 dataMax = max(dataMax, selectedData_p[i]);
     339             :             }
     340             :             // Find 1/2 way value (well, the first one that occurs)
     341             : 
     342           0 :             auto halfMax = dataMax/2.0;
     343           0 :             casacore::Int iVal = 0;
     344           0 :             for (i=0; i<nPts; ++i) {
     345           0 :                 if (selectedData_p[i] >= halfMax) {
     346           0 :                     iVal = i;
     347           0 :                     break;
     348             :                 }
     349             :             }
     350             :             // Linearly interpolate to velocity index
     351             :             casacore::Double interpPixel;
     352           0 :             if (iVal > 0) {
     353           0 :                 casacore::Double m = (selectedData_p[iVal] - selectedData_p[iVal-1])
     354           0 :                     / (selectedDataIndex_p[iVal] - selectedDataIndex_p[iVal-1]);
     355           0 :                 casacore::Double b = selectedData_p[iVal] - m*selectedDataIndex_p[iVal];
     356           0 :                 interpPixel = (selectedData_p[iVal] - b)/m;
     357             :             }
     358             :             else {
     359           0 :                 interpPixel = selectedDataIndex_p[iVal];
     360             :             }
     361             :             // Find world coordinate of that pixel on the moment axis
     362           0 :             vMedian = this->getMomentCoord(
     363           0 :                 iMom_p, pixelIn_p, worldOut_p, interpPixel,
     364           0 :                 iMom_p.shouldConvertToVelocity()
     365             :             );
     366             :         }
     367             :     }
     368             :     // Fill all moments array
     369           0 :     this->setCalcMoments(
     370           0 :         iMom_p, calcMoments_p, calcMomentsMask_p, pixelIn_p, worldOut_p,
     371           0 :         doCoordRandom_p, integratedScaleFactor_p,
     372             :         dMedian, vMedian, nPts, s0, s1, s2, s0Sq,
     373             :         sumAbsDev, dMin, dMax, iMin, iMax
     374             :     );
     375             :     // Fill vector of selected moments
     376           0 :     for (i=0; i<selectMoments_p.size(); ++i) {
     377           0 :         moments[i] = calcMoments_p(selectMoments_p[i]);
     378           0 :         momentsMask[i] = calcMomentsMask_p(selectMoments_p[i]);
     379             :     }
     380             : }
     381             : 
     382             : }
     383             : 

Generated by: LCOV version 1.16