// ----------------------------------------------------------------------- // spectraUtils.cc: Utility functions to obtain & manipulate spectra // ----------------------------------------------------------------------- // Copyright (C) 2006, Matthew Whiting, 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. // // Duchamp 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 Duchamp; if not, write to the Free Software Foundation, // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA // // Correspondence concerning Duchamp may be directed to: // Internet email: Matthew.Whiting [at] atnf.csiro.au // Postal address: Dr. Matthew Whiting // Australia Telescope National Facility, CSIRO // PO Box 76 // Epping NSW 1710 // AUSTRALIA // ----------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace PixelInfo; namespace duchamp { void getSpecAbscissae(Detection &object, FitsHeader &head, size_t zdim, float *abscissae) { /// @details /// A function that returns an array of /// frequency/velocity/channel/etc values (that can be used as the /// abscissae on the spectral plot). /// \param object The object on which our spectrum is centered (in /// case the spectral value changes with x & y /// \param head The FitsHeader set of parameters that determine the coordinate transformation. /// \param zdim The length of the spectral axis /// \param abscissae The array of spectral values -- must be allocated first getSpecAbscissae(head,object.getXcentre(),object.getYcentre(),zdim, abscissae); } void getSpecAbscissae(FitsHeader &head, float xpt, float ypt, size_t zdim, float *abscissae) { /// @details /// A function that returns an array of /// frequency/velocity/channel/etc values (that can be used as the /// horizontal axis on the spectral plot). /// \param head The FitsHeader set of parameters that determine the coordinate transformation. /// \param xpt The x-value of the spatial position on which our spectrum is centred. /// \param ypt The y-value of the spatial position on which our spectrum is centred. /// \param zdim The length of the spectral axis /// \param abscissae The array of spectral values -- must be allocated first. if(head.isWCS()){ double xval = double(xpt); double yval = double(ypt); for(double zval=0;zval mask, float beamCorrection, float *spec) { /// @details /// The base function that extracts an integrated spectrum for a /// given object from a pixel array. The spectrum is returned as /// the integrated flux, corrected for the beam using the given /// correction factor. /// \param object The Detection in question /// \param fluxArray The full array of pixel values. /// \param dimArray The axis dimensions for the fluxArray /// \param mask A mask array indicating whether given pixels are valid /// \param beamCorrection How much to divide the summed spectrum /// by to return the integrated flux. /// \param spec The integrated spectrum for the object -- must be allocated first. for(size_t i=0;i done(xySize,false); std::vector voxlist = object.getPixelSet(); std::vector::iterator vox; for(vox=voxlist.begin();voxgetX() + dimArray[0] * vox->getY(); if(!done[pos]){ done[pos] = true; for(size_t z=0;z mask, float *spec) { /// @details /// The base function that extracts an peak spectrum for a /// given object from a pixel array. The spectrum is returned as /// the integrated flux, corrected for the beam using the given /// correction factor. /// \param object The Detection in question /// \param fluxArray The full array of pixel values. /// \param dimArray The axis dimensions for the fluxArray /// \param mask A mask array indicating whether given pixels are valid /// \param spec The peak spectrum for the object -- must be allocated first if((object.getXPeak()<0 || object.getXPeak()>=int(dimArray[0])) || (object.getYPeak()<0 || object.getYPeak()>=int(dimArray[1]))){ DUCHAMPWARN("getPeakSpec","Object peak outside array boundaries"); for (size_t z=0;zaxisDim[0]; size_t ydim = this->axisDim[1]; size_t zdim = this->axisDim[2]; for(size_t i=0;i voxlist; if(objNum>=0){ if(this->par.getSpectralMethod()=="sum"){ xloc=double(this->objectList->at(objNum).getXcentre()); yloc=double(this->objectList->at(objNum).getYcentre()); voxlist = this->objectList->at(objNum).getPixelSet(); } else{ spatpos = this->objectList->at(objNum).getXPeak() + xdim*this->objectList->at(objNum).getYPeak(); xloc = spatpos % xdim; yloc = spatpos / xdim; } } if(this->head.isWCS()){ for(double zval=0;zvalhead.pixToVel(xloc,yloc,zval); } else { for(double zval=0;zvalheader().needBeamSize()) beamCorrection = this->head.beam().area(); else beamCorrection = 1.; if(objNum>=0 && this->par.getSpectralMethod()=="sum"){ std::vector done(xdim*ydim,false); std::vector::iterator vox; for(vox=voxlist.begin();voxgetX() + xdim * vox->getY(); if(!done[spatpos]){ done[spatpos] = true; for(size_t z=0;zisBlank(spatpos+z*xdim*ydim))){ specy[z] += this->array[spatpos + z*xdim*ydim] / beamCorrection; if(this->reconExists) specRecon[z] += this->recon[spatpos + z*xdim*ydim] / beamCorrection; if(this->par.getFlagBaseline()) specBase[z] += this->baseline[spatpos + z*xdim*ydim] / beamCorrection; } } } } } else {// if(par.getSpectralMethod()=="peak"){ // size_t spatpos = this->objectList->at(objNum).getXPeak() + // xdim*this->objectList->at(objNum).getYPeak(); for(size_t z=0;zarray[spatpos + z*xdim*ydim]; if(this->reconExists) specRecon[z] = this->recon[spatpos + z*xdim*ydim]; if(this->par.getFlagBaseline()) specBase[z] = this->baseline[spatpos + z*xdim*ydim]; } } } //-------------------------------------------------------------------- void getSmallVelRange(Detection &obj, FitsHeader &head, double *minvel, double *maxvel) { /// @details /// Routine to calculate the velocity range for the zoomed-in region. /// This range should be the maximum of 20 pixels, or 3x the wdith of /// the detection. /// Need to : /// Calculate pixel width of a 3x-detection-width region. /// If smaller than 20, calculate velocities of central vel +- 10 pixels /// If not, use the 3x-detection-width /// Range returned via "minvel" and "maxvel" parameters. /// \param obj Detection under examination. /// \param head FitsHeader, containing the WCS information. /// \param minvel Returned value of minimum velocity /// \param maxvel Returned value of maximum velocity double *pixcrd = new double[3]; double *world = new double[3]; float minpix,maxpix; // define new velocity extrema // -- make it 3x wider than the width of the detection. *minvel = 0.5*(obj.getVelMin()+obj.getVelMax()) - 1.5*obj.getVelWidth(); *maxvel = 0.5*(obj.getVelMin()+obj.getVelMax()) + 1.5*obj.getVelWidth(); // Find velocity range in number of pixels: world[0] = obj.getRA(); world[1] = obj.getDec(); world[2] = head.velToSpec(*minvel); head.wcsToPix(world,pixcrd); minpix = pixcrd[2]; world[2] = head.velToSpec(*maxvel); head.wcsToPix(world,pixcrd); maxpix = pixcrd[2]; if(maxpix