/**
 ** RtParams.java
 **
 ** Copyright (C) 2026 Elphel, Inc.
 **
 ** -----------------------------------------------------------------------------**
 **
 **  RtParams.java is free software: you can redistribute it and/or modify
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 of the License, or
 **  (at your option) any later version.
 **
 **  This program is distributed in the hope that it will be useful,
 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 **  GNU General Public License for more details.
 **
 **  You should have received a copy of the GNU General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ** -----------------------------------------------------------------------------**
 */
package com.elphel.imagej.cuas.rt;

/**
 * Runtime parameters for the real-time CUAS target detector.
 *
 * Mirrors the RtParams C struct in cuas_rt_gpu/src/rt_lib.h.
 * When JNA is added to pom.xml this class will gain a JNA Structure counterpart
 * (RtParamsJna extends com.sun.jna.Structure) for direct memory mapping.
 *
 * Velocity channels:
 *   X and Y each span [-maxVel .. +maxVel] pixels/sample.
 *   Total channels: nChan() = (2*maxVel+1)^2 = 25 for maxVel=2.
 *   Channel index:  chanIdx(ivx,ivy) = (ivy+maxVel)*nVel() + (ivx+maxVel)
 *   Units are pixels per input sample; input is already temporally
 *   averaged/decimated for the specific pyramid level, so the same
 *   maxVel applies at every pyramid level.
 */
public class RtParams {

    /** Velocity range per axis [-maxVel .. +maxVel] px/sample. Start with 2; try 1 and 3. */
    public int   maxVel      = 2;

    /** Accumulation buffer memory coefficient (high persistence). */
    public float memCoeff    = 0.9f;

    /** New observation weight (typically 1 - memCoeff). */
    public float obsCoeff    = 0.1f;

    /**
     * Leaky ReLU negative slope inside accumulation loop.
     * Controls competition vs. pure linear accumulation:
     *   slope=1.0 → linear (maximum SNR improvement, no competition)
     *   slope→0   → hard ReLU (strong competition, earlier saturation)
     * Tune experimentally; start near 1.0 and reduce toward 0.01.
     */
    public float leakySlope  = 0.1f;

    /** Accumulation buffer peak detection threshold for Stage 2 trigger. */
    public float peakThresh  = 0.5f;

    public RtParams() {}

    public RtParams(int maxVel, float memCoeff, float obsCoeff,
                    float leakySlope, float peakThresh) {
        this.maxVel     = maxVel;
        this.memCoeff   = memCoeff;
        this.obsCoeff   = obsCoeff;
        this.leakySlope = leakySlope;
        this.peakThresh = peakThresh;
    }

    /** Number of velocity channels per axis: 2*maxVel+1. */
    public int nVel()  { return 2 * maxVel + 1; }

    /** Total 2D velocity channels: nVel()^2. */
    public int nChan() { int n = nVel(); return n * n; }

    /**
     * Flat channel index for velocity (ivx, ivy), both in [-maxVel..+maxVel].
     * ivy is the major index (row), ivx is the minor index (column).
     */
    public int chanIdx(int ivx, int ivy) {
        return (ivy + maxVel) * nVel() + (ivx + maxVel);
    }

    /** Recover ivx from channel index. */
    public int ivxFromChan(int ich) { return (ich % nVel()) - maxVel; }

    /** Recover ivy from channel index. */
    public int ivyFromChan(int ich) { return (ich / nVel()) - maxVel; }

    @Override
    public String toString() {
        return String.format(
            "RtParams{maxVel=%d, nChan=%d, mem=%.3f, obs=%.3f, leaky=%.3f, thresh=%.3f}",
            maxVel, nChan(), memCoeff, obsCoeff, leakySlope, peakThresh);
    }
}
