/*
 * TrkNucleiZCut.cpp
 *
 *  Created on: 10-mag-2009
 *      Author: Nicola Mori
 */

/*! @file TrkNucleiZCut.cpp The TrkNucleiZCut class implementation file */
#ifndef NO_TRKNUCLEI

#include "TrkNucleiZCut.h"

const float TrkNucleiZCut::_sigmaZ[] = { 0.09, 0.1, 0.17, 0.34, 0.44, 0.59 }; // the charge-width in a layer for Z=1..6


int TrkNucleiZCut::Check(PamLevel2 *event) {

  if (_Z < 1 || _Z > 6)
    return TRKNUCLEIZ_ILLEGALZ;

  // ******** Check if TrkNuclei has already been initialized ********
  if (_trkNuclei == NULL)
    _trkNuclei = new TrkNuclei();
  _trkNuclei->Set(event->GetTrack(0)->GetTrkTrack());

  // ******** First of all, check if the minimum number of planes is matched. ********
  // NOTE: in current implementation a plane is considered valid if it is tagged as good in Tracker level 2
  //       routines. This should correspond to a valid charge.
  // TODO Check the above statement.

  // Prepare the valid charges counter
  unsigned int nValid = 0;
  for (unsigned int ip = 0; ip < 6; ip++) {
    if (_trkNuclei->GetTrkTrack()->XGood(ip) && _trkNuclei->GetTrkTrack()->XGood(ip))
      nValid++;
  }
  if (nValid < _minLayers)
    return TRKNUCLEIZ_TOOFEWLAYERS;

  // ******** Check the mean charge value ********
  if (_howToCheck == TRKNUCLEIZ_CHECKMEAN) {

    Float_t charge;
    switch (_method) {
    case TRKNUCLEIZ_DEFL:
      charge = _trkNuclei->GetZ_Rigidity();
      break;
    case TRKNUCLEIZ_BETA:
      charge = _trkNuclei->GetZ_Beta(event->GetTrack(0)->GetToFTrack()->beta[12]);
      break;
    }

    if ((charge > _Z + _upperLimit * _sigmaZ[_Z - 1]) || (charge < _Z - _lowerLimit * _sigmaZ[_Z - 1])) {
      return TRKNUCLEIZ_OUTOFBOUNDS;
    }

  }
  // ******** Check the charge value from each plane ********
  // NB. In current implementation only 2 check methods (mean and single values) are used, so an "else" statement
  //     is sufficient. Implement an "if" cascade or a "switch" if another check method is necessary.

  else {
    Float_t charge[6] = { 0., 0., 0., 0., 0., 0. };
    nValid = 0;
    switch (_method) {
    case TRKNUCLEIZ_DEFL:
      for (int ip = 0; ip < 6; ip++) {
        charge[ip] = _trkNuclei->GetZ_Rigidity(ip);
        if (charge[ip] > 0.) {
          nValid++;
        }
      }
      break;
    case TRKNUCLEIZ_BETA:
      for (int ip = 0; ip < 6; ip++) {
        charge[ip] = _trkNuclei->GetZ_Beta(ip, event->GetTrack(0)->GetToFTrack()->beta[12]);
        if (charge[ip] > 0.) {
          nValid++;
        }
      }
      break;
    }

    for (int ip = 0; ip < 6; ip++) {
      if (charge[ip] > 0.) // Check only good layers
        if ((charge[ip] > _Z + _upperLimit * _sigmaZ[_Z - 1]) || (charge[ip] < _Z - _lowerLimit * _sigmaZ[_Z - 1])) {
          return TRKNUCLEIZ_OUTOFBOUNDS;
        }
    }
  }

  return CUTOK;

}

#endif /* NO_TRKNUCLEI */
