//=========================================================================
//  Fill PV for related PV
//=========================================================================
StatusCode TupleToolGeometry::fillBPV( const VertexBase* primVtx
                                       , const Particle* P
                                       , const std::string& prefix
                                       , Tuples::Tuple& tuple
                                       , const std::string& trail) const {
  bool test = true ;

  double ip=0, chi2=0;
  if ( !primVtx )
  {
    ++counter("No BPV for "+prefix);
    test &= tuple->column( prefix + "_IP"+trail, -999. );
    test &= tuple->column( prefix + "_IPCHI2"+trail, -999. );
  }
  else
  {
    test &= m_dist->distance ( P, primVtx, ip, chi2 );
    if ( !test )
    {
      ip   = -1;
      chi2 = -1;
    }
    test &= tuple->column( prefix + "_IP"+trail, ip );
    test &= tuple->column( prefix + "_IPCHI2"+trail, chi2 );
  }

  if (!test) Warning("Error in fillBPV "+prefix,1).ignore();
  return StatusCode(test) ;
}
//=========================================================================
// fill vertex stuff
//=========================================================================
StatusCode TupleToolGeometry::fillVertex( const LHCb::VertexBase* vtx,
                                          const std::string& vtx_name,
                                          Tuples::Tuple& tuple ) const
{
  bool test = true ;

  // decay vertex information:
  if ( !vtx )
  {
    Gaudi::XYZPoint pt(-999.,-999.,-999.) ; // arbitrary point
    test &= tuple->column(  vtx_name+"_", pt );
    test &= tuple->column(  vtx_name + "_XERR", -999. );
    test &= tuple->column(  vtx_name + "_YERR", -999. );
    test &= tuple->column(  vtx_name + "_ZERR", -999. );
    test &= tuple->column(  vtx_name + "_CHI2", -999. );
    test &= tuple->column(  vtx_name + "_NDOF", -1 );
    test &= tuple->matrix(  vtx_name + "_COV_", Gaudi::SymMatrix3x3()  );
  }
  else
  {
    test &= tuple->column( vtx_name+"_", vtx->position() );
    const Gaudi::SymMatrix3x3 & m = vtx->covMatrix ();
    test &= tuple->column(  vtx_name + "_XERR", std::sqrt( m(0,0) ) );
    test &= tuple->column(  vtx_name + "_YERR", std::sqrt( m(1,1) ) );
    test &= tuple->column(  vtx_name + "_ZERR", std::sqrt( m(2,2) ) );
    test &= tuple->column(  vtx_name + "_CHI2", vtx->chi2() );
    test &= tuple->column(  vtx_name + "_NDOF", vtx->nDoF() );
    test &= tuple->matrix(  vtx_name + "_COV_", m );
  }

  // --------------------------------------------------
  if (!test) Warning("Error in fillVertex "+vtx_name,1).ignore();
  return StatusCode(test) ;

}
//=============================================================================
// Fill the tuple
//=============================================================================
StatusCode TupleToolTrackPosition::fill( const LHCb::Particle *, const LHCb::Particle *   part,
                                         const std::string &   head, Tuples::Tuple &   tuple )
{

  const std::string prefix=fullName(head);
  if ( msgLevel(MSG::DEBUG) ) debug() << "==> Fill" << endmsg;

  bool test=true;

  double X=-999999;
  double Y=-999999;


  if( part && part->proto() && part->proto()->track() )
  {

    if ( msgLevel(MSG::VERBOSE) ) verbose() << "extrapolating track to Z="<< m_Z << endmsg;

    LHCb::State aState=LHCb::State();
    //const LHCb::Track aTrack= *(part->proto()->track());
    StatusCode sc=m_extrapolator->stateFromTrajectory(aState,*(part->proto()->track()),m_Z);
    if(sc.isSuccess())
    {
      X=aState.x();
      Y=aState.y();
    }

  }

  test &= tuple->column( prefix+"_X", X );
  test &= tuple->column( prefix+"_Y", Y );

  return StatusCode(test);
}
//=============================================================================
StatusCode TupleToolCaloHypo::fill(const Particle* , const Particle* P
                                   ,const std::string& head
                                   ,Tuples::Tuple& tuple ){

  const std::string prefix=fullName(head);


  if( NULL == P )return StatusCode::SUCCESS;
  if( NULL == P->proto() )return StatusCode::SUCCESS;
  if( 0 != P->charge() && !m_charged)return StatusCode::SUCCESS;

  bool filltuple = true;
  const SmartRefVector<LHCb::CaloHypo>& hypos = P->proto()->calo();
  bool hasCalo = true;
  bool hasBremCalo = false;
  if( 0 == hypos.size() )hasCalo = false;
  if( 1 < hypos.size() )hasBremCalo = true;
  filltuple &= tuple->column( prefix+"_hasCaloHypo", (int) hasCalo );
  if( !isPureNeutralCalo( P ) && m_brem )
    filltuple &= tuple->column( prefix+"_hasBremCaloHypo", (int) hasBremCalo );



  using namespace CaloDataType;
  // select hypos
  const LHCb::CaloHypo* hypo = NULL;
  const LHCb::CaloHypo* hypo2 = NULL;
  for( SmartRefVector<CaloHypo>::const_iterator ih = hypos.begin() ; hypos.end() != ih ; ++ih){
    if( !isPureNeutralCalo( P ) ){
      if( (*ih)->hypothesis() == LHCb::CaloHypo::EmCharged)hypo = *ih;
      else hypo2 = *ih;
    }else hypo = *ih;
  }
  //fill tuple
  for( int id = 0 ; id < Last ; ++id){
    int mask = ( P->charge() == 0 ) ? 0x1 : 0x2;
    if( useData( id , mask ) ){
      double val  =  (NULL != hypo && hasCalo)    ? m_estimator->data(hypo, (DataType) id ,0.) : 0.;      
      filltuple &= tuple->column( prefix+"_CaloHypo_"+Name[id], val );
    }
    if( P->charge() != 0 && m_brem && useData( id , 0x1 ) ){
      double bval =  (NULL != hypo2 && hasBremCalo) ? m_estimator->data(hypo2,(DataType) id ,0.) : 0.;
      filltuple &= tuple->column( prefix+"_BremCaloHypo_"+Name[id], bval );
    }
  }
  return StatusCode(filltuple);
}
Exemple #5
0
// ============================================================================
StatusCode GaudiPython::TupleDecorator::column
( const Tuples::Tuple&  tuple ,
  const std::string&    name  ,
  IOpaqueAddress*       value )
{
  if ( !tuple.valid() ) { return StatusCode::FAILURE ; }
  return tuple->column( name , value ) ;
}
//=========================================================================
// fill flight distance, angle...
//=========================================================================
StatusCode TupleToolGeometry::fillFlight( const VertexBase* oriVtx,
                                          const Particle* P,
                                          const std::string& prefix,
                                          Tuples::Tuple& tuple,
                                          const std::string& trail ) const
{
  bool test = true ;
  // --------------------------------------------------
  if ( !oriVtx )
  {
    test &= tuple->column( prefix + "_FD"+trail, -999. );
    test &= tuple->column( prefix + "_FDCHI2"+trail, -999. );
    test &= tuple->column( prefix + "_DIRA"+trail, -999.);
  }
  else
  {

    // flight distance
    double dist = 0;
    double chi2 = 0 ;
    StatusCode sc = m_dist->distance( oriVtx, P->endVertex(), dist, chi2 );
    if ( sc.isFailure() ) return sc ;

    test &= tuple->column( prefix + "_FD"+trail, dist );
    test &= tuple->column( prefix + "_FDCHI2"+trail, chi2 );
    // --------------------------------------------------
    // cosine of (flight distance) dot (momentum):
    // find the origin vertex. Either the primary or the origin in the
    // decay
    test &= tuple->column( prefix + "_DIRA"+trail, dira(oriVtx,P) );
  }

  if (!test) Warning("Error in fillFlight "+prefix,1).ignore();
  return StatusCode(test);
}
StatusCode TupleToolVtxIsoln::fill( const Particle* mother
                                    , const Particle* P
                                    , const std::string& head
                                    , Tuples::Tuple& tuple ){

  const std::string prefix = fullName(head);
  Assert( P && mother, "This should not happen, you are inside TupleToolVtxIsoln.cpp :(" );
  // Check the ExtraInfo
  bool test = true ;
  if ( P->isBasicParticle() ) return StatusCode::SUCCESS ;
  // Fill tuple
  if ( P->hasInfo(m_indices.first) )
  {
    double def = -999999. ;
    double val ;
    for (int index = m_indices.first; index != m_indices.last; ++index)
    {
      val = P->info(index, def) ;
      test &= tuple->column(prefix+"_"+m_varNames[index], val);
    }
  }
  else
  {
    m_isolationTool->calculateExtraInfo(P, P) ;
    double val ;
    int result ;
    for (int index = m_indices.first; index != m_indices.last; ++index)
    {
      std::string name ;
      result = m_isolationTool->getInfo(index, val, name) ;
      if ( !result ) continue ;
      test &= tuple->column(prefix+"_"+name, val);
    }
  }
  return StatusCode(test) ;
}
//=============================================================================
// Fill
//=============================================================================
StatusCode TupleToolSelResults::fill( Tuples::Tuple& tup)
{
  const std::string prefix = fullName();
  bool test = true;
  for ( std::vector<std::string>::const_iterator s = m_selections.begin() ;
        s != m_selections.end(); ++s )
  {
    test &= tup->column(prefix+(*s),m_selTool->isSelected(*s));
    if (!test)
    {
      err() << "Cannot fill variable name " << prefix+(*s) << endmsg ;
      break;
    }
  }
  return StatusCode(test) ;
}
Exemple #9
0
// ============================================================================
// advanced column: time 
// ============================================================================
StatusCode GaudiPython::TupleDecorator::column
( const Tuples::Tuple&            tuple ,
  const std::string&              name  ,
  const Gaudi::Time&              value ) 
{ 
  if ( !tuple.valid() ) { return StatusCode::FAILURE ; }
  StatusCode sc = StatusCode::SUCCESS ;
  //
  sc = tuple->column ( name + "year"    , value.year    ( true )     , 1970 , 2070 ) ;
  if ( sc.isFailure() ) { return sc ; }
  sc = tuple->column ( name + "month"   , value.month   ( true ) + 1 , 1    ,   16 ) ;
  if ( sc.isFailure() ) { return sc ; }
  sc = tuple->column ( name + "day"     , value.day     ( true )     , 0    ,   32 ) ;
  if ( sc.isFailure() ) { return sc ; }
  sc = tuple->column ( name + "hour"    , value.hour    ( true )     , 0    ,   25 ) ;
  if ( sc.isFailure() ) { return sc ; }
  sc = tuple->column ( name + "minute"  , value.minute  ( true )     , 0    ,   61 ) ;
  if ( sc.isFailure() ) { return sc ; }
  sc = tuple->column ( name + "second"  , value.second  ( true )     , 0    ,   61 ) ;
  if ( sc.isFailure() ) { return sc ; }
  sc = tuple->column ( name + "nsecond" , value.nsecond () ) ;
  //
  return sc ;
}
StatusCode TupleToolTagging::fill( const Particle* mother
                                   , const Particle* P
                                   , const std::string& head
                                   , Tuples::Tuple& tuple )
{
  const std::string prefix=fullName(head);

  Assert( P && mother && m_dva && m_tagging,
          "Should not happen, you are inside TupleToolTagging.cpp" );

  std::string loc = objectLocation( P->parent() );

  // nothing to tag on something which is not a B
  if( !P->particleID().hasBottom() ) return StatusCode::SUCCESS;

  if( msgLevel( MSG::DEBUG ) ){
    debug() << " Going to Save Tagging information for B candidate "
            << endreq;
  }

  FlavourTag theTag;
  FlavourTags* tags = NULL;
  bool check = false;

  StatusCode sc=StatusCode::SUCCESS;

  boost::replace_all( loc, "/Particles", "/FlavourTags" );
  if( m_useFTonDST ) {
    if( exist < LHCb::FlavourTags > (loc,IgnoreRootInTES))
      tags = get< LHCb::FlavourTags > (loc,IgnoreRootInTES );
  }
  
  if (tags) {
    for(FlavourTags::const_iterator it = tags->begin(); it != tags->end(); ++it) {
      if( P != (**it).taggedB()) continue;
      theTag =  **it;
      check = true;
    }
    if (!check) sc = StatusCode::FAILURE;
  } else {
    const VertexBase* v = m_dva->bestVertex( mother );
    const RecVertex* vtx = dynamic_cast<const RecVertex*>(v);
    if( !vtx ){
      sc = m_tagging->tag( theTag, P );
    } else {
      sc = m_tagging->tag( theTag, P, vtx );
    }
  }
  // try to find unphysical defaults
  int dec = 0;
  double omega = 0.5;
  int decOS = 0;
  double omegaOS = 0.5;

  if( sc ){
    dec = theTag.decision();
    omega = theTag.omega(); // predicted wrong tag fraction.
    decOS = theTag.decisionOS();
    omegaOS = theTag.omegaOS(); // predicted wrong tag fraction.
  } else {
    Warning("The tagging algorithm failed");
  }

  bool test = true;
  test &= tuple->column( prefix+"_TAGDECISION" , dec );
  test &= tuple->column( prefix+"_TAGOMEGA" , omega );
  test &= tuple->column( prefix+"_TAGDECISION_OS" , decOS );
  test &= tuple->column( prefix+"_TAGOMEGA_OS" , omegaOS );

  int taggers_code = 0;
  // intialize tagger by tagger W :

  std::vector<Tagger> taggers = theTag.taggers();

  for(size_t i=0; i<taggers.size(); ++i) {
    int tdec = taggers[i].decision();

    if(tdec) switch ( taggers[i].type() ) {
    case Tagger::OS_Charm    : taggers_code +=1000000000 *(tdec+2); break;
    case Tagger::SS_Proton   : taggers_code += 100000000 *(tdec+2); break;
    case Tagger::OS_nnetKaon : taggers_code +=  10000000 *(tdec+2); break;
    case Tagger::SS_nnetKaon : taggers_code +=   1000000 *(tdec+2); break;
    case Tagger::OS_Muon     : taggers_code +=    100000 *(tdec+2); break;
    case Tagger::OS_Electron : taggers_code +=     10000 *(tdec+2); break;
    case Tagger::OS_Kaon     : taggers_code +=      1000 *(tdec+2); break;
    case Tagger::SS_Kaon     : taggers_code +=       100 *(tdec+2); break;
    case Tagger::SS_Pion     : taggers_code +=        10 *(tdec+2); break;
    case Tagger::VtxCharge   : taggers_code +=         1 *(tdec+2); break;

    }
  }
  
  test &= tuple->column( prefix+"_TAGGER" , taggers_code);
 
  if(isVerbose())  
  {    
    // Initialize all columns to default values
    for(size_t i=0; i<m_activeTaggers.size(); i++) {
        std::string active = m_activeTaggers[i];

        test &= tuple->column( prefix+"_"+active+"_DEC",  (short int)0 );
        test &= tuple->column( prefix+"_"+active+"_PROB", (float)0.5 );
        
        if(m_extendedTagging){
          if( true ) {
            std::vector<double> id, p, px, py, pz, pt, theta, phi;
            std::vector<double> pid_e, pid_mu, pid_k, pid_p;
            std::vector<double> ip, chi2, bip, bchi2, bp_chi2;
            
            const std::string num_name = prefix+"_"+active+"_PARTICLES_NUM";
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_ID", id.begin(), id.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_P", p.begin(), p.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PX", px.begin(), px.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PY", py.begin(), py.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PZ", pz.begin(), pz.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PT", pt.begin(), pt.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_THETA", theta.begin(), theta.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PHI", phi.begin(), phi.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PIDe", pid_e.begin(), pid_e.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PIDmu", pid_mu.begin(), pid_mu.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PIDk", pid_k.begin(), pid_k.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_PIDp", pid_p.begin(), pid_p.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_IP_OWNPV", ip.begin(), ip.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_IPCHI2_OWNPV", chi2.begin(), chi2.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_IP_BVertex", bip.begin(), bip.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_IPCHI2_BVertex", bchi2.begin(), bchi2.end(), num_name, 20 );
            test &= tuple->farray( prefix+"_"+active+"_PARTICLES_CHI2_BpVertex", bp_chi2.begin(), bp_chi2.end(), num_name, 20 );
            }
         }
                
    }  

    for(size_t i=0; i<taggers.size(); i++) {
      std::string name = m_tagger_map[(int)taggers[i].type()];

      //loop over active taggers only
      if(std::find(m_activeTaggers.begin(), m_activeTaggers.end(), name) != m_activeTaggers.end()) {
        Tagger tagger = taggers[i];

        test &= tuple->column( prefix+"_"+name+"_DEC",  tagger.decision() );
        test &= tuple->column( prefix+"_"+name+"_PROB", tagger.omega()    );

        if(m_extendedTagging){
          // Save interesting tagging data
          std::vector<double> id, p, px, py, pz, pt, theta, phi;
          std::vector<double> pid_e, pid_mu, pid_k, pid_p;
          std::vector<double> ip, chi2, bip, bchi2, bp_chi2;
          
          SmartRefVector<LHCb::Particle> parts = tagger.taggerParts();
          for(SmartRefVector<LHCb::Particle>::const_iterator it=parts.begin();
              it != parts.end(); it++) {
            
            VerboseData data = getVerboseData(*it, P);
            
            id.push_back(data.id);
            p.push_back(data.p);
            px.push_back(data.px);
            py.push_back(data.py);
            pz.push_back(data.pz);
            pt.push_back(data.pt);
            theta.push_back(data.theta);
            phi.push_back(data.phi);
            pid_e.push_back(data.pid_e);
            pid_mu.push_back(data.pid_mu);
            pid_k.push_back(data.pid_k);
            pid_p.push_back(data.pid_p);
            ip.push_back(data.ip);
            chi2.push_back(data.chi2);
            bip.push_back(data.bip);
            bchi2.push_back(data.bchi2);
            bp_chi2.push_back(data.bp_chi2);
          }
          
          const std::string num_name = prefix+"_"+name+"_PARTICLES_NUM";
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_ID", id.begin(), id.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_P", p.begin(), p.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PX", px.begin(), px.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PY", py.begin(), py.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PZ", pz.begin(), pz.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PT", pt.begin(), pt.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_THETA", theta.begin(), theta.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PHI", phi.begin(), phi.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PIDe", pid_e.begin(), pid_e.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PIDmu", pid_mu.begin(), pid_mu.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PIDk", pid_k.begin(), pid_k.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_PIDp", pid_p.begin(), pid_p.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_IP_OWNPV", ip.begin(), ip.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_IPCHI2_OWNPV", chi2.begin(), chi2.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_IP_BVertex", bip.begin(), bip.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_IPCHI2_BVertex", bchi2.begin(), bchi2.end(), num_name, 20 );
          test &= tuple->farray( prefix+"_"+name+"_PARTICLES_CHI2_BpVertex", bp_chi2.begin(), bp_chi2.end(), num_name, 20 );
        }        
      }      
    }    
  }
  

  if( msgLevel( MSG::DEBUG ) ){
    debug() << "Tagging summary: decision: " << dec
            << ", omega=" << omega << endreq;
  }

  return StatusCode(test);

}
//=========================================================================
//  Fill PV for all PV
//=========================================================================
StatusCode TupleToolGeometry::fillMinIP( const Particle* P,
                                         const std::string& prefix,
                                         Tuples::Tuple& tuple ) const
{
  bool test = true ;
  // minimum IP
  double ipmin = -1;
  double minchi2 = -1 ;

  double ipminnextbest = -1;
  double minchi2nextbest = -1;
  if(msgLevel(MSG::VERBOSE)) verbose() << "Looking for Min IP"  << endmsg  ;
  const RecVertex::Range PV = m_dva->primaryVertices();
  if(msgLevel(MSG::VERBOSE)) verbose() << "PV size: "  << PV.size() << endmsg  ;
  std::vector<double> ips, ipchi2s, diras;
  if ( !PV.empty() )
  {
    if(msgLevel(MSG::VERBOSE)) verbose() << "Filling IP " << prefix + "_MINIP : "
                                         << P << " PVs:" << PV.size() << endmsg ;

    for ( RecVertex::Range::const_iterator pv = PV.begin() ; pv!=PV.end() ; ++pv)
    {
      RecVertex newPV(**pv);
      if (m_refitPVs)
      {

        StatusCode scfit = m_pvReFitter->remove(P, &newPV);
        if(!scfit) { Warning("ReFitter fails!",StatusCode::SUCCESS,10).ignore(); continue; }
      }

      double ip, chi2;
      //StatusCode test2 = m_dist->distance ( P, *pv, ip, chi2 );

      LHCb::VertexBase* newPVPtr = (LHCb::VertexBase*)&newPV;
      StatusCode test2 = m_dist->distance ( P, newPVPtr, ip, chi2 );
      ips.push_back(ip);
      ipchi2s.push_back(chi2);
      if (P->endVertex()) diras.push_back(dira(newPVPtr,P));
      if( test2 && isVerbose() )
      {
        if ((ip<ipmin) || (ipmin<0.))
        {
          ipminnextbest = ipmin;
          ipmin = ip ;
        }
        else
        {
          if((ip < ipminnextbest) || (ipminnextbest < 0))
          {
            ipminnextbest = ip;
          }
        }

        if ((chi2<minchi2) || (minchi2<0.))
        {
          minchi2nextbest = minchi2;
          minchi2 = chi2 ;
        }
        else
        {
          if((chi2 < minchi2nextbest) || (minchi2nextbest < 0))
          {
            minchi2nextbest = chi2;
          }
        }
      }
    }
  }
  if (isVerbose()){
    if ( msgLevel(MSG::VERBOSE) )
    {
      verbose() << "Filling IP " << prefix + "_MINIP " << ipmin << " at " << minchi2 << endmsg  ;
      verbose() << "Filling IP next best " << prefix + "_MINIP " << ipminnextbest << " at "
                << minchi2nextbest << endmsg  ;
    }
    test &= tuple->column( prefix + "_MINIP", ipmin );
    test &= tuple->column( prefix + "_MINIPCHI2", minchi2 );
    
    test &= tuple->column( prefix + "_MINIPNEXTBEST", ipminnextbest );
    test &= tuple->column( prefix + "_MINIPCHI2NEXTBEST", minchi2nextbest );
  }
  if (m_fillMultiPV){
    test &= tuple->farray( prefix + "_AllIP", ips, "nPV", m_maxPV );
    test &= tuple->farray( prefix + "_AllIPchi2", ipchi2s, "nPV", m_maxPV );
    if (!diras.empty()) test &= tuple->farray( prefix + "_AllDIRA", diras, "nPV", m_maxPV );
    // --------------------------------------------------
  }
  
  if(msgLevel(MSG::VERBOSE))
    verbose() << "Return from fillMinIP: " << prefix  << " " << test << endmsg;
  if (!test)  Warning("Error in fillMinIP",1,StatusCode::FAILURE);
  return StatusCode(test) ;
}