Changeset 369


Ignore:
Timestamp:
02/06/05 17:40:28 (19 years ago)
Author:
vor010
Message:

SDLineFinder: bug corrections, setOption method
has been added + fitting baseline at each iterations to cope with bad
baselines

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/python/asaplinefind.py

    r331 r369  
    1313        return
    1414
     15    def set_options(self,threshold=1.7320508075688772,min_nchan=3,
     16        avg_limit=8,box_size=0.2):
     17        """
     18        Set the parameters of the algorithm
     19        Parameters:
     20             threshold    a single channel S/N ratio above which the
     21                          channel is considered to be a detection
     22                          Default is sqrt(3), which together with
     23                          min_nchan=3 gives a 3-sigma criterion
     24             min_nchan    a minimal number of consequtive channels,
     25                          which should satisfy a threshold criterion to
     26                          be a detection. Default is 3.
     27             avg_limit    A number of consequtive channels not greater than
     28                          this parameter can be averaged to search for
     29                          broad lines. Default is 8.
     30             box_size     A running mean box size specified as a fraction
     31                          of the total spectrum length. Default is 1/5
     32        Note:  For bad baselines threshold should be increased,
     33               and avg_limit decreased (or even switched off completely by
     34               setting this parameter to 1) to avoid detecting baseline
     35               undulations instead of real lines. 
     36        """
     37        self.finder.setoptions(threshold,min_nchan,avg_limit,box_size)
     38        return
     39             
    1540    def set_scan(self,scan,mask=None,edge=(0,0)):
    1641        """
  • trunk/src/SDLineFinder.cc

    r368 r369  
    3333// ASAP
    3434#include "SDLineFinder.h"
     35#include "SDFitter.h"
    3536
    3637// STL
     
    434435      // determine the off-line variance first
    435436      // an assumption made: lines occupy a small part of the spectrum
    436 
     437       
    437438      std::vector<float> variances(edge.second-edge.first);
    438439      DebugAssert(variances.size(),AipsError);
    439 
     440     
    440441      for (;running_box->haveMore();running_box->next())
    441442           variances[running_box->getChannel()-edge.first]=
    442443                                running_box->getLinVariance();
    443                                
     444       
    444445      // in the future we probably should do a proper Chi^2 estimation
    445446      // now a simple 80% of smaller values will be used.
     
    447448      // due to a bias of the Chi^2 distribution.
    448449      stable_sort(variances.begin(),variances.end());
     450     
    449451      Float offline_variance=0;
    450452      uInt offline_cnt=uInt(0.8*variances.size());     
     
    459461      Vector<Int> signs(spectrum.nelements(),0);
    460462
    461       ofstream os("dbg.dat");
     463      //ofstream os("dbg.dat");
    462464      for (running_box->rewind();running_box->haveMore();
    463465                                 running_box->next()) {
     
    471473           else if (buf<0) signs[ch]=-1;
    472474           else if (buf==0) signs[ch]=0;
    473            os<<ch<<" "<<spectrum[ch]<<" "<<running_box->getLinMean()<<" "<<
    474                         threshold*offline_variance<<endl;
     475        //   os<<ch<<" "<<spectrum[ch]<<" "<<running_box->getLinMean()<<" "<<
     476          //              threshold*offline_variance<<endl;
    475477      }
    476478      if (lines.size())
     
    578580SDLineFinder::SDLineFinder() throw() : edge(0,0)
    579581{
    580   // detection threshold - the minimal signal to noise ratio
    581   threshold=sqrt(3.); // 3 sigma and 3 channels is a default -> sqrt(3) in
    582                      // a single channel
    583   box_size=1./5.; // default box size for running mean calculations is
    584                   // 1/5 of the whole spectrum
    585   // A minimum number of consequtive channels, which should satisfy
    586   // the detection criterion, to be a detection
    587   min_nchan=3;     // default is 3 channels
     582  setOptions();
     583}
     584
     585// set the parameters controlling algorithm
     586// in_threshold a single channel threshold default is sqrt(3), which
     587//              means together with 3 minimum channels at least 3 sigma
     588//              detection criterion
     589//              For bad baseline shape, in_threshold may need to be
     590//              increased
     591// in_min_nchan minimum number of channels above the threshold to report
     592//              a detection, default is 3
     593// in_avg_limit perform the averaging of no more than in_avg_limit
     594//              adjacent channels to search for broad lines
     595//              Default is 8, but for a bad baseline shape this
     596//              parameter should be decreased (may be even down to a
     597//              minimum of 1 to disable this option) to avoid
     598//              confusing of baseline undulations with a real line.
     599//              Setting a very large value doesn't usually provide
     600//              valid detections.
     601// in_box_size  the box size for running mean calculation. Default is
     602//              1./5. of the whole spectrum size
     603void SDLineFinder::setOptions(const casa::Float &in_threshold,
     604                              const casa::Int &in_min_nchan,
     605                              const casa::Int &in_avg_limit,
     606                              const casa::Float &in_box_size) throw()
     607{
     608  threshold=in_threshold;
     609  min_nchan=in_min_nchan;
     610  avg_limit=in_avg_limit;
     611  box_size=in_box_size;
    588612}
    589613
     
    635659               edge.second=scan->nChan()-edge.second;
    636660           } else edge.second=scan->nChan()-edge.first;
    637            if (edge.second<0 || (edge.second+edge.first)>scan->nChan())
     661           if (edge.second<0 || (edge.first>=edge.second))
    638662               throw AipsError("SDLineFinder::setScan - all channels are rejected by the in_edge parameter");
    639663       }       
     
    674698     // a buffer for new lines found at this iteration
    675699     std::list<pair<int,int> > new_lines;     
    676      // line find algorithm
    677      LFAboveThreshold lfalg(new_lines,avg_factor*min_nchan, threshold);
    678700
    679701     try {
     702         // line find algorithm
     703         LFAboveThreshold lfalg(new_lines,avg_factor*min_nchan, threshold);
    680704         lfalg.findLines(spectrum,temp_mask,edge,max_box_nchan);
    681705         first_pass=False;
     
    688712         // nothing new - proceed to the next step of averaging, if any
    689713         // (to search for broad lines)
     714         if (avg_factor>avg_limit) break; // averaging up to avg_limit
     715                                          // adjacent channels,
     716                                          // stop after that
    690717         avg_factor*=2; // twice as more averaging
     718         subtractBaseline(temp_mask,9);
    691719         averageAdjacentChannels(temp_mask,avg_factor);
    692          if (avg_factor>8) break; // averaging up to 8 adjacent channels,
    693                                   // stop after that
    694720         continue;
    695721     }
     
    701727  }
    702728  return int(lines.size());
     729}
     730
     731// auxiliary function to fit and subtract a polynomial from the current
     732// spectrum. It uses the SDFitter class. This action is required before
     733// reducing the spectral resolution if the baseline shape is bad
     734void SDLineFinder::subtractBaseline(const casa::Vector<casa::Bool> &temp_mask,
     735                      const casa::Int &order) throw(casa::AipsError)
     736{
     737  AlwaysAssert(spectrum.nelements(),AipsError);
     738  // use the fact that temp_mask excludes channels rejected at the edge
     739  SDFitter sdf;
     740  std::vector<float> absc(spectrum.nelements());
     741  for (Int i=0;i<absc.size();++i)
     742       absc[i]=float(i)/float(spectrum.nelements());
     743  std::vector<float> spec;
     744  spectrum.tovector(spec);
     745  std::vector<bool> std_mask;
     746  temp_mask.tovector(std_mask);
     747  sdf.setData(absc,spec,std_mask);
     748  sdf.setExpression("poly",order);
     749  if (!sdf.fit()) return; // fit failed, use old spectrum
     750  spectrum=casa::Vector<casa::Float>(sdf.getResidual());   
    703751}
    704752
  • trunk/src/SDLineFinder.h

    r368 r369  
    135135   virtual ~SDLineFinder() throw(casa::AipsError);
    136136
     137   // set the parameters controlling algorithm
     138   // in_threshold a single channel threshold default is sqrt(3), which
     139   //              means together with 3 minimum channels at least 3 sigma
     140   //              detection criterion
     141   //              For bad baseline shape, in_threshold may need to be
     142   //              increased
     143   // in_min_nchan minimum number of channels above the threshold to report
     144   //              a detection, default is 3
     145   // in_avg_limit perform the averaging of no more than in_avg_limit
     146   //              adjacent channels to search for broad lines
     147   //              Default is 8, but for a bad baseline shape this
     148   //              parameter should be decreased (may be even down to a
     149   //              minimum of 1 to disable this option) to avoid
     150   //              confusing of baseline undulations with a real line.
     151   //              Setting a very large value doesn't usually provide
     152   //              valid detections.
     153   // in_box_size  the box size for running mean calculation. Default is
     154   //              1./5. of the whole spectrum size
     155   void setOptions(const casa::Float &in_threshold=sqrt(3.),
     156                   const casa::Int &in_min_nchan=3,
     157                   const casa::Int &in_avg_limit=8,
     158                   const casa::Float &in_box_size=0.2) throw();
     159
    137160   // set the scan to work with (in_scan parameter), associated mask (in_mask
    138161   // parameter) and the edge channel rejection (in_edge parameter)
     
    171194                               const casa::Int &boxsize)
    172195                               throw(casa::AipsError);
     196
     197   // auxiliary function to fit and subtract a polynomial from the current
     198   // spectrum. It uses the SDFitter class. This action is required before
     199   // reducing the spectral resolution if the baseline shape is bad
     200   void subtractBaseline(const casa::Vector<casa::Bool> &temp_mask,
     201                         const casa::Int &order) throw(casa::AipsError);
    173202   
    174203   // an auxiliary function to remove all lines from the list, except the
     
    203232                                           // the detection criterion, to be
    204233                                           // a detection
     234   casa::Int   avg_limit;                  // perform the averaging of no
     235                                           // more than in_avg_limit
     236                                           // adjacent channels to search
     237                                           // for broad lines. see setOptions
    205238   std::list<std::pair<int, int> > lines;  // container of start and stop+1
    206239                                           // channels of the spectral lines
  • trunk/src/python_SDLineFinder.cc

    r297 r369  
    4040       class_<SDLineFinder>("linefinder")
    4141         .def( init <> () )
     42         .def("setoptions",&SDLineFinder::setOptions)
    4243         .def("setscan",&SDLineFinder::setScan)
    4344         .def("findlines",&SDLineFinder::findLines)
Note: See TracChangeset for help on using the changeset viewer.