ROOT logo
//*-- Author : M.Sanchez (14.06.2000)
#include "hmdcvertexfind.h"
#include "hcategory.h"
#include "hmdcgeompar.h"
#include "hades.h"
#include "hevent.h"
#include "hiterator.h"
#include "hruntimedb.h"
#include "hspectrometer.h"
#include "hgeomvector.h"
#include "hmdcdef.h"
#include "hmdcseg.h"
#include "hmdcsegsim.h"
#include "hmdchit.h"
#include "hmdchitsim.h"
#include "hgeomvolume.h"
#include "hrecevent.h"
#include "hpartialevent.h"
#include "hgeantdef.h"
#include "hgeantkine.h"
#include "TNtuple.h"

//_HADES_CLASS_DESCRIPTION
//////////////////////////////////////
// HMdcVertexFind
//
//   Vertex finder using weighted LSM with optional Tukey weights
//
// To use it in a macro just add
//
// taskset->add(new HMdcVertexFind("name","title",input_mode,tukey)
//
// where
//
// input_mode is one of HMdcVertexFind::kSegments or HMdcVertexFind::kHits.
// In the first case HMdcSeg objecst will be used as input (recomended for
// now) while in the secon HMdcHit objects will be used
//
// As for 'tukey' it can be kTRUE or kFALSE depending on if Tukey weights
// should be used in the minimization. For low multiplicity environments
// like C+C I would recomend kFALSE; at least until I have found better
// parameters for the Tukey weigths minimization.
//
//  static void setRejectEmbeddedTracks(Bool_t reject = kTRUE){rejectEmbeddedTracks = reject;}
//  static void setUseEventSeqNumber   (Bool_t use    = kTRUE){useEventSeqNumber    = use;   }
//  static void setSkipNoVertex        (Bool_t skip   = kTRUE){doSkipNoVertex       = skip;  }
//
// For the track embedding the are several configurations possible using
// the above static member functions.
// MODE:
//       1. THIS IS CLEARLY THE PREFERED METHOD IF ON NEEDS TO GET SIMULATED PARTICLES
//          AT EXACTLY THE SAME VERTEX AS THE REAL DATA!
//          READING vertex from HGeantKine objects (sim done with real vertices)
//          In this mode (useEventSeqNumber == kTRUE (default)) the event sequence number
//          of the real events which have been used to create the sim tracks with
//          PLUTO will be stored in the HGeantKine::userVal of the particles. If the
//          current event does not match the one from GEANT the event will be skipped as
//          Long_t as the numbers match again.
//       2. useEventSeqNumber == kFALSE. In this mode rejectEmbeddedTracks == kTRUE (default)
//          segments which keep GEANT track numbers and more than one contributing track number
//          will be skipped (minimize the influence of the embedded tracks to the vertex calculation).
//          Anyway the vertex will never be exactly the same as the one from the real dsts. Eventually
//          everything will go out of sync with the vertex of the sim input (if used real vertex with PLUTO)
//          because an additional event will skipped.
//          With rejectEmbeddedTracks == kFALSE all segments will be taken into account.
//       3. With doSkipNoVertex == kTRUE (default : kFALSE) events without calculated vertex will be skipped.
//          This mode has only influence if MODE 1 is not used, because here the events will be skipped.
//
/////////////////////////////////////////

Bool_t HMdcVertexFind::rejectEmbeddedTracks = kTRUE;
Bool_t HMdcVertexFind::useEventSeqNumber    = kTRUE;
Bool_t HMdcVertexFind::doSkipNoVertex       = kFALSE;
Bool_t HMdcVertexFind::doSkipFakeSegments   = kTRUE;
HMdcVertexFind::HMdcVertexFind(const Text_t name[],const Text_t title[],EInputMode m,
			       Bool_t tukey) :
    HReconstructor(name,title),fPos("HGeomVector",200),
    fAlpha("HGeomVector",200)
{
    initVars();
    useTukeyWeights(tukey);
    fInputMode = m;
}

HMdcVertexFind::~HMdcVertexFind(void)
{
    if(geantKineIter) {delete geantKineIter;}
    initVars();
}

void HMdcVertexFind::initVars(void)
{
    fInput         = 0;
    fGeometry      = 0;
    fIter          = 0;
    fMaxIterations = 100;
    fTukeyConst    = 6.0;
    fEpsilon       = .3;
    fUsingTukey    = kTRUE;
    fDebugMode     = kFALSE;
    fInputMode     = HMdcVertexFind::kSegments;
    isEmbedding    = kFALSE;
    geantKineIter  = 0;

    fseg0Chi2Cut       = 6;  // cut 10%
    fcallExecuteManual = kFALSE;
    setCut(-120,20,15);
    setMinReqTracks(10);
    setMinWindow(2);
    fProgressiveTukey = kFALSE;

}

Bool_t HMdcVertexFind::init(void)
{
    HRuntimeDb *rtdb = gHades->getRuntimeDb();
    HRecEvent *ev    = dynamic_cast<HRecEvent *>(gHades->getCurrentEvent());
    if(!ev) {return kFALSE;}

    switch(fInputMode)
    {
    case kSegments:
	fInput = gHades->getCurrentEvent()->getCategory(catMdcSeg);
	break;
    case kHits:
	fInput = gHades->getCurrentEvent()->getCategory(catMdcHit);
	break;
    default:
	fInput = 0;
    }
    if(!fInput) {return kFALSE;}
    //  else fIter=(HIterator *)fInput->MakeIterator();
    fGeometry     = (HMdcGeomPar *) rtdb->getContainer("MdcGeomPar");
    fSpecGeometry = (HSpecGeomPar *)rtdb->getContainer("SpecGeomPar");

    if(gHades->getOutputFile())
    {
	gHades->getOutputFile()->cd();
	//fData----
	// x,y,z,n : posicion del vertice en la iteracion n
	// con : converged??
	//fData=new TNtuple("Data","Data","x:y:z:n:con");
	if(fDebugMode) {fControl = new TNtuple("con","control","rho:dx:dy:dz:sector:module");}
    }

    //-----------------------------------------------
    // find out if we are running track embedding mode
    // This flag is later used to reject the embedded
    // simulated tracks from the vertex calculation
    isEmbedding = kFALSE;
    HCategory* geantKineCat = (HCategory*)gHades->getCurrentEvent()->getCategory(catGeantKine);
    if(gHades->getEmbeddingMode() > 0 && geantKineCat)
    {
	isEmbedding   = kTRUE;
	geantKineIter = geantKineCat->MakeIterator();
    }
    //-----------------------------------------------

    return kTRUE;
}

Bool_t HMdcVertexFind::finalize(void)
{
    return kTRUE;
}

Bool_t HMdcVertexFind::pointsToTarget(const HGeomVector &r,HGeomVector &alpha,
				      Int_t sector,Int_t module, Double_t locminZ,Double_t locmaxZ)
{
    //Gilipollas el HMdcSeg ya tiene esta informacion.....
    Double_t bx = alpha.getX() / alpha.getZ();
    Double_t by = alpha.getY() / alpha.getZ();
    Bool_t res  = kTRUE;
    HGeomVector rmin;

    //Evaluate maximum approach to z axis
    rmin.setZ(r.getZ() - (r.getX() * bx + r.getY() * by) / (bx * bx + by * by));
    rmin.setX(r.getX() + bx * (rmin.getZ() - r.getZ()));
    rmin.setY(r.getY() + by * (rmin.getZ() - r.getZ()));
    Double_t rhomin = TMath::Sqrt(rmin.getX() * rmin.getX() +
				  rmin.getY() * rmin.getY());

    //Impose condition
    if(fDebugMode){
	fControl->Fill(rhomin,rmin.getX(),rmin.getY(),rmin.getZ(),sector,module);
    }

    if(rmin.getZ() < locmaxZ && rmin.getZ() > locminZ && rhomin < fmaxR) {res = kTRUE;}
    else                                                                 {res = kFALSE;}

    return res;
}

void HMdcVertexFind::transform(HMdcSeg *hit,
			       HGeomVector &r,HGeomVector &alpha)
{
    //Calculates position and direction vector for a HMdcHit
    Float_t theta,phi;
    Double_t pi2 = TMath::Pi() / 2.;

    theta = hit->getTheta();
    phi   = hit->getPhi();
    r.setZ(hit->getZ());
    r.setX(hit->getR() * TMath::Cos(phi + pi2));
    r.setY(hit->getR() * TMath::Sin(phi + pi2));
    alpha.setZ(TMath::Cos(theta));
    alpha.setY(TMath::Sin(theta) * TMath::Sin(phi));
    alpha.setX(TMath::Sin(theta) * TMath::Cos(phi));
}

Bool_t HMdcVertexFind::readSegments(HGeomVector &estimate)
{
    HGeomVector *r,*alpha,rLocal,alphaLocal;
    HMdcSeg *data = 0;
    Int_t count   = 0;
    fInput        = gHades->getCurrentEvent()->getCategory(catMdcSeg);



    if(fInput)
    {
	//First vertex estimation and filling of fPos, fAlpha.

	Double_t locmaxZ = fmaxZ;
	Double_t locminZ = fminZ;

	fIter = (HIterator *)fInput->MakeIterator();
	fIter->Reset();
	fFitter.reset();

	vector <HMdcSeg*> usedCand;
        vector <HMdcSeg*> usedCandFinal;

	while( (data = (HMdcSeg *)fIter->Next()) != 0)
	{
	    // Transform from MDC system to LAB system
	    if(data->getIOSeg() == 0 && data->getChi2() >= 0)
	    {
                if(doSkipFakeSegments && data->isFake()) continue;

		if(isEmbedding && rejectEmbeddedTracks)
		{
		    // in embedding mode we have to reject the
		    // embedded tracks from vertex calculations

		    HMdcSegSim* datasim = (HMdcSegSim*) data;
		    if( (datasim->getTrack(0) > 0 && datasim->getNTracks() == 1) ||
		         datasim->getNTracks() > 1
		      )
		    {
			continue;
		    }
		}


		//---------------------------------------------
		// fill starting list
		if(data->getZ() < locmaxZ && data->getZ() > locminZ && data->getR() < fmaxR) {
		    usedCand.push_back(data);
		}
		//---------------------------------------------
	    }
	}
	delete fIter;


	if (usedCand.size() > 10) {  // we have enough tracks

	    vector <HMdcSeg*> usedCandTmp;
	    vector <HMdcSeg*> usedCandTmp2;
            vector<Double_t> values;
	    Double_t mean = 0;

	    for(UInt_t i = 0; i < usedCand.size() ; i ++){
                data = usedCand[i];
		if(data->getChi2() < getSeg0Chi2Cut()
		  ) {
		    usedCandFinal.push_back(data);
		    usedCandTmp2.push_back(data);
		    values.push_back(data->getZprime());
		}
	    }
	    mean = TMath::Mean(values.size(),values.data());

	    //------------------------------------------------------
            // filter more
	    if(usedCandFinal.size() > 0)
	    {
                
		Double_t accepted    = usedCandFinal.size();
                Double_t window      = 40;
                Int_t maxIteration   = 20;
		Double_t fac         = 0.8;
		Int_t it = 0;

		while (accepted >= fminReqTrack && window >= fminWindow && it < maxIteration){
                    it++;
		    usedCandTmp.clear();
		    accepted = 0;
                    values.clear();
		    //------------------------------------------------------
                    // calculate new mean + accepted tracks
		    for(UInt_t i = 0; i < usedCandFinal.size() ; i ++){
			data = usedCandFinal[i];
			Double_t zprime = data->getZprime() ;
			if( TMath::Abs(zprime - mean) < window){
                            values.push_back(zprime);
			    usedCandTmp.push_back(data);
			}
		    }
		    accepted = values.size();
		    //------------------------------------------------------

		    //------------------------------------------------------
		    // worked out : copy pointers
		    if(accepted >= fminReqTrack) {
			usedCandTmp2.clear();
			for(UInt_t i = 0; i < usedCandTmp.size() ; i ++){
			    usedCandTmp2.push_back(usedCandTmp[i]);
			}
			mean = TMath::Mean(values.size(),values.data());
			window *= fac; // shrink the window
		    }
		    //------------------------------------------------------

		} // end while
	    }
            //------------------------------------------------------

	    //------------------------------------------------------
            // copy to output
            usedCandFinal.clear();
	    for(UInt_t i = 0; i < usedCandTmp2.size() ; i ++){
		usedCandFinal.push_back(usedCandTmp2[i]);
	    }
            //------------------------------------------------------



	} else {  // do not cut sharp at low mult
	    for(UInt_t i = 0; i < usedCand.size() ; i ++){
		usedCandFinal.push_back(usedCand[i]);
	    }

	}

	for(UInt_t i = 0; i < usedCandFinal.size(); i ++)
	{
            data = usedCandFinal[i] ;

	    HGeomTransform &trans = fSpecGeometry->getSector(data->getSec())->getTransform();

	    transform(data,rLocal,alphaLocal);

	    r    = new(fPos  [count]) HGeomVector(trans.transFrom(rLocal));
	    alpha= new(fAlpha[count]) HGeomVector(trans.getRotMatrix() * alphaLocal);
	    //Feed to LSM fitter.
	    if(pointsToTarget(*r,*alpha,data->getSec(),0,locminZ,locmaxZ))
	    {
		fFitter.addLine(*r,*alpha); //Default weigth =1.0
		count ++;
	    }
	}


	if(count > 1){
	    fFitter.getVertex(estimate);  // will be  -1000,-1000,-1000 in case of fail
	} else {
	    estimate.setXYZ(-1000,-1000,-1000);
	    // in case we are running embedding we
	    // have to skip events with no vertex
	    if(isEmbedding){return kFALSE;}
	}

    } else {return kFALSE;}  // no input
    return kTRUE;
}

Bool_t HMdcVertexFind::readHits(HGeomVector &estimate)
{
    HGeomVector *r,*alpha,rLocal,alphaLocal;
    HMdcHit *data = 0;
    Int_t count   = 0,sector,module;
    Double_t dx,dy;

    fInput = gHades->getCurrentEvent()->getCategory(catMdcHit);
    if(fInput)
    {
	//First vertex estimation and filling of fPos, fAlpha.
	Double_t locmaxZ = fmaxZ;
	Double_t locminZ = fminZ;


	fIter = (HIterator *)fInput->MakeIterator();
	fIter->Reset();
	fFitter.reset();

	while( (data = (HMdcHit *)fIter->Next()) != 0)
	{
	    // Transform from MDC system to LAB system

	    if(isEmbedding && rejectEmbeddedTracks)
	    {
		// in embedding mode we have to reject the
		// embedded tracks from vertex calculations
		HMdcHitSim* datasim = (HMdcHitSim*) data;
		if( (datasim->getTrack(0) > 0 && datasim->getNTracks() == 1) ||
		     datasim->getNTracks() > 1
		  )
		{
		    continue;
		}
	    }

	    data->getSecMod(sector,module);
	    HGeomTransform &trans = fGeometry->getModule(sector,module)->getLabTransform();
	    rLocal.setX(data->getX());
	    rLocal.setY(data->getY());
	    rLocal.setZ(0.);
	    dx = data->getXDir();
	    dy = data->getYDir();
	    alphaLocal.setX(dx);
	    alphaLocal.setY(dy);
	    alphaLocal.setZ(TMath::Sqrt(1. - dx*dx - dy*dy));
	    r    = new(fPos  [count]) HGeomVector(trans.transFrom(rLocal));
	    alpha= new(fAlpha[count]) HGeomVector(trans.getRotMatrix() * alphaLocal);
	    //Feed to LSM fitter.
	    if(pointsToTarget(*r,*alpha,sector,module,locminZ,locmaxZ)){
		fFitter.addLine(*r,*alpha); //Default weigth =1.0
		count ++;
	    }
	}
	if(count>1){
	    fFitter.getVertex(estimate);
	} else {
	    estimate.setXYZ(-1000,-1000,-1000);
	    // in case we are running embedding we
	    // have to skip events with no vertex
	    if(isEmbedding) {return kFALSE;}
	}
    } else {return kFALSE;}
    return kTRUE;
}
Int_t HMdcVertexFind::execute(void)
{
    if(!fcallExecuteManual) return doFit();
    return 0;
}

Int_t HMdcVertexFind::doFit(void)
{
    HGeomVector *r,*alpha;
    HGeomVector oldVertex;
    HVertex     &event_vertex = gHades->getCurrentEvent()->getHeader()->getVertex();
    HGeomVector &vertex       = event_vertex.getPos();

    Int_t count = 0,i = 0,iteration = 0;
    Double_t weight,residual2,temp; //Weight and residual^2

    //-----------------------------------------------------------------
    // in embedding mode we have to take care
    // about the vertex : if useEventSeqNumber == kTRUE
    // we read the vertex coordinates of the primary GEANT
    // particles. To guaranty the sync between sim and real
    // we compare the event sequence numbers (written by PLUTO
    // to the userVal in HGeantKine). If a mismatch is detected
    // a kSkipEvent is returned (causing the second datasource
    // to rewind by one event).
    Float_t x,y,z;
    x = y = z = -1000;
    Int_t seqNumber   = -1;
    Int_t seqNumberEv = gHades->getCurrentEvent()->getHeader()->getEventSeqNumber();
    x = y = z = -1000;
    if(isEmbedding && useEventSeqNumber)
    {
	geantKineIter->Reset();
	HGeantKine* kine = 0;

	while( (kine = (HGeantKine*) geantKineIter->Next()) )
	{

	    if(kine->getParentTrack() == 0){
		kine->getVertex(x,y,z);
		seqNumber = (Int_t) kine->getUserVal();
		break;
	    }
	}

	if( seqNumber >= 0)
	{
	    if(seqNumberEv < seqNumber )  {    // we do not match the events
		return kSkipEvent;
	    } else if( seqNumberEv > seqNumber ){
		Error("HMdcVertexFind::execute()","Running in useEventSeqNumber == kTRUE mode , but seqNumberEv (%i)> seqNumber (%i) from GEANT!",seqNumberEv,seqNumber );
	    }
	} else {
	    Error("HMdcVertexFind::execute()","Running in useEventSeqNumber == kTRUE mode , but could not get seqNumber from GEANT!");
	}
	vertex.setXYZ(x,y,z);
	event_vertex.setPos(vertex);
	event_vertex.setSumOfWeights(-1);
	event_vertex.setChi2(-1);
	event_vertex.setIterations(-1);

	return 0;
    }
    //-----------------------------------------------------------------




    switch(fInputMode){
    case kSegments:
	if(!readSegments(vertex)){
	    if(isEmbedding && doSkipNoVertex) {return kSkipEvent;}
	    else                              {return 1;}
	}
	break;
    case kHits:
	if(!readHits(vertex)){
	    if(isEmbedding && doSkipNoVertex) {return kSkipEvent;}
	    else                              {return 1;}
	}
	break;
    default:
	Error("execute","Unrecognized mode");
    }
    if(fUsingTukey)
    {

	count = fPos.GetEntriesFast();
	if(count > 1 && (vertex.Z()!=-1000. && vertex.X()!=-1000. && vertex.Y()!=-1000.))
	{
	    Double_t locTukeyConst = fTukeyConst;

	    if(fProgressiveTukey){
		//--------------------------------------------------------
		// progressive tukey constants
		Double_t minTuk = 1.0;
		Double_t maxTuk = fTukeyConst;
		Int_t   minMult = 10;
		Int_t   maxMult = 30;

		if(count >= minMult && count < maxMult ){
		    locTukeyConst = maxTuk - ((maxTuk-minTuk)/(maxMult-minMult)) * (count-maxMult);

		} else if (count < minMult) {

		    locTukeyConst = maxTuk;

		} else if (count >= maxMult) {

		    locTukeyConst = minTuk;
		}
		//--------------------------------------------------------
	    }

	    //Iteration on weights
	    Float_t sumOfResiduals = 0;
	    Float_t sumOfWeights   = 0;
	    for (i = 0; i < count; i ++) {
		r     = (HGeomVector *)fPos.UncheckedAt(i);
		alpha = (HGeomVector *)fAlpha.UncheckedAt(i);
		temp  = ((r->getY() - vertex.getY()) * alpha->getZ() -
			 (r->getZ() - vertex.getZ()) * alpha->getY());
		residual2 = temp * temp;
		temp = ((r->getZ() - vertex.getZ()) * alpha->getX() -
			(r->getX() - vertex.getX()) * alpha->getZ());
		residual2 += temp * temp;
		temp = ((r->getX() - vertex.getX()) * alpha->getY() -
			(r->getY() - vertex.getY()) * alpha->getX());
		residual2 += temp * temp;

		sumOfResiduals += residual2;

	    }

	    Float_t width = locTukeyConst * sqrt(sumOfResiduals);


	    iteration = 0;
	    do
	    {
		sumOfResiduals = 0;
		sumOfWeights   = 0;
		oldVertex      = vertex;
		//fData->Fill(vertex(0),vertex(1),vertex(2),iteration,0.);
		iteration ++;
		fFitter.reset();
		for (i = 0; i <count; i ++)
		{
		    r     = (HGeomVector *)fPos.UncheckedAt(i);
		    alpha = (HGeomVector *)fAlpha.UncheckedAt(i);
		    temp  = ((r->getY() - oldVertex.getY()) * alpha->getZ() -
			     (r->getZ() - oldVertex.getZ()) * alpha->getY());
		    residual2 = temp * temp;
		    temp = ((r->getZ() - oldVertex.getZ()) * alpha->getX() -
			    (r->getX() - oldVertex.getX()) * alpha->getZ());
		    residual2 += temp * temp;
		    temp = ((r->getX() - oldVertex.getX()) * alpha->getY() -
			    (r->getY() - oldVertex.getY()) * alpha->getX());
		    residual2 += temp * temp;



		    temp   = sqrt(residual2);
		    weight = (temp < width) ? ((1. - (temp/width)*(temp/width)) *
					       (1. - (temp/width)*(temp/width))):0.0;
		    sumOfResiduals += weight*residual2;
		    sumOfWeights   += weight;
		    fFitter.addLine(*r,*alpha,weight);
		}
		width = locTukeyConst * sqrt(sumOfResiduals / sumOfWeights);

		fFitter.getVertex(vertex);
	    } // iteration loop
	    while(!hasConverged(vertex,oldVertex) && (iteration < fMaxIterations));


	    if(iteration < fMaxIterations){
		event_vertex.setIterations(iteration);
		event_vertex.setChi2(sumOfResiduals / sumOfWeights);
		event_vertex.setSumOfWeights(sumOfWeights);
	    } else {  // iteration >=  fMaxIterations
		event_vertex.setIterations(-2);
		event_vertex.setChi2(-1);
		event_vertex.setSumOfWeights(-1);
	    }
	} else {  // count <=1
	    event_vertex.setIterations(-1);
	    event_vertex.setChi2(-1);
	    event_vertex.setSumOfWeights(-1);
	}
	//fData->Fill(vertex(0),vertex(1),vertex(2),iteration,temp);
    } else {  // !fUsingTukey
	event_vertex.setIterations(1);
	event_vertex.setChi2(-1);
	event_vertex.setSumOfWeights(-1);
	//fData->Fill(vertex(0),vertex(1),vertex(2),0,1);
    }

    fPos.Clear();
    fAlpha.Clear();

    return 0;
}

Bool_t HMdcVertexFind::hasConverged(HGeomVector &v,HGeomVector &oldV) {
    Bool_t r =((v - oldV).length() < fEpsilon) ? kTRUE:kFALSE;
    return r;
}

ClassImp(HMdcVertexFind)
 hmdcvertexfind.cc:1
 hmdcvertexfind.cc:2
 hmdcvertexfind.cc:3
 hmdcvertexfind.cc:4
 hmdcvertexfind.cc:5
 hmdcvertexfind.cc:6
 hmdcvertexfind.cc:7
 hmdcvertexfind.cc:8
 hmdcvertexfind.cc:9
 hmdcvertexfind.cc:10
 hmdcvertexfind.cc:11
 hmdcvertexfind.cc:12
 hmdcvertexfind.cc:13
 hmdcvertexfind.cc:14
 hmdcvertexfind.cc:15
 hmdcvertexfind.cc:16
 hmdcvertexfind.cc:17
 hmdcvertexfind.cc:18
 hmdcvertexfind.cc:19
 hmdcvertexfind.cc:20
 hmdcvertexfind.cc:21
 hmdcvertexfind.cc:22
 hmdcvertexfind.cc:23
 hmdcvertexfind.cc:24
 hmdcvertexfind.cc:25
 hmdcvertexfind.cc:26
 hmdcvertexfind.cc:27
 hmdcvertexfind.cc:28
 hmdcvertexfind.cc:29
 hmdcvertexfind.cc:30
 hmdcvertexfind.cc:31
 hmdcvertexfind.cc:32
 hmdcvertexfind.cc:33
 hmdcvertexfind.cc:34
 hmdcvertexfind.cc:35
 hmdcvertexfind.cc:36
 hmdcvertexfind.cc:37
 hmdcvertexfind.cc:38
 hmdcvertexfind.cc:39
 hmdcvertexfind.cc:40
 hmdcvertexfind.cc:41
 hmdcvertexfind.cc:42
 hmdcvertexfind.cc:43
 hmdcvertexfind.cc:44
 hmdcvertexfind.cc:45
 hmdcvertexfind.cc:46
 hmdcvertexfind.cc:47
 hmdcvertexfind.cc:48
 hmdcvertexfind.cc:49
 hmdcvertexfind.cc:50
 hmdcvertexfind.cc:51
 hmdcvertexfind.cc:52
 hmdcvertexfind.cc:53
 hmdcvertexfind.cc:54
 hmdcvertexfind.cc:55
 hmdcvertexfind.cc:56
 hmdcvertexfind.cc:57
 hmdcvertexfind.cc:58
 hmdcvertexfind.cc:59
 hmdcvertexfind.cc:60
 hmdcvertexfind.cc:61
 hmdcvertexfind.cc:62
 hmdcvertexfind.cc:63
 hmdcvertexfind.cc:64
 hmdcvertexfind.cc:65
 hmdcvertexfind.cc:66
 hmdcvertexfind.cc:67
 hmdcvertexfind.cc:68
 hmdcvertexfind.cc:69
 hmdcvertexfind.cc:70
 hmdcvertexfind.cc:71
 hmdcvertexfind.cc:72
 hmdcvertexfind.cc:73
 hmdcvertexfind.cc:74
 hmdcvertexfind.cc:75
 hmdcvertexfind.cc:76
 hmdcvertexfind.cc:77
 hmdcvertexfind.cc:78
 hmdcvertexfind.cc:79
 hmdcvertexfind.cc:80
 hmdcvertexfind.cc:81
 hmdcvertexfind.cc:82
 hmdcvertexfind.cc:83
 hmdcvertexfind.cc:84
 hmdcvertexfind.cc:85
 hmdcvertexfind.cc:86
 hmdcvertexfind.cc:87
 hmdcvertexfind.cc:88
 hmdcvertexfind.cc:89
 hmdcvertexfind.cc:90
 hmdcvertexfind.cc:91
 hmdcvertexfind.cc:92
 hmdcvertexfind.cc:93
 hmdcvertexfind.cc:94
 hmdcvertexfind.cc:95
 hmdcvertexfind.cc:96
 hmdcvertexfind.cc:97
 hmdcvertexfind.cc:98
 hmdcvertexfind.cc:99
 hmdcvertexfind.cc:100
 hmdcvertexfind.cc:101
 hmdcvertexfind.cc:102
 hmdcvertexfind.cc:103
 hmdcvertexfind.cc:104
 hmdcvertexfind.cc:105
 hmdcvertexfind.cc:106
 hmdcvertexfind.cc:107
 hmdcvertexfind.cc:108
 hmdcvertexfind.cc:109
 hmdcvertexfind.cc:110
 hmdcvertexfind.cc:111
 hmdcvertexfind.cc:112
 hmdcvertexfind.cc:113
 hmdcvertexfind.cc:114
 hmdcvertexfind.cc:115
 hmdcvertexfind.cc:116
 hmdcvertexfind.cc:117
 hmdcvertexfind.cc:118
 hmdcvertexfind.cc:119
 hmdcvertexfind.cc:120
 hmdcvertexfind.cc:121
 hmdcvertexfind.cc:122
 hmdcvertexfind.cc:123
 hmdcvertexfind.cc:124
 hmdcvertexfind.cc:125
 hmdcvertexfind.cc:126
 hmdcvertexfind.cc:127
 hmdcvertexfind.cc:128
 hmdcvertexfind.cc:129
 hmdcvertexfind.cc:130
 hmdcvertexfind.cc:131
 hmdcvertexfind.cc:132
 hmdcvertexfind.cc:133
 hmdcvertexfind.cc:134
 hmdcvertexfind.cc:135
 hmdcvertexfind.cc:136
 hmdcvertexfind.cc:137
 hmdcvertexfind.cc:138
 hmdcvertexfind.cc:139
 hmdcvertexfind.cc:140
 hmdcvertexfind.cc:141
 hmdcvertexfind.cc:142
 hmdcvertexfind.cc:143
 hmdcvertexfind.cc:144
 hmdcvertexfind.cc:145
 hmdcvertexfind.cc:146
 hmdcvertexfind.cc:147
 hmdcvertexfind.cc:148
 hmdcvertexfind.cc:149
 hmdcvertexfind.cc:150
 hmdcvertexfind.cc:151
 hmdcvertexfind.cc:152
 hmdcvertexfind.cc:153
 hmdcvertexfind.cc:154
 hmdcvertexfind.cc:155
 hmdcvertexfind.cc:156
 hmdcvertexfind.cc:157
 hmdcvertexfind.cc:158
 hmdcvertexfind.cc:159
 hmdcvertexfind.cc:160
 hmdcvertexfind.cc:161
 hmdcvertexfind.cc:162
 hmdcvertexfind.cc:163
 hmdcvertexfind.cc:164
 hmdcvertexfind.cc:165
 hmdcvertexfind.cc:166
 hmdcvertexfind.cc:167
 hmdcvertexfind.cc:168
 hmdcvertexfind.cc:169
 hmdcvertexfind.cc:170
 hmdcvertexfind.cc:171
 hmdcvertexfind.cc:172
 hmdcvertexfind.cc:173
 hmdcvertexfind.cc:174
 hmdcvertexfind.cc:175
 hmdcvertexfind.cc:176
 hmdcvertexfind.cc:177
 hmdcvertexfind.cc:178
 hmdcvertexfind.cc:179
 hmdcvertexfind.cc:180
 hmdcvertexfind.cc:181
 hmdcvertexfind.cc:182
 hmdcvertexfind.cc:183
 hmdcvertexfind.cc:184
 hmdcvertexfind.cc:185
 hmdcvertexfind.cc:186
 hmdcvertexfind.cc:187
 hmdcvertexfind.cc:188
 hmdcvertexfind.cc:189
 hmdcvertexfind.cc:190
 hmdcvertexfind.cc:191
 hmdcvertexfind.cc:192
 hmdcvertexfind.cc:193
 hmdcvertexfind.cc:194
 hmdcvertexfind.cc:195
 hmdcvertexfind.cc:196
 hmdcvertexfind.cc:197
 hmdcvertexfind.cc:198
 hmdcvertexfind.cc:199
 hmdcvertexfind.cc:200
 hmdcvertexfind.cc:201
 hmdcvertexfind.cc:202
 hmdcvertexfind.cc:203
 hmdcvertexfind.cc:204
 hmdcvertexfind.cc:205
 hmdcvertexfind.cc:206
 hmdcvertexfind.cc:207
 hmdcvertexfind.cc:208
 hmdcvertexfind.cc:209
 hmdcvertexfind.cc:210
 hmdcvertexfind.cc:211
 hmdcvertexfind.cc:212
 hmdcvertexfind.cc:213
 hmdcvertexfind.cc:214
 hmdcvertexfind.cc:215
 hmdcvertexfind.cc:216
 hmdcvertexfind.cc:217
 hmdcvertexfind.cc:218
 hmdcvertexfind.cc:219
 hmdcvertexfind.cc:220
 hmdcvertexfind.cc:221
 hmdcvertexfind.cc:222
 hmdcvertexfind.cc:223
 hmdcvertexfind.cc:224
 hmdcvertexfind.cc:225
 hmdcvertexfind.cc:226
 hmdcvertexfind.cc:227
 hmdcvertexfind.cc:228
 hmdcvertexfind.cc:229
 hmdcvertexfind.cc:230
 hmdcvertexfind.cc:231
 hmdcvertexfind.cc:232
 hmdcvertexfind.cc:233
 hmdcvertexfind.cc:234
 hmdcvertexfind.cc:235
 hmdcvertexfind.cc:236
 hmdcvertexfind.cc:237
 hmdcvertexfind.cc:238
 hmdcvertexfind.cc:239
 hmdcvertexfind.cc:240
 hmdcvertexfind.cc:241
 hmdcvertexfind.cc:242
 hmdcvertexfind.cc:243
 hmdcvertexfind.cc:244
 hmdcvertexfind.cc:245
 hmdcvertexfind.cc:246
 hmdcvertexfind.cc:247
 hmdcvertexfind.cc:248
 hmdcvertexfind.cc:249
 hmdcvertexfind.cc:250
 hmdcvertexfind.cc:251
 hmdcvertexfind.cc:252
 hmdcvertexfind.cc:253
 hmdcvertexfind.cc:254
 hmdcvertexfind.cc:255
 hmdcvertexfind.cc:256
 hmdcvertexfind.cc:257
 hmdcvertexfind.cc:258
 hmdcvertexfind.cc:259
 hmdcvertexfind.cc:260
 hmdcvertexfind.cc:261
 hmdcvertexfind.cc:262
 hmdcvertexfind.cc:263
 hmdcvertexfind.cc:264
 hmdcvertexfind.cc:265
 hmdcvertexfind.cc:266
 hmdcvertexfind.cc:267
 hmdcvertexfind.cc:268
 hmdcvertexfind.cc:269
 hmdcvertexfind.cc:270
 hmdcvertexfind.cc:271
 hmdcvertexfind.cc:272
 hmdcvertexfind.cc:273
 hmdcvertexfind.cc:274
 hmdcvertexfind.cc:275
 hmdcvertexfind.cc:276
 hmdcvertexfind.cc:277
 hmdcvertexfind.cc:278
 hmdcvertexfind.cc:279
 hmdcvertexfind.cc:280
 hmdcvertexfind.cc:281
 hmdcvertexfind.cc:282
 hmdcvertexfind.cc:283
 hmdcvertexfind.cc:284
 hmdcvertexfind.cc:285
 hmdcvertexfind.cc:286
 hmdcvertexfind.cc:287
 hmdcvertexfind.cc:288
 hmdcvertexfind.cc:289
 hmdcvertexfind.cc:290
 hmdcvertexfind.cc:291
 hmdcvertexfind.cc:292
 hmdcvertexfind.cc:293
 hmdcvertexfind.cc:294
 hmdcvertexfind.cc:295
 hmdcvertexfind.cc:296
 hmdcvertexfind.cc:297
 hmdcvertexfind.cc:298
 hmdcvertexfind.cc:299
 hmdcvertexfind.cc:300
 hmdcvertexfind.cc:301
 hmdcvertexfind.cc:302
 hmdcvertexfind.cc:303
 hmdcvertexfind.cc:304
 hmdcvertexfind.cc:305
 hmdcvertexfind.cc:306
 hmdcvertexfind.cc:307
 hmdcvertexfind.cc:308
 hmdcvertexfind.cc:309
 hmdcvertexfind.cc:310
 hmdcvertexfind.cc:311
 hmdcvertexfind.cc:312
 hmdcvertexfind.cc:313
 hmdcvertexfind.cc:314
 hmdcvertexfind.cc:315
 hmdcvertexfind.cc:316
 hmdcvertexfind.cc:317
 hmdcvertexfind.cc:318
 hmdcvertexfind.cc:319
 hmdcvertexfind.cc:320
 hmdcvertexfind.cc:321
 hmdcvertexfind.cc:322
 hmdcvertexfind.cc:323
 hmdcvertexfind.cc:324
 hmdcvertexfind.cc:325
 hmdcvertexfind.cc:326
 hmdcvertexfind.cc:327
 hmdcvertexfind.cc:328
 hmdcvertexfind.cc:329
 hmdcvertexfind.cc:330
 hmdcvertexfind.cc:331
 hmdcvertexfind.cc:332
 hmdcvertexfind.cc:333
 hmdcvertexfind.cc:334
 hmdcvertexfind.cc:335
 hmdcvertexfind.cc:336
 hmdcvertexfind.cc:337
 hmdcvertexfind.cc:338
 hmdcvertexfind.cc:339
 hmdcvertexfind.cc:340
 hmdcvertexfind.cc:341
 hmdcvertexfind.cc:342
 hmdcvertexfind.cc:343
 hmdcvertexfind.cc:344
 hmdcvertexfind.cc:345
 hmdcvertexfind.cc:346
 hmdcvertexfind.cc:347
 hmdcvertexfind.cc:348
 hmdcvertexfind.cc:349
 hmdcvertexfind.cc:350
 hmdcvertexfind.cc:351
 hmdcvertexfind.cc:352
 hmdcvertexfind.cc:353
 hmdcvertexfind.cc:354
 hmdcvertexfind.cc:355
 hmdcvertexfind.cc:356
 hmdcvertexfind.cc:357
 hmdcvertexfind.cc:358
 hmdcvertexfind.cc:359
 hmdcvertexfind.cc:360
 hmdcvertexfind.cc:361
 hmdcvertexfind.cc:362
 hmdcvertexfind.cc:363
 hmdcvertexfind.cc:364
 hmdcvertexfind.cc:365
 hmdcvertexfind.cc:366
 hmdcvertexfind.cc:367
 hmdcvertexfind.cc:368
 hmdcvertexfind.cc:369
 hmdcvertexfind.cc:370
 hmdcvertexfind.cc:371
 hmdcvertexfind.cc:372
 hmdcvertexfind.cc:373
 hmdcvertexfind.cc:374
 hmdcvertexfind.cc:375
 hmdcvertexfind.cc:376
 hmdcvertexfind.cc:377
 hmdcvertexfind.cc:378
 hmdcvertexfind.cc:379
 hmdcvertexfind.cc:380
 hmdcvertexfind.cc:381
 hmdcvertexfind.cc:382
 hmdcvertexfind.cc:383
 hmdcvertexfind.cc:384
 hmdcvertexfind.cc:385
 hmdcvertexfind.cc:386
 hmdcvertexfind.cc:387
 hmdcvertexfind.cc:388
 hmdcvertexfind.cc:389
 hmdcvertexfind.cc:390
 hmdcvertexfind.cc:391
 hmdcvertexfind.cc:392
 hmdcvertexfind.cc:393
 hmdcvertexfind.cc:394
 hmdcvertexfind.cc:395
 hmdcvertexfind.cc:396
 hmdcvertexfind.cc:397
 hmdcvertexfind.cc:398
 hmdcvertexfind.cc:399
 hmdcvertexfind.cc:400
 hmdcvertexfind.cc:401
 hmdcvertexfind.cc:402
 hmdcvertexfind.cc:403
 hmdcvertexfind.cc:404
 hmdcvertexfind.cc:405
 hmdcvertexfind.cc:406
 hmdcvertexfind.cc:407
 hmdcvertexfind.cc:408
 hmdcvertexfind.cc:409
 hmdcvertexfind.cc:410
 hmdcvertexfind.cc:411
 hmdcvertexfind.cc:412
 hmdcvertexfind.cc:413
 hmdcvertexfind.cc:414
 hmdcvertexfind.cc:415
 hmdcvertexfind.cc:416
 hmdcvertexfind.cc:417
 hmdcvertexfind.cc:418
 hmdcvertexfind.cc:419
 hmdcvertexfind.cc:420
 hmdcvertexfind.cc:421
 hmdcvertexfind.cc:422
 hmdcvertexfind.cc:423
 hmdcvertexfind.cc:424
 hmdcvertexfind.cc:425
 hmdcvertexfind.cc:426
 hmdcvertexfind.cc:427
 hmdcvertexfind.cc:428
 hmdcvertexfind.cc:429
 hmdcvertexfind.cc:430
 hmdcvertexfind.cc:431
 hmdcvertexfind.cc:432
 hmdcvertexfind.cc:433
 hmdcvertexfind.cc:434
 hmdcvertexfind.cc:435
 hmdcvertexfind.cc:436
 hmdcvertexfind.cc:437
 hmdcvertexfind.cc:438
 hmdcvertexfind.cc:439
 hmdcvertexfind.cc:440
 hmdcvertexfind.cc:441
 hmdcvertexfind.cc:442
 hmdcvertexfind.cc:443
 hmdcvertexfind.cc:444
 hmdcvertexfind.cc:445
 hmdcvertexfind.cc:446
 hmdcvertexfind.cc:447
 hmdcvertexfind.cc:448
 hmdcvertexfind.cc:449
 hmdcvertexfind.cc:450
 hmdcvertexfind.cc:451
 hmdcvertexfind.cc:452
 hmdcvertexfind.cc:453
 hmdcvertexfind.cc:454
 hmdcvertexfind.cc:455
 hmdcvertexfind.cc:456
 hmdcvertexfind.cc:457
 hmdcvertexfind.cc:458
 hmdcvertexfind.cc:459
 hmdcvertexfind.cc:460
 hmdcvertexfind.cc:461
 hmdcvertexfind.cc:462
 hmdcvertexfind.cc:463
 hmdcvertexfind.cc:464
 hmdcvertexfind.cc:465
 hmdcvertexfind.cc:466
 hmdcvertexfind.cc:467
 hmdcvertexfind.cc:468
 hmdcvertexfind.cc:469
 hmdcvertexfind.cc:470
 hmdcvertexfind.cc:471
 hmdcvertexfind.cc:472
 hmdcvertexfind.cc:473
 hmdcvertexfind.cc:474
 hmdcvertexfind.cc:475
 hmdcvertexfind.cc:476
 hmdcvertexfind.cc:477
 hmdcvertexfind.cc:478
 hmdcvertexfind.cc:479
 hmdcvertexfind.cc:480
 hmdcvertexfind.cc:481
 hmdcvertexfind.cc:482
 hmdcvertexfind.cc:483
 hmdcvertexfind.cc:484
 hmdcvertexfind.cc:485
 hmdcvertexfind.cc:486
 hmdcvertexfind.cc:487
 hmdcvertexfind.cc:488
 hmdcvertexfind.cc:489
 hmdcvertexfind.cc:490
 hmdcvertexfind.cc:491
 hmdcvertexfind.cc:492
 hmdcvertexfind.cc:493
 hmdcvertexfind.cc:494
 hmdcvertexfind.cc:495
 hmdcvertexfind.cc:496
 hmdcvertexfind.cc:497
 hmdcvertexfind.cc:498
 hmdcvertexfind.cc:499
 hmdcvertexfind.cc:500
 hmdcvertexfind.cc:501
 hmdcvertexfind.cc:502
 hmdcvertexfind.cc:503
 hmdcvertexfind.cc:504
 hmdcvertexfind.cc:505
 hmdcvertexfind.cc:506
 hmdcvertexfind.cc:507
 hmdcvertexfind.cc:508
 hmdcvertexfind.cc:509
 hmdcvertexfind.cc:510
 hmdcvertexfind.cc:511
 hmdcvertexfind.cc:512
 hmdcvertexfind.cc:513
 hmdcvertexfind.cc:514
 hmdcvertexfind.cc:515
 hmdcvertexfind.cc:516
 hmdcvertexfind.cc:517
 hmdcvertexfind.cc:518
 hmdcvertexfind.cc:519
 hmdcvertexfind.cc:520
 hmdcvertexfind.cc:521
 hmdcvertexfind.cc:522
 hmdcvertexfind.cc:523
 hmdcvertexfind.cc:524
 hmdcvertexfind.cc:525
 hmdcvertexfind.cc:526
 hmdcvertexfind.cc:527
 hmdcvertexfind.cc:528
 hmdcvertexfind.cc:529
 hmdcvertexfind.cc:530
 hmdcvertexfind.cc:531
 hmdcvertexfind.cc:532
 hmdcvertexfind.cc:533
 hmdcvertexfind.cc:534
 hmdcvertexfind.cc:535
 hmdcvertexfind.cc:536
 hmdcvertexfind.cc:537
 hmdcvertexfind.cc:538
 hmdcvertexfind.cc:539
 hmdcvertexfind.cc:540
 hmdcvertexfind.cc:541
 hmdcvertexfind.cc:542
 hmdcvertexfind.cc:543
 hmdcvertexfind.cc:544
 hmdcvertexfind.cc:545
 hmdcvertexfind.cc:546
 hmdcvertexfind.cc:547
 hmdcvertexfind.cc:548
 hmdcvertexfind.cc:549
 hmdcvertexfind.cc:550
 hmdcvertexfind.cc:551
 hmdcvertexfind.cc:552
 hmdcvertexfind.cc:553
 hmdcvertexfind.cc:554
 hmdcvertexfind.cc:555
 hmdcvertexfind.cc:556
 hmdcvertexfind.cc:557
 hmdcvertexfind.cc:558
 hmdcvertexfind.cc:559
 hmdcvertexfind.cc:560
 hmdcvertexfind.cc:561
 hmdcvertexfind.cc:562
 hmdcvertexfind.cc:563
 hmdcvertexfind.cc:564
 hmdcvertexfind.cc:565
 hmdcvertexfind.cc:566
 hmdcvertexfind.cc:567
 hmdcvertexfind.cc:568
 hmdcvertexfind.cc:569
 hmdcvertexfind.cc:570
 hmdcvertexfind.cc:571
 hmdcvertexfind.cc:572
 hmdcvertexfind.cc:573
 hmdcvertexfind.cc:574
 hmdcvertexfind.cc:575
 hmdcvertexfind.cc:576
 hmdcvertexfind.cc:577
 hmdcvertexfind.cc:578
 hmdcvertexfind.cc:579
 hmdcvertexfind.cc:580
 hmdcvertexfind.cc:581
 hmdcvertexfind.cc:582
 hmdcvertexfind.cc:583
 hmdcvertexfind.cc:584
 hmdcvertexfind.cc:585
 hmdcvertexfind.cc:586
 hmdcvertexfind.cc:587
 hmdcvertexfind.cc:588
 hmdcvertexfind.cc:589
 hmdcvertexfind.cc:590
 hmdcvertexfind.cc:591
 hmdcvertexfind.cc:592
 hmdcvertexfind.cc:593
 hmdcvertexfind.cc:594
 hmdcvertexfind.cc:595
 hmdcvertexfind.cc:596
 hmdcvertexfind.cc:597
 hmdcvertexfind.cc:598
 hmdcvertexfind.cc:599
 hmdcvertexfind.cc:600
 hmdcvertexfind.cc:601
 hmdcvertexfind.cc:602
 hmdcvertexfind.cc:603
 hmdcvertexfind.cc:604
 hmdcvertexfind.cc:605
 hmdcvertexfind.cc:606
 hmdcvertexfind.cc:607
 hmdcvertexfind.cc:608
 hmdcvertexfind.cc:609
 hmdcvertexfind.cc:610
 hmdcvertexfind.cc:611
 hmdcvertexfind.cc:612
 hmdcvertexfind.cc:613
 hmdcvertexfind.cc:614
 hmdcvertexfind.cc:615
 hmdcvertexfind.cc:616
 hmdcvertexfind.cc:617
 hmdcvertexfind.cc:618
 hmdcvertexfind.cc:619
 hmdcvertexfind.cc:620
 hmdcvertexfind.cc:621
 hmdcvertexfind.cc:622
 hmdcvertexfind.cc:623
 hmdcvertexfind.cc:624
 hmdcvertexfind.cc:625
 hmdcvertexfind.cc:626
 hmdcvertexfind.cc:627
 hmdcvertexfind.cc:628
 hmdcvertexfind.cc:629
 hmdcvertexfind.cc:630
 hmdcvertexfind.cc:631
 hmdcvertexfind.cc:632
 hmdcvertexfind.cc:633
 hmdcvertexfind.cc:634
 hmdcvertexfind.cc:635
 hmdcvertexfind.cc:636
 hmdcvertexfind.cc:637
 hmdcvertexfind.cc:638
 hmdcvertexfind.cc:639
 hmdcvertexfind.cc:640
 hmdcvertexfind.cc:641
 hmdcvertexfind.cc:642
 hmdcvertexfind.cc:643
 hmdcvertexfind.cc:644
 hmdcvertexfind.cc:645
 hmdcvertexfind.cc:646
 hmdcvertexfind.cc:647
 hmdcvertexfind.cc:648
 hmdcvertexfind.cc:649
 hmdcvertexfind.cc:650
 hmdcvertexfind.cc:651
 hmdcvertexfind.cc:652
 hmdcvertexfind.cc:653