46 namespace algorithms {
49 #define SFKeyAssign(var,key) \
51 if (mustexist || params.keyExists(keyPrefix + key)) { \
52 var = params[ keyPrefix + key ];\
54 xdbg << "SFAssign " key " = " << var; \
55 xdbg << " from parameter "<<(keyPrefix + key)<<std::endl; \
59 const ConfigFile& params, std::string keyPrefix,
bool mustexist)
95 const ConfigFile& params, std::string keyPrefix)
99 std::istringstream is(fspd);
103 defaultParams.
read(is);
114 std::vector<PotentialStar*>& allObj)
116 dbg<<
"starting FindStars, allobj.size() = "<<allObj.size()<<std::endl;
119 std::sort(allObj.begin(),allObj.end(),std::mem_fun(
121 dbg<<
"sorted allobj\n";
130 const int nObj = allObj.size();
131 for(
int k=0;k<nObj;++k) totalBounds += allObj[k]->getPos();
132 dbg<<
"totalbounds = \n"<<totalBounds<<std::endl;
137 xdbg<<
"made qbounds\n";
140 std::vector<PotentialStar*> probStars;
143 const int nSection = qBounds.size();
144 for(
int i=0;i<nSection;++i) {
145 dbg<<
"i = "<<i<<
": bounds = "<<qBounds[i]<<std::endl;
150 std::vector<PotentialStar*> someObj;
151 for(
int k=0;k<nObj;++k) {
152 if (qBounds[i].includes(allObj[k]->getPos()))
153 someObj.push_back(allObj[k]);
155 dbg<<
"added "<<someObj.size()<<
" obj\n";
164 dbg<<
"fit bright stars: sigma = "<<sigma<<std::endl;
167 double minSize,maxSize;
168 findMinMax(someObj,&minSize,&maxSize,fLinear);
169 dbg<<
"min,max = "<<minSize<<
','<<maxSize<<std::endl;
172 std::vector<PotentialStar*> qPeakList =
177 const int nPeak = qPeakList.size();
178 dbg<<
"peaklist has "<<nPeak<<
" stars\n";
183 dbg<<
"rejected outliers, now have "<<nPeak<<
" stars\n";
188 int nStarsExpected = int(
_starFrac * someObj.size());
189 if (nPeak < nStarsExpected) {
190 if (nPeak <
int(0.2 * nStarsExpected)) {
192 std::cout<<
"STATUS3BEG Warning: Only "<<
193 qPeakList.size()<<
" stars found in section "<<
194 i<<
". STATUS3END"<<std::endl;
196 dbg<<
"Warning: only "<<qPeakList.size()<<
197 " stars found in section "<<i<<
198 " "<<qBounds[i]<<std::endl;
200 probStars.insert(probStars.end(),qPeakList.begin(),qPeakList.end());
202 std::sort(qPeakList.begin(),qPeakList.end(),
204 probStars.insert(probStars.end(),qPeakList.begin(),
205 qPeakList.begin()+nStarsExpected);
207 dbg<<
"added to probstars\n";
209 xdbg<<
"done qbounds loop\n";
210 int nStars = probStars.size();
211 dbg<<
"nstars = "<<nStars<<std::endl;
229 double minSize,maxSize;
231 dbg<<
"new minmax = "<<minSize<<
','<<maxSize<<std::endl;
239 allObj,0.5*sigma,minSize,maxSize,
241 nStars = probStars.size();
242 dbg<<
"probstars has "<<nStars<<
" stars\n";
246 dbg<<
"rejected outliers, now have "<<probStars.size()<<
" stars\n";
249 dbg<<
"rejected outliers, now have "<<probStars.size()<<
" stars\n";
254 bool shouldRefit =
true;
256 dbg<<
"starting refit\n"<<std::endl;
258 std::vector<std::vector<PotentialStar*> > starsList(nSection);
261 for(
int k=0;k<nStars;++k) {
262 for(
int i=0;i<nSection;++i) {
263 if(qBounds[i].includes(probStars[k]->getPos()))
264 starsList[i].push_back(probStars[k]);
269 std::vector<PotentialStar*> fitList;
270 for(
int i=0;i<nSection;++i) {
275 std::cout<<
"STATUS3BEG Warning: Only "<<
276 starsList[i].size()<<
" stars in section "<<i<<
277 ". STATUS3END"<<std::endl;
279 dbg<<
"Warning: only "<<starsList[i].size()<<
280 " stars in section ";
281 dbg<<i<<
" "<<qBounds[i]<<std::endl;
282 fitList.insert(fitList.end(),starsList[i].begin(),
287 std::sort(starsList[i].begin(),starsList[i].end(),
291 fitList.insert(fitList.end(),starsList[i].begin(),
297 nStars = fitList.size();
300 dbg<<
"new minmax = "<<minSize<<
','<<maxSize<<std::endl;
302 allObj,0.5*sigma,minSize,maxSize,
305 dbg<<
"probstars has "<<probStars.size()<<
" stars\n";
308 dbg<<
"rejected outliers, now have "<<probStars.size()<<
" stars\n";
309 if (
int(probStars.size()) < nStars) {
311 dbg<<
"fewer than "<<nStars<<
" - so refit\n";
313 nStars = probStars.size();
316 dbg<<
"done FindStars\n";
318 for(
int i=0;i<nStars;++i) {
319 xdbg<<
"stars["<<i<<
"]: size = "<<probStars[i]->getSize();
320 xdbg<<
", size - f(pos) = ";
321 xdbg<<probStars[i]->getSize()-f(probStars[i]->getPos())<<std::endl;
322 xdbg<<probStars[i]->getLine()<<std::endl;
328 const std::vector<PotentialStar*>& list,
329 double *min,
double *max,
const Function2D& f)
332 min1 = max1 = list[0]->getSize()-f(list[0]->getPos());
333 const int nStars = list.size();
334 for(
int k=1;k<nStars;++k) {
335 double size = list[k]->getSize() - f(list[k]->getPos());
336 if (size > max1) max1 = size;
337 if (size < min1) min1 = size;
344 std::vector<PotentialStar*>& list,
345 double nSigma,
double minSigma,
const Function2D& f)
352 const int nStars = list.size();
353 if (nStars <= 4)
return;
355 std::vector<PotentialStar*> modifList(nStars);
356 for(
int k=0;k<nStars;++k) {
358 double newSize = list[k]->getSize() - f(list[k]->getPos());
359 modifList[k]->setSize(newSize);
361 std::sort(modifList.begin(),modifList.end(),
366 double median = mStar->getSize();
369 double sigma = std::max(q3-median,median-q1);
370 sigma = std::max(sigma,minSigma);
371 xdbg<<
"q1,m,q3 = "<<q1<<
" , "<<median<<
" , "<<q3<<std::endl;
372 xdbg<<
"sigma = "<<sigma<<
", nsig * sigma = "<<nSigma*sigma<<std::endl;
375 for(
int k=0; k<nStars;++k) {
376 if (std::abs(modifList[k]->getSize()-median)>nSigma*sigma) {
377 xdbg<<
"k = "<<k<<
", size = "<<modifList[k]->getSize();
378 xdbg<<
" might be an outlier (median = "<<median<<
")\n";
383 if (j<nStars) list.erase(list.begin()+j,list.end());
384 for(
int k=0;k<nStars;++k)
delete modifList[k];
388 const std::vector<PotentialStar*>& objList,
389 double binSize,
double minSize,
double maxSize,
390 int nStart,
int minIter,
double magStep,
double maxSignifRatio,
402 Assert(nStart<=
int(objList.size()));
403 for(k=0;k<nStart;++k) {
404 hist.
add(objList[k]->getSize()-f(objList[k]->getPos()),objList[k]);
406 xdbg<<
"added "<<nStart<<
" objects\n";
412 xdbg<<
"peak1 = "<<peak1<<
" ("<<hist[peak1]<<
")\n";
414 xdbg<<
"valley1 = "<<valley1<<
" ("<<hist[valley1]<<
")\n";
415 while (valley1 < 0.0) {
417 peak1 = hist.findFirstPeakAfter(valley1);
418 xdbg<<
"new peak1 = "<<peak1<<
" ("<<hist[peak1]<<
")\n";
425 double newValley1 = hist.findFirstValleyAfter(peak1);
426 if (!(newValley1 > valley1)) {
427 std::ostringstream err;
428 err<<
"Couldn't find a stellar peak. ";
429 err<<
"All the objects seem to be basically the same size.";
432 valley1 = newValley1;
433 xdbg<<
"new valley1 = "<<valley1<<
" ("<<hist[valley1]<<
")\n";
437 double peak2 = hist.findFirstPeakAfter(valley1);
438 xdbg<<
"peak2 = "<<peak2<<
" ("<<hist[peak2]<<
")\n";
441 double nBinsForHorn = isFirstPass ? 2.5 : 4.5;
442 if (peak2-peak1 < nBinsForHorn*binSize && peak2+binSize < maxSize) {
443 valley1 = hist.findFirstValleyAfter(peak2);
444 peak2 = hist.findFirstPeakAfter(peak2+binSize);
445 xdbg<<
"horn pattern: next peak2 = "<<peak2<<
" ("<<hist[peak2]<<
")\n";
447 double valley2 = hist.findFirstValleyAfter(peak2);
448 xdbg<<
"valley2 = "<<valley2<<
" ("<<hist[valley2]<<
")\n";
449 double valley0 = hist.findFirstValleyBefore(peak1);
450 if (!isFirstPass && valley0 > 0.) valley0 = hist.findFirstValleyBefore(0.);
451 xdbg<<
"valley0 = "<<valley0<<
" ("<<hist[valley0]<<
")\n";
455 std::vector<PotentialStar*> peakList=hist.getRefsInRange(valley0,valley1);
458 double highMag = objList[nStart-1]->getMag();
463 double prevValley=valley1;
465 for(
int count = 0; count < minIter || !done; ++count) {
469 xdbg<<
"count = "<<count<<
", highmag = "<<highMag<<std::endl;
472 const int nObj = objList.size();
473 for(;k<nObj && objList[k]->getMag()<highMag;++k) {
474 hist.add(objList[k]->getSize()-f(objList[k]->getPos()),objList[k]);
476 xdbg<<
"hist has "<<k<<
" objects\n";
479 xdbg<<
"valley0 = "<<valley0<<std::endl;
481 double peak = hist.findFirstPeakAfter(valley0,!isFirstPass);
482 valley0 = hist.findFirstValleyBefore(peak);
483 xdbg<<
"done findpeak: "<<peak<<std::endl;
487 double valley = hist.findFirstValleyAfter(peak,!isFirstPass);
488 xdbg<<
"done findvalley: "<<valley<<std::endl;
492 double nextPeak = hist.findFirstPeakAfter(valley,!isFirstPass);
494 while (std::abs(nextPeak) < std::abs(peak)) {
496 xdbg<<
"negative valley - new peak: "<<peak<<std::endl;
497 valley = hist.findFirstValleyAfter(peak,!isFirstPass);
498 xdbg<<
"new valley: "<<valley<<std::endl;
500 nextPeak = hist.findFirstPeakAfter(valley,!isFirstPass);
511 if (isFirstPass && valley > prevValley+binSize) {
513 xdbg<<
"moved valley to "<<valley<<std::endl;
514 if (peak >= valley) {
523 if (peak > prevValley && std::abs(peak) > std::abs(prevPeak)) {
524 xdbg<<
"New peak passed previous valley.\n";
532 int peakCount = hist.getRefinedPeakCount(&peak);
533 xdbg<<
"peakcount = "<<peakCount<<
" centered at "<<peak<<std::endl;
534 xdbg<<
"before refined: valley = "<<valley<<std::endl;
535 int valleyCount = hist.getRefinedValleyCount(&valley);
536 xdbg<<
"valleycount = "<<valleyCount<<
" centered at "<<valley<<std::endl;
542 if ((valley-peak < nBinsForHorn*binSize) &&
543 (hist.findFirstPeakAfter(valley) - valley) < nBinsForHorn*binSize) {
544 double newValley = hist.findFirstValleyAfter(
545 hist.findFirstPeakAfter(valley));
546 int newValleyCount = hist.getRefinedValleyCount(&newValley);
547 if (((isFirstPass && newValleyCount <= valleyCount) ||
548 (!isFirstPass && valleyCount > 0 && newValleyCount == 0)) &&
549 newValley <= prevValley + nBinsForHorn*binSize) {
551 xdbg<<
"horn pattern detected. new valley = "<<
552 newValley<<std::endl;
553 xdbg<<
"new valley count = "<<newValleyCount<<std::endl;
555 valleyCount = newValleyCount;
564 double signif = (double)valleyCount/(
double)peakCount;
565 dbg<<
"signif = "<<valleyCount<<
"/"<<peakCount<<
" = "<<signif<<std::endl;
572 dbg<<
"reset signif to 0, since valleycount "<<valleyCount<<
" <= ";
578 if (signif <= maxSignifRatio) {
579 dbg<<
"signif = "<<signif<<
" <= "<<maxSignifRatio<<std::endl;
580 xdbg<<
"good signif value\n";
582 double peakStart = std::min(2.*peak-valley,peak-binSize*0.5);
583 std::vector<PotentialStar*> temp =
584 hist.getRefsInRange(peakStart,valley);
585 xdbg<<
"get refs from "<<peakStart<<
" to "<<valley<<std::endl;
586 xdbg<<
"got refs: "<<temp.size()<<std::endl;
591 if (temp.size() >= peakList.size() ||
592 (valley<prevValley && valley>prevPeak) ||
593 (peak > prevPeak) ) {
595 if (temp.size() >= peakList.size()) {
596 xdbg<<
"tempsize = "<<temp.size()<<
" >= "<<peakList.size();
597 }
else if ((valley<prevValley && valley>prevPeak)) {
598 xdbg<<
"valley = "<<valley<<
" < "<<prevValley;
600 xdbg<<
"peak = "<<peak<<
" > "<<prevPeak;
602 xdbg<<
" so keep adding...\n";
608 xdbg<<
"tempsize < "<<peakList.size();
609 xdbg<<
" and peak,valley didn't contract, so stop adding now.\n";
613 dbg<<
"signif = "<<signif<<
" > "<<maxSignifRatio<<std::endl;
619 xdbg<<
"no more to add\n";
620 count = minIter; done =
true;
623 xdbg<<
"done finding peaklist\n";
629 const std::vector<PotentialStar*>& starList,
double *outSigma)
632 std::vector<Position> posList(starList.size());
633 std::transform(starList.begin(),starList.end(),posList.begin(),
637 std::vector<double> sizelist(starList.size());
638 std::transform(starList.begin(),starList.end(),sizelist.begin(),
642 std::vector<bool> useList(starList.size(),
true);
644 if (
int(starList.size()) <= (order+1)*(order+2)/2) {
645 std::ostringstream err;
646 err<<
"Not enough stars to do fit. ";
647 err<<
"Increase starsPerBin or decrease fitOrder.";
654 xdbg<<
"before outlier fit\n";
655 f->
outlierFit(order,sigClip,posList,sizelist,&useList,0,&chisq,&dof,0);
656 xdbg<<
"after outlier fit\n";
658 xdbg<<
"chisq,dof,sigma = "<<chisq<<
','<<dof<<
','<<
659 sqrt(chisq/dof)<<std::endl;
660 *outSigma = sqrt(chisq/dof);
664 const std::vector<PotentialStar*>& objList,
669 std::vector<PotentialStar*> brightList(
671 objList.begin()+int(
_nStart1*objList.size()));
674 std::sort(brightList.begin(),brightList.end(),
677 xdbg<<
"brightlist is:\n";
678 const int twenty = std::min(20,
int(brightList.size()));
679 for(
int i=0; i<twenty; ++i) {
680 xdbg<<brightList[i]->getMag()<<
" , "<<
681 brightList[i]->getSize()<<std::endl;
683 if (brightList.size() > 20) {
684 xdbg<<
"... (total of "<<brightList.size()<<
" elements)\n";
689 int five = int(0.5*
_starFrac*brightList.size());
690 xdbg<<
"'five' = "<<five<<std::endl;
693 xdbg<<
"'five' => "<<five<<std::endl;
695 if (3*five-1 >=
int(brightList.size())) {
696 std::ostringstream err;
697 err<<
"Too few objects in brightList. Increase startn1.";
701 double peakWidth = brightList[five-1]->getSize()-brightList[0]->getSize();
702 for(
int k=1;k<=2*five;++k) {
703 Assert(k+five-1<
int(brightList.size()));
704 double sizeRange = brightList[k+five-1]->getSize() -
705 brightList[k]->getSize();
706 if (sizeRange < peakWidth) {
707 peakWidth = brightList[k+five-1]->getSize() -
708 brightList[k]->getSize();
712 xdbg<<
"found peak starting at "<<peakStart<<
713 " with width "<<peakWidth<<std::endl;
715 int k1=peakStart, k2=peakStart+five;
718 k1 > 0 && brightList[peakStart+2]->getSize() -
719 brightList[k1-1]->getSize() <
_binSize1) {
722 const int nBright = brightList.size();
725 brightList[k2]->getSize() - brightList[k1]->getSize() < 2.*
_binSize1) {
728 xdbg<<
"expanded to "<<k1<<
','<<k2<<std::endl;
731 std::vector<PotentialStar*> starList(
732 brightList.begin()+k1, brightList.begin()+k2);
738 while(*outSigma >
_maxRms && starList.size() > 4) {
739 double diff1 = starList.front()->getSize() -
740 (*f)(starList.front()->getPos());
741 double diff2 = starList.back()->getSize() -
742 (*f)(starList.back()->getPos());
744 if (std::abs(diff1) > std::abs(diff2)) {
745 starList.erase(starList.begin());
746 xdbg<<
"Erased first star. New size = "<<starList.size()<<std::endl;
748 starList.erase(starList.end()-1);
749 xdbg<<
"Erased last star. New size = "<<starList.size()<<std::endl;
std::vector< Bounds > divide(int nx, int ny) const
void setParams(const ConfigFile ¶ms, std::string keyPrefix, bool mustExist=false)
void fitStellarSizes(Function2D *f, int order, double sigClip, const std::vector< PotentialStar * > &starList, double *outSigma)
std::vector< PotentialStar * > findStars(std::vector< PotentialStar * > &allObj)
SizeMagnitudeStarSelectorAlgo(const ConfigFile ¶ms, std::string keyPrefix)
std::vector< PotentialStar * > getPeakList(const std::vector< PotentialStar * > &objList, double binSize, double minSize, double maxSize, int nStart, int minIter, double magStep, double maxSignifRatio, bool isFirstPass, const Function2D &f)
unsigned int findstars_params_default_len
void rejectOutliers(std::vector< PotentialStar * > &list, double nSigma, double minSigma, const Function2D &f)
virtual void outlierFit(int order, double nsig, const std::vector< Position > &pos, const std::vector< double > &v, std::vector< bool > *shouldUse, const std::vector< double > *sigList=0, double *chisqout=0, int *dofout=0, DMatrix *cov=0)
double findFirstValleyAfter(double val1, bool hasPoissonNoise=false) const
std::string setComment(const std::string &s)
afw::table::Key< double > sigma
double findFirstPeakAfter(double val1, bool hasPoissonNoise=false) const
void print(std::ostream &fout, double val1=-1.e10, double val2=1.e10) const
#define SFKeyAssign(var, key)
char findstars_params_default[]
bool isBrighterThan(const PotentialStar *rhs) const
bool isSmallerThan(const PotentialStar *rhs) const
const Position & getPos() const
void read(std::istream &is)
void add(double value, const T &ref)
std::string setDelimiter(const std::string &s)
void roughlyFitBrightStars(const std::vector< PotentialStar * > &objList, Function2D *f, double *outSigma)
std::ostream *const dbgout
void findMinMax(const std::vector< PotentialStar * > &list, double *min, double *max, const Function2D &f)