Changeset 344


Ignore:
Timestamp:
02/01/05 16:17:25 (20 years ago)
Author:
vor010
Message:

An algorithm to detect line wings, which are
below detection threshold, has been added

Location:
trunk/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/SDLineFinder.cc

    r343 r344  
    4444using namespace boost::python;
    4545
     46namespace asap {
     47
     48///////////////////////////////////////////////////////////////////////////////
     49//
     50// IStatHolder - an abstract class to collect statistics from the running
     51//               mean calculator, if necessary.
     52//               We define it here, because it is used in LFRunningMean and
     53//               SDLineFinder only
     54//
     55
     56struct IStatHolder  {
     57   // This function is called for each spectral channel processed by
     58   // the running mean calculator. The order of channel numbers may be
     59   // arbitrary
     60   // ch - a number of channel, corresponding to (approximately) the centre
     61   //      of the running box
     62   // box_nchan - number of channels in the box
     63   //
     64   virtual void accumulate(int ch, Float sum, Float sum2, int box_nchan)
     65                      throw(AipsError) = 0;                   
     66};
     67
     68//
     69///////////////////////////////////////////////////////////////////////////////
     70
     71///////////////////////////////////////////////////////////////////////////////
     72//
     73// SignAccumulator - a simple class to deal with running mean statistics:
     74//                   it stores the sign of the value-mean only
     75//
     76class SignAccumulator : public IStatHolder {
     77   Vector<Int>  sign;                // either +1, -1 or 0
     78   const Vector<Float>   &spectrum;  // a reference to the spectrum
     79                                     // to calculate the sign   
     80public:
     81   // all channels >=nchan are ignored
     82   SignAccumulator(uInt nchan, const Vector<Float> &in_spectrum);
     83   
     84   // This function is called for each spectral channel processed by
     85   // the running mean calculator. The order of channel numbers may be
     86   // arbitrary
     87   // ch - a number of channel, corresponding to (approximately) the centre
     88   //      of the running box
     89   // box_nchan - number of channels in the box
     90   //
     91   virtual void accumulate(int ch, Float sum, Float, int box_nchan)
     92                      throw(AipsError);
     93
     94   // access to the sign
     95   const Vector<Int>& getSigns() const throw();
     96};
     97
     98//
     99///////////////////////////////////////////////////////////////////////////////
     100
    46101///////////////////////////////////////////////////////////////////////////////
    47102//
     
    49104//
    50105//
    51 
    52 namespace asap {
    53106
    54107// An auxiliary class implementing one pass of the line search algorithm,
     
    96149
    97150   // find spectral lines and add them into list
    98    void findLines(std::list<pair<int,int> > &lines) throw(casa::AipsError);
     151   // if statholder is not NULL, the accumulate function of it will be
     152   // called for each channel to save statistics
     153   void findLines(std::list<pair<int,int> > &lines,
     154                  IStatHolder* statholder = NULL) throw(casa::AipsError);
    99155   
    100156protected:
     
    123179
    124180};
     181
     182//
     183///////////////////////////////////////////////////////////////////////////////
    125184} // namespace asap
     185
     186///////////////////////////////////////////////////////////////////////////////
     187//
     188// SignAccumulator - a simple class to deal with running mean statistics:
     189//                   it stores the sign of the value-mean only
     190//
     191
     192// all channels >=nchan are ignored
     193SignAccumulator::SignAccumulator(uInt nchan,
     194                   const Vector<Float> &in_spectrum) : sign(nchan,0),
     195                   spectrum(in_spectrum) {}
     196
     197
     198// This function is called for each spectral channel processed by
     199// the running mean calculator. The order of channel numbers may be
     200// arbitrary
     201// ch - a number of channel, corresponding to (approximately) the centre
     202//      of the running box
     203// box_nchan - number of channels in the box
     204//
     205void SignAccumulator::accumulate(int ch, Float sum, Float, int box_nchan)
     206                   throw(AipsError)
     207{
     208   if (ch>=sign.nelements()) return;
     209   DebugAssert(ch>=0,AipsError);
     210   DebugAssert(ch<=spectrum.nelements(), AipsError);
     211   if (box_nchan) {
     212       Float buf=spectrum[ch]-sum/Float(box_nchan);
     213       if (buf>0) sign[ch]=1;
     214       else if (buf<0) sign[ch]=-1;
     215       else sign[ch]=0;
     216   } else sign[ch]=0;   
     217}
     218
     219// access to the sign
     220const Vector<Int>& SignAccumulator::getSigns() const throw()
     221{
     222   return sign;
     223}
     224
    126225
    127226//
     
    253352
    254353// find spectral lines and add them into list
    255 void LFRunningMean::findLines(std::list<pair<int,int> > &lines)
     354void LFRunningMean::findLines(std::list<pair<int,int> > &lines,
     355                              IStatHolder* statholder)
    256356                        throw(casa::AipsError)
    257357{
     
    273373  is_detected_before=False;
    274374
     375  if (statholder!=NULL)
     376      for (int n=0;n<initial_box_ch-max_box_nchan/2;++n)
     377           statholder->accumulate(n,sum,sumsq,box_chan_cntr);
     378
    275379  if (box_chan_cntr>=minboxnchan)
    276380      // there is a minimum amount of data. We can search in the
     
    283387  for (int n=initial_box_ch-max_box_nchan/2;n<edge.second;++n) {
    284388      advanceRunningBox(n+max_box_nchan/2); // update running mean & variance
     389      if (statholder!=NULL)
     390          statholder->accumulate(n,sum,sumsq,box_chan_cntr);
    285391      if (box_chan_cntr>=minboxnchan) // have enough data to process
    286392          processChannel(lines,n);
    287393      else processCurLine(lines); // just finish what was accumulated before
    288   } 
     394  }
     395  if (statholder!=NULL)
     396      for (int n=edge.second;n<spectrum.nelements();++n)
     397           statholder->accumulate(n,sum,sumsq,box_chan_cntr);
    289398}
    290399
     
    468577  lines.resize(0); // search from the scratch
    469578  Vector<Bool> temp_mask(mask);
    470   Bool need2iterate=True;
    471   while (need2iterate) {
     579 
     580  while (true) {
    472581     // line find algorithm
    473582     LFRunningMean lfalg(spectrum,temp_mask,edge,max_box_nchan,min_nchan,
    474583                         threshold);
     584     SignAccumulator sacc(spectrum.nelements(),spectrum);
     585
     586     // a buffer for new lines found at this iteration
    475587     std::list<pair<int,int> > new_lines;
    476      lfalg.findLines(new_lines);
    477      if (!new_lines.size()) need2iterate=False;
    478      temp_mask=getMask();
     588     
     589     lfalg.findLines(new_lines,&sacc);
     590     if (!new_lines.size()) break; // nothing new
     591
     592     searchForWings(new_lines, sacc.getSigns());
     593
    479594     // update the list (lines) merging intervals, if necessary
    480      addNewSearchResult(new_lines);
     595     addNewSearchResult(new_lines,lines);
     596     // get a new mask
     597     temp_mask=getMask();     
    481598  }
    482599  return int(lines.size());
     
    569686// concatenate two lists preserving the order. If two lines appear to
    570687// be adjacent, they are joined into the new one
    571 void SDLineFinder::addNewSearchResult(const std::list<pair<int, int> > &newlines)
     688void SDLineFinder::addNewSearchResult(const std::list<pair<int, int> > &newlines,
     689                         std::list<std::pair<int, int> > &lines_list)
    572690                        throw(AipsError)
    573691{
     
    578696           // the first item, which has a non-void intersection or touches
    579697           // the new line
    580            std::list<pair<int,int> >::iterator pos_beg=find_if(lines.begin(),
    581                           lines.end(), IntersectsWith(*cli));           
     698           std::list<pair<int,int> >::iterator pos_beg=find_if(lines_list.begin(),
     699                          lines_list.end(), IntersectsWith(*cli));           
    582700           // the last such item         
    583701           std::list<pair<int,int> >::iterator pos_end=find_if(pos_beg,
    584                           lines.end(), not1(IntersectsWith(*cli)));
     702                          lines_list.end(), not1(IntersectsWith(*cli)));
    585703
    586704           // extract all lines which intersect or touch a new one into
     
    589707           // one.
    590708           std::list<pair<int,int> > lines_buffer;
    591            lines_buffer.splice(lines_buffer.end(),lines, pos_beg, pos_end);
     709           lines_buffer.splice(lines_buffer.end(),lines_list, pos_beg, pos_end);
    592710
    593711           // build a union of all intersecting lines
     
    596714           
    597715           // search for a right place for the new line (union_line) and add
    598            std::list<pair<int,int> >::iterator pos2insert=find_if(lines.begin(),
    599                           lines.end(), LaterThan(union_line));
    600            lines.insert(pos2insert,union_line);
     716           std::list<pair<int,int> >::iterator pos2insert=find_if(lines_list.begin(),
     717                          lines_list.end(), LaterThan(union_line));
     718           lines_list.insert(pos2insert,union_line);
    601719      }
    602720  }
     
    608726  }
    609727}
     728
     729// extend all line ranges to the point where a value stored in the
     730// specified vector changes (e.g. value-mean change its sign)
     731// This operation is necessary to include line wings, which are below
     732// the detection threshold. If lines becomes adjacent, they are
     733// merged together. Any masked channel stops the extension
     734void SDLineFinder::searchForWings(std::list<std::pair<int, int> > &newlines,
     735           const casa::Vector<casa::Int> &signs) throw(casa::AipsError)
     736{
     737  try {
     738      for (std::list<pair<int,int> >::iterator li=newlines.begin();
     739           li!=newlines.end();++li) {
     740           // update the left hand side
     741           for (int n=li->first-1;n>=edge.first;--n) {
     742                if (!mask[n]) break;
     743                if (signs[n]==signs[li->first] && signs[li->first])
     744                    li->first=n;
     745                else break;   
     746           }
     747           // update the right hand side
     748           for (int n=li->second;n<edge.second;++n) {
     749                if (!mask[n]) break;
     750                if (signs[n]==signs[li->second-1] && signs[li->second-1])
     751                    li->second=n;
     752                else break;   
     753           }
     754      }
     755      // need to search for possible mergers.
     756      std::list<std::pair<int, int> >  result_buffer;
     757      addNewSearchResult(newlines,result_buffer);
     758      newlines.clear();
     759      newlines.splice(newlines.end(),result_buffer);
     760  }
     761  catch (const AipsError &ae) {
     762      throw;
     763  } 
     764  catch (const exception &ex) {
     765      throw AipsError(String("SDLineFinder::extendLines - STL error: ")+ex.what());
     766  }
     767}
  • trunk/src/SDLineFinder.h

    r343 r344  
    8989   // be adjacent or have a non-void intersection, they are joined into
    9090   // the new line
    91    void addNewSearchResult(const std::list<std::pair<int, int> > &newlines)
     91   static void addNewSearchResult(const std::list<std::pair<int, int> >
     92                  &newlines, std::list<std::pair<int, int> > &lines_list)
    9293                           throw(casa::AipsError);
     94
     95   // extend all line ranges to the point where a value stored in the
     96   // specified vector changes (e.g. value-mean change its sign)
     97   // This operation is necessary to include line wings, which are below
     98   // the detection threshold. If lines becomes adjacent, they are
     99   // merged together. Any masked channel stops the extension
     100   void searchForWings(std::list<std::pair<int, int> > &newlines,
     101                           const casa::Vector<casa::Int> &signs)
     102                           throw(casa::AipsError);
    93103                           
    94104   // An auxiliary object function to test whether two lines have a non-void
Note: See TracChangeset for help on using the changeset viewer.