{
    //Let us create a "virtual detector"
    //First, we create dummy root files
    //For a real detector, they can be derived e.g.
    //from a full GEANT simulation and re-opened
    //here from a ROOT file
    //Our dummy detector should have an acceptance
    //for electrons in forward directions
    //between 18 - 95 degrees. The efficiency
    //of electrons should be 80%,
    //in a momentum range below 100 MeV only 50,
    //and below 50 MeV no acceptance
    //Protons should have a flat acceptance of 90%
    //using a forward detector (a plane) in 
    //a distance of 2m downstream with 3x3m
    //Other particles are rejected
    //Remember, this is NOT HADES
    //This filter should come in 2 modi operandi:
    //1. For inclusive measurements (e+e-)
    //2. For exclusive measurements (ppe+e-)
    
    //Make a pseudo-Monto-Carlo simulation:
    //Generate particles between: 
    //mom = 0 ... 3000 MeV   (x)
    //cos(theta) = -1 ... 1  (y)
    //phi = 0 ... 360 deg    (z)
    //On purpose, we do not use the Pluto convention
    //to demonstrate the convertion inside the command list
    //In addition, we apply a 1% momentum resolution...
    //...just fixed, to keep it easy. Of course it is possible
    //to use matrices as well
    //This is controlled via "filter_smear_factor"
    //Create the efficiency matrices:
    TH3F *gen = 
	new TH3F ("gen", "Generated events", 30, 0, 1500, 20, -1, 1, 20, 0, 360);
    TH3F *eff_elec = 
	new TH3F ("eff_elec", "Efficiency matrix electrons", 30, 0, 1500, 20, -1, 1, 20, 0, 360);    
    TH3F *eff_protons = 
	new TH3F ("eff_protons", "Efficiency matrix protons", 30, 0, 1500, 20, -1, 1, 20, 0, 360);
    //Start the Monte-Carlo
    int nev = 1000000;
    for (int i=0; i<nev; i++) {
	Double_t mom = PUtils::sampleFlat()*3000;
	Double_t costheta = PUtils::sampleFlat()*2 - 1;
	Double_t phi = PUtils::sampleFlat()*360;
	
	gen->Fill(mom, costheta, phi);
	Double_t theta = acos(costheta)*180/TMath::Pi();
	//electrons
	if ((theta > 18) && (theta < 95)) {
	    Double_t rnd = PUtils::sampleFlat();
	    if ((mom > 100) && (rnd < 0.8))
		eff_elec->Fill(mom, costheta, phi);
	    else if ((mom > 50) && (rnd < 0.5))
		eff_elec->Fill(mom, costheta, phi);	    
	}
	//protons
	Double_t x = tan(acos(costheta)) * 2 * cos(phi*TMath::Pi()/180);
	Double_t y = tan(acos(costheta)) * 2 * sin(phi*TMath::Pi()/180);
	
	if ((fabs(x) < 1.5) && (fabs(y) < 1.5)) {
	    Double_t rnd = PUtils::sampleFlat();
	    if (rnd < 0.90)
		eff_protons->Fill(mom,costheta,phi);
	}
    }
    eff_elec->Divide(gen);
    eff_protons->Divide(gen);
    //Now we create the filter file
    TFile *f = new TFile("pluto_demo_filter.root", "RECREATE");
    //Commands with the keyword "_main" are called when the filter is attached
    PCommandList *p = new PCommandList("_main", "echo **** This is our demo filter, v1");
    
    //A little bit of hello information:
    p->AddCommand("echo ********************************************************************************");
    p->AddCommand("echo Usage:      This filter works in 2 modi:");
    p->AddCommand("echo Usage:      1.) inclusive:");
    p->AddCommand("echo Usage:          default");
    p->AddCommand("echo Usage:      2.) exclusive measurement:");
    p->AddCommand("echo Usage:          Add in your macro after filter attachment:");
    p->AddCommand("echo Usage:          makeDistributionManager()->Startup(\"_filter_exclusive=1\");");
    p->AddCommand("echo ********************************************************************************");
    p->AddCommand("echo Usage:      Momentum smearing is applied, you can change:");
    p->AddCommand("echo Usage:          makeDistributionManager()->Startup(\"_filter_smear_factor=....\");");
    p->AddCommand("echo ********************************************************************************");
    p->AddCommand("echo Debug mode:     makeDistributionManager()->Startup(\"_filter_debug=1\");");
    p->AddCommand("echo ********************************************************************************");
    //Generate variables
    p->AddCommand("_filter_debug=0");
    p->AddCommand("_filter_exclusive=0");
    p->AddCommand("_filter_smear_factor=1.");
    p->Write();
    //Commands with the keyword "_startup" are called when event loop is started
    //Here, it is used to add another warning
    PCommandList *s = 
	new PCommandList("_startup", 
			 "echo ********************************************************************************");
    
    s->AddCommand("echo This event loop uses the demo filter ");
    s->AddCommand("echo ********************************************************************************");
    s->Write();
    //Commands with the keyword "_loop" are called within event loop
    //Labels should be unique. Avoid common names
    PCommandList *l = new PCommandList("_loop");
    //The first thing we have to do is to calculate for each particle under test the axes values
    l->AddCommand("if (_filter_debug); echo **** New event called"); //do not forget the ";" after the if-statement
    l->AddCommand("_start: removed=0");                   //labels with colon
    l->AddCommand("_x = [e+]->P() * 1000.; ");  //Conversion of units
    l->AddCommand("_y = [e+]->CosTheta(); ");
    l->AddCommand("_z = (([e+]->Phi()) *180/TMath::Pi()); if (_z<0); _z = _z + 360");
    l->AddCommand(eff_elec,"eff_ep = Eval(); rnd =  sampleFlat(); if (rnd>eff_ep); [e+]->SetInActive(); removed=1");
    l->AddCommand("mom = [e+]->P(); newmom = sampleGaus(mom,0.01*mom*_filter_smear_factor);[e+]->SetMom(newmom)");
    l->AddCommand("if (_filter_debug && removed); echo e+: $_x, $_y, $_z eff: $eff_ep <removed>");
    l->AddCommand("if (_filter_debug && !removed); echo e+: $_x, $_y, $_z eff: $eff_ep");
    l->AddCommand("formore e+; goto _start");  // added 2 separate gotos for e+ and e- following a hint by V. Hejny
    l->AddCommand("_start2: removed=0");  
    l->AddCommand("_x = [e-]->P() * 1000.;");
    l->AddCommand("_y = [e-]->CosTheta(); ");
    l->AddCommand("_z = (([e-]->Phi()) *180/TMath::Pi()); if (_z<0); _z = _z + 360;");
    l->AddCommand(eff_elec,"eff_em = Eval(); rnd = sampleFlat(); if (rnd>eff_em); [e-]->SetInActive(); removed=1");
    l->AddCommand("mom = [e-]->P(); newmom = sampleGaus(mom,0.01*mom*_filter_smear_factor);[e-]->SetMom(newmom)");
    l->AddCommand("if (_filter_debug && removed); echo e-: $_x, $_y, $_z eff: $eff_em <removed>");
    l->AddCommand("if (_filter_debug && !removed); echo e-: $_x, $_y, $_z eff: $eff_em");
    l->AddCommand("formore e-; goto _start2");
    l->AddCommand("if (!_filter_exclusive); goto _end;");
    l->AddCommand("_start_proton_loop: removed=0");
    l->AddCommand("_x = [p]->P() * 1000.; ");
    l->AddCommand("_y = [p]->CosTheta(); ");
    l->AddCommand("_z = (([p]->Phi()) *180/TMath::Pi()); if (_z<0); _z = _z + 360;");
    //l->AddCommand("[p]->Print();");
    l->AddCommand(eff_protons,"eff_p = Eval(); rnd = sampleFlat(); if (rnd>eff_p); [p]->SetInActive(); removed=1");
    l->AddCommand("mom = [p]->P(); newmom = sampleGaus(mom,0.01*mom*_filter_smear_factor);[p]->SetMom(newmom)");
    // l->AddCommand("echo $mom , $newmom");
    //l->AddCommand("[p]->Print();");
    l->AddCommand("if (_filter_debug && removed); echo p: $_x, $_y, $_z eff: $eff_p <removed>");
    l->AddCommand("if (_filter_debug && !removed); echo p: $_x, $_y, $_z eff: $eff_p");
    l->AddCommand("formore p; goto _start_proton_loop");
    l->AddCommand("_end:");
    
    l->Write();
    eff_elec->Write();
    eff_protons->Write();
    f->Write();
}