Ignore:
Timestamp:
12/28/12 15:52:45 (11 years ago)
Author:
WataruKawasaki
Message:

New Development: Yes

JIRA Issue: Yes CAS-3618

Ready for Test: Yes

Interface Changes: No

What Interface Changed:

Test Programs:

Put in Release Notes: No

Module(s): sd

Description: new method for scantable to calculate AIC, AICc, BIC and GCV.


File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/Scantable.cpp

    r2683 r2713  
    26562656}
    26572657
     2658double Scantable::calculateModelSelectionCriteria(const std::string& valname, const std::string& blfunc, int order, const std::vector<bool>& inMask, int whichrow, bool useLineFinder, const std::vector<int>& edge, float threshold, int chanAvgLimit)
     2659{
     2660  if (useLineFinder) {
     2661    int minEdgeSize = getIFNos().size()*2;
     2662
     2663
     2664    int edgeSize = edge.size();
     2665    std::vector<int> currentEdge;
     2666    if (edgeSize >= 2) {
     2667      int idx = 0;
     2668      if (edgeSize > 2) {
     2669        if (edgeSize < minEdgeSize) {
     2670          throw(AipsError("Length of edge element info is less than that of IFs"));
     2671        }
     2672        idx = 2 * getIF(whichrow);
     2673      }
     2674      currentEdge.push_back(edge[idx]);
     2675      currentEdge.push_back(edge[idx+1]);
     2676    } else {
     2677      throw(AipsError("Wrong length of edge element"));
     2678    }
     2679
     2680    STLineFinder lineFinder = STLineFinder();
     2681    std::vector<float> sp = getSpectrum(whichrow);
     2682    lineFinder.setData(sp);
     2683    lineFinder.setOptions(threshold, 3, chanAvgLimit);
     2684    lineFinder.findLines(getCompositeChanMask(whichrow, inMask), currentEdge, whichrow);
     2685    std::vector<bool> chanMask = lineFinder.getMask();
     2686   
     2687    return doCalculateModelSelectionCriteria(valname, sp, chanMask, blfunc, order);
     2688
     2689  } else {
     2690    return doCalculateModelSelectionCriteria(valname, getSpectrum(whichrow), getCompositeChanMask(whichrow, inMask), blfunc, order);
     2691  }
     2692
     2693}
     2694
     2695double Scantable::doCalculateModelSelectionCriteria(const std::string& valname, const std::vector<float>& spec, const std::vector<bool>& mask, const std::string& blfunc, int order)
     2696{
     2697  int nparam;
     2698  std::vector<float> params;
     2699  int nClipped = 0;
     2700  float thresClip = 0.0;
     2701  int nIterClip = 0;
     2702  std::vector<float> res;
     2703  if (blfunc == "chebyshev") {
     2704    nparam = order + 1;
     2705    res = doChebyshevFitting(spec, mask, order, params, nClipped, thresClip, nIterClip, true);
     2706  } else if (blfunc == "sinusoid") {
     2707    std::vector<int> nWaves;
     2708    nWaves.clear();
     2709    for (int i = 0; i <= order; ++i) {
     2710      nWaves.push_back(i);
     2711    }
     2712    nparam = 2*order + 1;  // order = nwave
     2713    res = doSinusoidFitting(spec, mask, nWaves, params, nClipped, thresClip, nIterClip, true);
     2714  } else if (blfunc == "cspline") {
     2715    std::vector<int> pieceEdges(order+1);  //order = npiece
     2716    nparam = order + 3;
     2717    params.resize(4*order);
     2718    res = doCubicSplineFitting(spec, mask, order, pieceEdges, params, nClipped, thresClip, nIterClip, true);
     2719  } else {
     2720    throw(AipsError("blfunc must be chebyshev, cspline or sinusoid."));
     2721  }
     2722
     2723  double msq = 0.0;
     2724  int nusedchan = 0;
     2725  int nChan = res.size();
     2726  for (int i = 0; i < nChan; ++i) {
     2727    if (mask[i]) {
     2728      msq += (double)res[i]*(double)res[i];
     2729      nusedchan++;
     2730    }
     2731  }
     2732  if (nusedchan == 0) {
     2733    throw(AipsError("all channels masked."));
     2734  }
     2735  msq /= (double)nusedchan;
     2736
     2737  nparam++;  //add 1 for sigma of Gaussian distribution
     2738  const double PI = 6.0 * asin(0.5); // PI (= 3.141592653...)
     2739
     2740  if (valname.find("aic") == 0) {
     2741    // Original Akaike Information Criterion (AIC)
     2742    double aic = nusedchan * (log(2.0 * PI * msq) + 1.0) + 2.0 * nparam;
     2743
     2744    // Corrected AIC by Sugiura(1978)
     2745    if (valname == "aicc") {
     2746      if (nusedchan - nparam - 1 <= 0) {
     2747        throw(AipsError("channel size is too small to calculate AICc."));
     2748      }
     2749      aic += 2.0*nparam*(nparam + 1)/(double)(nusedchan - nparam - 1);
     2750    }
     2751
     2752    return aic;
     2753
     2754  } else if (valname == "bic") {
     2755    // Bayesian Information Criterion (BIC)
     2756    double bic = nusedchan * log(msq) + nparam * log((double)nusedchan);
     2757    return bic;
     2758
     2759  } else if (valname == "gcv") {
     2760    // Generalised Cross Validation
     2761    double x = 1.0 - (double)nparam / (double)nusedchan;
     2762    double gcv = msq / (x * x);
     2763    return gcv;
     2764
     2765  } else {
     2766    throw(AipsError("valname must be aic, aicc, bic or gcv."));
     2767  }
     2768}
     2769
    26582770void Scantable::autoChebyshevBaseline(const std::vector<bool>& mask, int order, float thresClip, int nIterClip, const std::vector<int>& edge, float threshold, int chanAvgLimit, bool getResidual, const std::string& progressInfo, const bool outLogger, const std::string& blfile)
    26592771{
     
    27512863  if ((x < -1.0)||(x > 1.0)) {
    27522864    throw(AipsError("out of definition range (-1 <= x <= 1)."));
     2865  } else if (x == 1.0) {
     2866    return 1.0;
     2867  } else if (x == 0.0) {
     2868    double res;
     2869    if (n%2 == 0) {
     2870      if (n%4 == 0) {
     2871        res = 1.0;
     2872      } else {
     2873        res = -1.0;
     2874      }
     2875    } else {
     2876      res = 0.0;
     2877    }
     2878    return res;
     2879  } else if (x == -1.0) {
     2880    double res = (n%2 == 0 ? 1.0 : -1.0);
     2881    return res;
    27532882  } else if (n < 0) {
    27542883    throw(AipsError("the order must be zero or positive."));
     
    27662895        }
    27672896      }
    2768       res += (m%2 == 0 ? 1.0 : -1.0)*(double)n/(double)(n-m)*pow(2.0*x, (double)(n-2*m-1))/2.0*c;
     2897      res += (m%2 == 0 ? 1.0 : -1.0)*(double)n/(double)(n-m)*pow(2.0*x, (double)(n-2*m))/2.0*c;
    27692898    }
    27702899    return res;
Note: See TracChangeset for help on using the changeset viewer.