/////////////////////////////////////////////////////////////////////
//
// Generic distribution to change any kind of distribution 
// by using the batch script language to define equations
//
// This is a rejection method. It works as an afterburner
// for the normal distribution(s).
//
// Usage:
// 1.) Define a template, e.g.:
// PAnyDistribution* decay = 
//        new PAnyDistribution("name","description");
// decay->Add("....,     parent");
// decay->Add("....,     daughter");
//             .....
// 2.) If a non-uniform distribution should be defined (otherwise go to step 4),
// one has to add a "cache" which stores the undistorted
// distribution. The result is calculated by comparing
// the undistorted cache (as filled in 3) with the equation in step 4
// The size and binning of the cache must
// be chosen such, that during runtime (or even better: during Preheating) the statistic
// is sufficiently filled
// TH1F * cache  = new TH1F ("cache","......",...);
// (2- or 3-dim histograms are possible as well - if one has enough time!) 
//
// 3.) Add the equation to fill the cache:
// decay->AddEquation(cache,"_x = ...(calculate something here)...;");
// Here it is important to know that the daughters are in 
// their rest frame (i.e. the parent).
// But the parent itself is in lab frame.
// The parent is indicated by "_parent"
// Moreover, all particles of the decay (daughters and parent)
// can be accessed via the usual '[parname]' identifier.
// N.B.: "x,y,z,t" are reserved in TFormula, do NOT use such variable names.
//
// 4.) Add the usual equation:
// The distribution (the probability function)
// must be stored in "_f"
// decay->AddEquation("_f = ...(calculate something here)...");
//
// 5.) Remember, AnyDistribution is a rejection method. Therefore
// it can happen, that parts of the phase space, where _f has a 
// large probability, is not well populated by the generated events.
// In this case, the event loop will run forever, as Pluto tries
// to match the shape defined by _f.
// The following factor is the maximum enhancement factor to avoid such
// deadlocks.
// N.B.: It directly scales with the computing time!!!
// decay->SetMaxEnhancementFactor(10);
//
// 6.) Add this model to the Pluto data base:
// makeDistributionManager()->Add(decay);
// 
// An example can be found in macros/demo_PAnyDistribution.C
//
//                                  Author:  I. Froehlich
/////////////////////////////////////////////////////////////////////


using namespace std;
#include <sstream>
#include <iostream>
#include <iomanip>

#include "PAnyDistribution.h"
#include "PDynamicData.h"

ClassImp(PAnyDistribution)

PAnyDistribution::PAnyDistribution() {
    Fatal("PAnyDistribution", "Wrong ctor called");
};

PAnyDistribution::PAnyDistribution(const Char_t *id, const Char_t *de) :
    PDistribution(id, de) {

    parent    = NULL;
    projector = NULL;
    cache1    = NULL;
    cache2    = NULL;
    cache3    = NULL;
    max = 0;
    max_enhance_factor = 10;

    daughter_pos = 0;
    for (int i=0; i<ANY_DISTRIBUTION_MAX_DAUGHTERS; i++) {
        daughters[i] = NULL;
    }
};

PDistribution *PAnyDistribution::Clone(const char *) const {
    return new PAnyDistribution((const PAnyDistribution &)* this);
};

void PAnyDistribution::MakeVars() {
    if (!projector) projector = new PProjector();

    vparent   = makeDynamicData()->GetBatchParticle("_parent");  
    vf        = makeStaticData()->GetBatchValue("_f"); 

    x = makeStaticData()->GetBatchValue("_x"); 
    y = makeStaticData()->GetBatchValue("_y"); 
    z = makeStaticData()->GetBatchValue("_z"); 
};

Bool_t PAnyDistribution::AddEquation(const char *command) {
    MakeVars();
    return projector->AddCommand(command);
};

Bool_t PAnyDistribution::AddEquation(TH1 *histo, const char *command) {
    MakeVars();
    cache1 = histo;
    return projector->AddHistogram(histo, command, 2);
};

Bool_t PAnyDistribution::AddEquation(TH2 *histo, const char *command) {
    MakeVars();
    cache2 = histo;
    return projector->AddHistogram(histo, command, 2);
};

Bool_t PAnyDistribution::AddEquation(TH3 *histo, const char *command) {
    MakeVars();
    cache3 = histo;
    return projector->AddHistogram(histo, command, 2);
};

// Bool_t PAnyDistribution::AddHistogram(TH2 * histo, const char * command) {
//     MakeVars();
//     return  projector->AddHistogram(histo,command,0);
// };


Bool_t PAnyDistribution::Init(void) {

    daughter_pos = 0; //clear stuff because the Attach function makes a clone

    //get the parent
    for (int i=0; i<position; i++) {
	if (particle_flag[i] == PARTICLE_LIST_PARENT)
	    parent = particle[i];
    }
    if (!parent) {
	Warning("Init", "Parent not found");
	return kFALSE;
    }
    
    //Now get all daughters
    for (int i=0; i<ANY_DISTRIBUTION_MAX_DAUGHTERS; i++) {
        daughters[i] = GetParticle("daughter");
        if (daughters[i]) {         
            daughter_pos++;
        }
    }
 
    return kTRUE;    
};

Bool_t PAnyDistribution::Prepare(void) {
    return kTRUE;
};

Bool_t PAnyDistribution::Finalize(void) {
    return kTRUE;
};

Bool_t PAnyDistribution::CheckAbort(void) {
    return kFALSE;
};

Bool_t PAnyDistribution::IsNotRejected(void) {

    double factor = 1.;

    if (projector) {	

	*vparent = parent;
	//vparent->Boost(-parent->BoostVector()); 

	stack[0] = vparent;
	for (int i=0; i<ANY_DISTRIBUTION_MAX_DAUGHTERS; i++) {
	    stack[i+1] = daughters[i];
	}
	//projector->Execute();
	Int_t num = daughter_pos + 1;
	projector->Modify((PParticle **)&stack,(int *)&decay_done, &num, 
			  ANY_DISTRIBUTION_MAX_DAUGHTERS);
	factor = *vf;
    } else {
	Fatal("IsNotRejected", "No equation set");
    }
    
    Double_t myres = 0.;
    if (cache1) {
	int bin = cache1->FindBin(*x);
	myres = cache1->GetBinContent(bin);
	//dw= hist3D->GetBinError(bin);
	if (cache1->GetEntries()) myres /= cache1->GetEntries();
	myres *= cache1-> GetNbinsX();
    } else if (cache2) {
	int bin = cache2->FindBin(*x, *y);
	myres = cache2->GetBinContent(bin);
	if (cache2->GetEntries()) myres /= cache2->GetEntries();
	myres *= cache1-> GetNbinsX() * cache1->GetNbinsY();
    } else if (cache3) {
	int bin = cache3->FindBin(*x,*y,*z);
	myres = cache3->GetBinContent(bin);
	if (cache3->GetEntries()) myres /= cache3->GetEntries();
    } 
    
    Double_t reduction_factor = 1.;
    if (myres) {
	reduction_factor /= myres;
    }

    if (reduction_factor > max_enhance_factor) reduction_factor = max_enhance_factor;

    factor *= reduction_factor;

    if (factor>max) {
	max = factor * 1.1;
	Warning("IsNotRejected", "Factor > max, increased (%f)",max);
    }
 
    if ((factor/max) > PUtils::sampleFlat()) return kTRUE; // sample now 
    
    return kFALSE;
};


 PAnyDistribution.cc:1
 PAnyDistribution.cc:2
 PAnyDistribution.cc:3
 PAnyDistribution.cc:4
 PAnyDistribution.cc:5
 PAnyDistribution.cc:6
 PAnyDistribution.cc:7
 PAnyDistribution.cc:8
 PAnyDistribution.cc:9
 PAnyDistribution.cc:10
 PAnyDistribution.cc:11
 PAnyDistribution.cc:12
 PAnyDistribution.cc:13
 PAnyDistribution.cc:14
 PAnyDistribution.cc:15
 PAnyDistribution.cc:16
 PAnyDistribution.cc:17
 PAnyDistribution.cc:18
 PAnyDistribution.cc:19
 PAnyDistribution.cc:20
 PAnyDistribution.cc:21
 PAnyDistribution.cc:22
 PAnyDistribution.cc:23
 PAnyDistribution.cc:24
 PAnyDistribution.cc:25
 PAnyDistribution.cc:26
 PAnyDistribution.cc:27
 PAnyDistribution.cc:28
 PAnyDistribution.cc:29
 PAnyDistribution.cc:30
 PAnyDistribution.cc:31
 PAnyDistribution.cc:32
 PAnyDistribution.cc:33
 PAnyDistribution.cc:34
 PAnyDistribution.cc:35
 PAnyDistribution.cc:36
 PAnyDistribution.cc:37
 PAnyDistribution.cc:38
 PAnyDistribution.cc:39
 PAnyDistribution.cc:40
 PAnyDistribution.cc:41
 PAnyDistribution.cc:42
 PAnyDistribution.cc:43
 PAnyDistribution.cc:44
 PAnyDistribution.cc:45
 PAnyDistribution.cc:46
 PAnyDistribution.cc:47
 PAnyDistribution.cc:48
 PAnyDistribution.cc:49
 PAnyDistribution.cc:50
 PAnyDistribution.cc:51
 PAnyDistribution.cc:52
 PAnyDistribution.cc:53
 PAnyDistribution.cc:54
 PAnyDistribution.cc:55
 PAnyDistribution.cc:56
 PAnyDistribution.cc:57
 PAnyDistribution.cc:58
 PAnyDistribution.cc:59
 PAnyDistribution.cc:60
 PAnyDistribution.cc:61
 PAnyDistribution.cc:62
 PAnyDistribution.cc:63
 PAnyDistribution.cc:64
 PAnyDistribution.cc:65
 PAnyDistribution.cc:66
 PAnyDistribution.cc:67
 PAnyDistribution.cc:68
 PAnyDistribution.cc:69
 PAnyDistribution.cc:70
 PAnyDistribution.cc:71
 PAnyDistribution.cc:72
 PAnyDistribution.cc:73
 PAnyDistribution.cc:74
 PAnyDistribution.cc:75
 PAnyDistribution.cc:76
 PAnyDistribution.cc:77
 PAnyDistribution.cc:78
 PAnyDistribution.cc:79
 PAnyDistribution.cc:80
 PAnyDistribution.cc:81
 PAnyDistribution.cc:82
 PAnyDistribution.cc:83
 PAnyDistribution.cc:84
 PAnyDistribution.cc:85
 PAnyDistribution.cc:86
 PAnyDistribution.cc:87
 PAnyDistribution.cc:88
 PAnyDistribution.cc:89
 PAnyDistribution.cc:90
 PAnyDistribution.cc:91
 PAnyDistribution.cc:92
 PAnyDistribution.cc:93
 PAnyDistribution.cc:94
 PAnyDistribution.cc:95
 PAnyDistribution.cc:96
 PAnyDistribution.cc:97
 PAnyDistribution.cc:98
 PAnyDistribution.cc:99
 PAnyDistribution.cc:100
 PAnyDistribution.cc:101
 PAnyDistribution.cc:102
 PAnyDistribution.cc:103
 PAnyDistribution.cc:104
 PAnyDistribution.cc:105
 PAnyDistribution.cc:106
 PAnyDistribution.cc:107
 PAnyDistribution.cc:108
 PAnyDistribution.cc:109
 PAnyDistribution.cc:110
 PAnyDistribution.cc:111
 PAnyDistribution.cc:112
 PAnyDistribution.cc:113
 PAnyDistribution.cc:114
 PAnyDistribution.cc:115
 PAnyDistribution.cc:116
 PAnyDistribution.cc:117
 PAnyDistribution.cc:118
 PAnyDistribution.cc:119
 PAnyDistribution.cc:120
 PAnyDistribution.cc:121
 PAnyDistribution.cc:122
 PAnyDistribution.cc:123
 PAnyDistribution.cc:124
 PAnyDistribution.cc:125
 PAnyDistribution.cc:126
 PAnyDistribution.cc:127
 PAnyDistribution.cc:128
 PAnyDistribution.cc:129
 PAnyDistribution.cc:130
 PAnyDistribution.cc:131
 PAnyDistribution.cc:132
 PAnyDistribution.cc:133
 PAnyDistribution.cc:134
 PAnyDistribution.cc:135
 PAnyDistribution.cc:136
 PAnyDistribution.cc:137
 PAnyDistribution.cc:138
 PAnyDistribution.cc:139
 PAnyDistribution.cc:140
 PAnyDistribution.cc:141
 PAnyDistribution.cc:142
 PAnyDistribution.cc:143
 PAnyDistribution.cc:144
 PAnyDistribution.cc:145
 PAnyDistribution.cc:146
 PAnyDistribution.cc:147
 PAnyDistribution.cc:148
 PAnyDistribution.cc:149
 PAnyDistribution.cc:150
 PAnyDistribution.cc:151
 PAnyDistribution.cc:152
 PAnyDistribution.cc:153
 PAnyDistribution.cc:154
 PAnyDistribution.cc:155
 PAnyDistribution.cc:156
 PAnyDistribution.cc:157
 PAnyDistribution.cc:158
 PAnyDistribution.cc:159
 PAnyDistribution.cc:160
 PAnyDistribution.cc:161
 PAnyDistribution.cc:162
 PAnyDistribution.cc:163
 PAnyDistribution.cc:164
 PAnyDistribution.cc:165
 PAnyDistribution.cc:166
 PAnyDistribution.cc:167
 PAnyDistribution.cc:168
 PAnyDistribution.cc:169
 PAnyDistribution.cc:170
 PAnyDistribution.cc:171
 PAnyDistribution.cc:172
 PAnyDistribution.cc:173
 PAnyDistribution.cc:174
 PAnyDistribution.cc:175
 PAnyDistribution.cc:176
 PAnyDistribution.cc:177
 PAnyDistribution.cc:178
 PAnyDistribution.cc:179
 PAnyDistribution.cc:180
 PAnyDistribution.cc:181
 PAnyDistribution.cc:182
 PAnyDistribution.cc:183
 PAnyDistribution.cc:184
 PAnyDistribution.cc:185
 PAnyDistribution.cc:186
 PAnyDistribution.cc:187
 PAnyDistribution.cc:188
 PAnyDistribution.cc:189
 PAnyDistribution.cc:190
 PAnyDistribution.cc:191
 PAnyDistribution.cc:192
 PAnyDistribution.cc:193
 PAnyDistribution.cc:194
 PAnyDistribution.cc:195
 PAnyDistribution.cc:196
 PAnyDistribution.cc:197
 PAnyDistribution.cc:198
 PAnyDistribution.cc:199
 PAnyDistribution.cc:200
 PAnyDistribution.cc:201
 PAnyDistribution.cc:202
 PAnyDistribution.cc:203
 PAnyDistribution.cc:204
 PAnyDistribution.cc:205
 PAnyDistribution.cc:206
 PAnyDistribution.cc:207
 PAnyDistribution.cc:208
 PAnyDistribution.cc:209
 PAnyDistribution.cc:210
 PAnyDistribution.cc:211
 PAnyDistribution.cc:212
 PAnyDistribution.cc:213
 PAnyDistribution.cc:214
 PAnyDistribution.cc:215
 PAnyDistribution.cc:216
 PAnyDistribution.cc:217
 PAnyDistribution.cc:218
 PAnyDistribution.cc:219
 PAnyDistribution.cc:220
 PAnyDistribution.cc:221
 PAnyDistribution.cc:222
 PAnyDistribution.cc:223
 PAnyDistribution.cc:224
 PAnyDistribution.cc:225
 PAnyDistribution.cc:226
 PAnyDistribution.cc:227
 PAnyDistribution.cc:228
 PAnyDistribution.cc:229
 PAnyDistribution.cc:230
 PAnyDistribution.cc:231