# include "psphotInternal.h"

// Find peaks in the significance image above a threshold significance level.  The significance
// image must be constructed to represent (S/N)^2.  If nMax is non-zero, only return a maximum
// of nMax peaks
psArray *psphotFindPeaks (psImage *significance, pmReadout *readout, psMetadata *recipe, const float threshold, const int nMax) {

    bool status = false;

    psTimerStart ("psphot.peaks");

    // find the peaks in the smoothed image
    psArray *peaks = pmPeaksInImage (significance, threshold);
    if (peaks == NULL) {
	// we only get a NULL peaks array due to a programming or config error. 
	// this will result in a failure.
        psError(PSPHOT_ERR_DATA, false, "no peaks found in this image");
        return NULL;
    }

    if (peaks->n == 0) {
        // XXX do we need to set something in the readout->analysis to indicate that
        // we tried and failed to find peaks (something in the header data)
	psLogMsg ("psphot", PS_LOG_INFO, "no peaks found in this image");
	return peaks;
    }

    // Convert the peak values to S/N = sqrt(significance).
    // Get the peak flux from the unsmoothed image.
    // Rescale the peak position errors using the peak variance
    // The peak pixel coords are guaranteed to be on the image
    int row0 = readout->image->row0;
    int col0 = readout->image->col0;
    for (int i = 0; i < peaks->n; i++) {
        pmPeak *peak = peaks->data[i];
        peak->SN = sqrt(peak->value);
        peak->flux = readout->image->data.F32[peak->y-row0][peak->x-col0];
	// if (peak->flux / peak->value > 5.0/12.0) {
	//     psWarning ("odd peak levels (1)");
	// }
	// if (peak->value / peak->flux > 5*12.0) {
	//     psWarning ("odd peak levels (2)");
	// }
	if (readout->variance && isfinite (peak->dx)) {
	    peak->dx *= sqrt(readout->variance->data.F32[peak->y-row0][peak->x-col0]);
	}
	if (readout->variance && isfinite (peak->dy)) {
	    peak->dy *= sqrt(readout->variance->data.F32[peak->y-row0][peak->x-col0]);
	}
    }

    // limit the total number of returned peaks as specified
    psArraySort (peaks, pmPeakSortBySN);
    if (nMax && (peaks->n > nMax)) {
	psArray *tmpPeaks = psArrayAllocEmpty (nMax);
	for (int i = 0; i < nMax; i++) {
	    psArrayAdd (tmpPeaks, 100, peaks->data[i]);
	}
	psFree (peaks);
	peaks = tmpPeaks;
    }

    // optional dump of all peak data 
    char *output = psMetadataLookupStr (&status, recipe, "PEAKS_OUTPUT_FILE");
    if (output && strcasecmp (output, "NONE")) {
        pmPeaksWriteText (peaks, output);
    }
    psLogMsg ("psphot", PS_LOG_INFO, "%ld peaks: %f sec\n", peaks->n, psTimerMark ("psphot.peaks"));

    return peaks;

}
