/**
 * Method rewrites Reco Signal to Phys Signal.
 * Time of Signal set to time of the Leading Signal Channel at the lowest threshold.
 * Other fields are set to -1, quality fields set to 0.
 */
JPetPhysSignal SignalTransformer::createPhysSignal(const JPetRecoSignal& recoSignal)
{
  JPetPhysSignal physSignal;
  physSignal.setRecoSignal(recoSignal);
  physSignal.setPhe(-1.0);
  physSignal.setQualityOfPhe(0.0);
  physSignal.setQualityOfTime(0.0);
  physSignal.setRecoFlag(recoSignal.getRecoFlag());
  std::vector<JPetSigCh> leadingSigChVec = recoSignal.getRawSignal().getPoints(
    JPetSigCh::Leading, JPetRawSignal::ByThrValue
  );
  physSignal.setTime(leadingSigChVec.at(0).getValue());
  return physSignal;
}
JPetPhysSignal JPetSimplePhysSignalReco::createPhysSignal(JPetRecoSignal& recoSignal)
{
  // create a Phys Signal
  JPetPhysSignal physSignal;

  // use the values from Reco Signal to set the physical properties of signal
  // here, a dummy example - much more sophisticated procedures should go here
  physSignal.setPhe( recoSignal.getCharge() * 1.0 + 0.0 );
  physSignal.setQualityOfPhe(1.0);

  // in the previous module (C2) we have reconstructed one time at arbitrary
  // threshold - now we retrieve it by getting a map of times vs. thresholds,
  // and taking its first (and only) element by the begin() iterator. We get
  // an std::pair, where first is the threshold value, and second is time.
  double time = recoSignal.getRecoTimesAtThreshold().begin()->second;

  // -----------------------------------------------------------
  //
  // Estimate the time of the signal based on raw signal samples
  JPetRawSignal rawSignal = recoSignal.getRawSignal();

  if (rawSignal.getNumberOfPoints(JPetSigCh::Leading) >= 2
      && rawSignal.getNumberOfPoints(JPetSigCh::Trailing) >= 2) {
    // get number of points on leading edge
    int iNumPoints = rawSignal.getNumberOfPoints(JPetSigCh::Leading);

    std::vector<JPetSigCh> leadingPoints = rawSignal.getPoints(
        JPetSigCh::Leading, JPetRawSignal::ByThrValue);

    // create vectors
    vector<float> vecTime(iNumPoints);
    vector<float> vecVolt(iNumPoints);

    for (int j = 0; j < iNumPoints; j++) {
      vecTime(j) = leadingPoints.at(j).getValue();
      vecVolt(j) = leadingPoints.at(j).getThreshold();
    }

    // To evaluate time below parameters should be specified:

    // the parameter alfa of the below expression need to be specified:
    // vecVolt = a(t - vecTime)^(alfa);
    // Here alfa is fixed for the linear case.
    // Caution! alfa has to be an integer and positive value, negative values are ignored.
    int alfa = getAlpha();

    // thr_sel specifies the threshold level to read the time value,
    // and with thr_sel the below equation may be solved:
    // thr_sel = a(t - time)^(alfa);
    // Caution! thr_sel has to negative, and for positive values the program will set thr_sel equal to 0.
    float thr_sel = getThresholdSel();

    // The evaluation of time based on alfa and thr_sel
    assert(thr_sel < 0);
    assert(alfa > 0);
    time = static_cast<double>(polynomialFit(vecTime, vecVolt, alfa, thr_sel));
  }
  // ------------------------------------------------------------

  physSignal.setTime(time);
  physSignal.setQualityOfTime(1.0);

  // store the original JPetRecoSignal in the PhysSignal as a processing history
  physSignal.setRecoSignal(recoSignal);
  return physSignal;
}