MLP for position reconstruction

I want to reconstruct position of particles passing throught an aerogel detector.

I know whvh pmt was fireing (PMT1,2…12)]

I wanted to build a network like this:

TMultiLayerPerceptron *mlp =
new TMultiLayerPerceptron(“PMT1,PMT2,PMT3,PMT4,PMT2,PMT5,PMT1,PMT6,PMT7,PMT8,PMT9,PMT10,PMT11,PMT12:5:3:X,Y”,

The question is the evaluation.

The TMultiLayerPerceptron has “Evaluate” function but it comes back with one double, while I would need the X and Y information …
Of course I can build 2 NN for X and Y …

Do I understand the problem well?


The prototype for the Evaluate method is:Double_t Evaluate(Int_t index, Double_t* params) const;

The first argument is the index of the output neuron. In your case index=0 will be X and index=1 will be Y.
The second argument is the array of input value, that you must fill with the various PMT readings.



So …
I modified the mlpHiggs in order to do the do position rconstruction.
The code:

----------------------- code -------------------------------

void mlpPosRecon(Int_t ntrain=100) {

if (!gROOT->GetClass(“TMultiLayerPerceptron”)) {

const char *fname = “outfile_1000.root”;
TFile *input = 0;
if (!gSystem->AccessPathName(fname)) {
input = TFile::Open(fname);
if (!input) return;

TTree *training = (TTree *) input->Get(“tree”);
bool PMT0,PMT1,PMT2,PMT3,
int X, Y;
double x, y;

training->SetBranchAddress(“PMT0”, &PMT0);
training->SetBranchAddress(“PMT1”, &PMT1);
training->SetBranchAddress(“PMT2”, &PMT2);

training->SetBranchAddress(“PMT3”, &PMT3);
training->SetBranchAddress(“PMT4”, &PMT4);
training->SetBranchAddress(“PMT5”, &PMT5);

training->SetBranchAddress(“PMT6”, &PMT6);
training->SetBranchAddress(“PMT7”, &PMT7);
training->SetBranchAddress(“PMT8”, &PMT8);

training->SetBranchAddress(“PMT9”, &PMT9);
training->SetBranchAddress(“PMT10”, &PMT10);
training->SetBranchAddress(“PMT11”, &PMT11);

training->SetBranchAddress(“X”, &X);
training->SetBranchAddress(“Y”, &Y);

TMultiLayerPerceptron *mlp = new TMultiLayerPerceptron(“PMT0,PMT1,PMT2,PMT3,PMT4,PMT5,PMT6,PMT7,PMT8,PMT9,PMT10,PMT11:5:3:X,Y”,
mlp->Train(ntrain, “text,graph,update=10”);

//training ends
/* ------- --------- -------- -------- ------- -------- ---------*/

// Use TMLPAnalyzer to see what it looks for
TCanvas* mlpa_canvas = new TCanvas(“mlpa_canvas”,“Network analysis”);
TMLPAnalyzer ana(mlp);
// Initialisation
// output to the console
// shows how each variable influences the network
// shows the network structure


Double_t params[12];
int Xold, Yold;
TH1D* diffx = new TH1D(“diffx”, “diffx”, 320, -16, 16);

TH2D* histx = new TH2D(“histx”, “histx”, 160, 0, 16, 16, 0, 16);
TH2D* histy = new TH2D(“histy”, “histy”, 160, 0, 16, 16, 0, 16);

TH1D* norm = new TH1D(“norm”, “norm”, 10000, 0, 10);
TH2D* norm2 = new TH2D(“norm2”, “norm2”, 10000, 0, 10, 16, 0, 16);

// in order of the simplicity I want to reconstruct the same events with which I trained the network

for (int i = 0; i < training->GetEntries(); i++) {

  params[0] = PMT0;
  params[1] = PMT1;
  params[2] = PMT2;
  params[3] = PMT3;
  params[4] = PMT4;

  params[5] = PMT5;
  params[6] = PMT6;
  params[7] = PMT7;
  params[8] = PMT8;
  params[9] = PMT9;

  params[10] = PMT10;
  params[11] = PMT11;

  diffx->Fill(mlp->Evaluate(0, params)-X);
  histx->Fill(mlp->Evaluate(0, params), X);
  histy->Fill(mlp->Evaluate(1, params), Y);
  if(X != 0){
     norm->Fill(mlp->Evaluate(0, params)/X);
     cout << mlp->Evaluate(0, params) << "; " << X << "; " << mlp->Evaluate(0, params)/X << endl;
     norm2->Fill(mlp->Evaluate(0, params)/X, X);


------------------------------- end of code ---------------------------

The result is strange:
The “input” of both variables X and Y are between 0 and 16. The “output” result of the network is between -8 and 8. This wouldnt be a problem. but there is no correlation between the input and the reconstructed value (at least I cant see any).
I tried to use normailized variables (between 0 and 1), but the result is the same.

Instead of sending you ps files, I sending the tree and the code …

Am I doing something wrong or … ?

Thanx in advance,

PS: The data set is comind from a measurement.
We read out the light from a aerogel detector with 12 pmts placed around the the black-box of the aerogel.
Than we shot the box with charged pion-beam.
Outside the box there was two plastic-strip detector consists 16 strips each (this is the X and Y information), and the data was written out if the aerogel, and the two strip-detectors were in coincidence …
This is not the cleanest data ever (just because of the physical processes …), but it is clean enough to see correlation if we weight the PMT-signals …
outfile_1000.root (45.2 KB)


I looked at the network, and I don’t see anything strange with it.
I ran with 1000 training samples, and I changed the training method, but the result is similar.

Asymptotically, it tends to a network where the output is always 0.5 for X/16 and 0.5 for Y/16… that makes sense for a minimization outcome when no correlation can be exploited.

My impression is that the correlation between the inputs and the output is too small or too chaotic to be handled by the network. Possible solutions would be to pre-digest the inputs or to try with a more complex network… but then you would need more statistics in the rootfile, and it would take more time to try the network (and without any guarantee that it will work).

Thank you very much for your quick answer …

Finally, could you tell me what the [“Entry$%2”,"(Entry$+1)%2"] means in the constructor?
TMultiLayerPerceptron *mlp = new TMultiLayerPerceptron("@msumf,@ptsumf,@acolin:5:3:type",

It comes back every case with 1, 0 or 0 1 … not? But what does it mean?

Tnax again,

It’s an easy way to divide the input in two samples: the training sample and the test sample. Each event is put either in one or the other according to the value of that parameter.

You are free to divide the input differently. Good practice is to have three samples: the training and test samples plus the dataset used after training.
You might also not want to split the sample at all (typically when fitting a function) in which case you can put “1” and “1” so that all entries are put in both samples.

Thank you very much for your help …