Index: trunk/examples/advanced/hadrontherapy/src/HadrontherapyMatrix.cc
===================================================================
--- trunk/examples/advanced/hadrontherapy/src/HadrontherapyMatrix.cc	(revision 1230)
+++ trunk/examples/advanced/hadrontherapy/src/HadrontherapyMatrix.cc	(revision 1313)
@@ -1,144 +1,404 @@
-//
-// ********************************************************************
-// * License and Disclaimer                                           *
-// *                                                                  *
-// * The  Geant4 software  is  copyright of the Copyright Holders  of *
-// * the Geant4 Collaboration.  It is provided  under  the terms  and *
-// * conditions of the Geant4 Software License,  included in the file *
-// * LICENSE and available at  http://cern.ch/geant4/license .  These *
-// * include a list of copyright holders.                             *
-// *                                                                  *
-// * Neither the authors of this software system, nor their employing *
-// * institutes,nor the agencies providing financial support for this *
-// * work  make  any representation or  warranty, express or implied, *
-// * regarding  this  software system or assume any liability for its *
-// * use.  Please see the license in the file  LICENSE  and URL above *
-// * for the full disclaimer and the limitation of liability.         *
-// *                                                                  *
-// * This  code  implementation is the result of  the  scientific and *
-// * technical work of the GEANT4 collaboration.                      *
-// * By using,  copying,  modifying or  distributing the software (or *
-// * any work based  on the software)  you  agree  to acknowledge its *
-// * use  in  resulting  scientific  publications,  and indicate your *
-// * acceptance of all terms of the Geant4 Software license.          *
-// ********************************************************************
-//
-// $Id: HadrontherapyMatrix.cc;
-// See more at: http://g4advancedexamples.lngs.infn.it/Examples/hadrontherapy//
+	//
+	// ********************************************************************
+	// * License and Disclaimer                                           *
+	// *                                                                  *
+	// * The  Geant4 software  is  copyright of the Copyright Holders  of *
+	// * the Geant4 Collaboration.  It is provided  under  the terms  and *
+	// * conditions of the Geant4 Software License,  included in the file*
+	// * LICENSE and available at  http://cern.ch/geant4/license .  These *
+	// * include a list of copyright holders.                             *
+	// *                                                                  *
+	// * Neither the authors of this software system, nor their employing *
+	// * institutes,nor the agencies providing financial support for this *
+	// * work  make  any representation or  warranty, express or implied, *
+	// * regarding  this  software system or assume any liability for its *
+	// * use.  Please see the license in the file  LICENSE  and URL above *
+	// * for the full disclaimer and the limitation of liability.         *
+	// *                                                                  *
+	// * This  code  implementation is the result of  the  scientific and *
+	// * technical work of the GEANT4 collaboration.                      *
+	// * By using,  copying,  modifying or  distributing the software (or *
+	// * any work based  on the software)  you  agree  to acknowledge its *
+	// * use  in  resulting  scientific  publications,  and indicate your *
+	// * acceptance of all terms of the Geant4 Software license.          *
+	// ********************************************************************
+	//
+	// $Id: HadrontherapyMatrix.cc;
+	// See more at: http://g4advancedexamples.lngs.infn.it/Examples/hadrontherapy//
 
 #include "HadrontherapyMatrix.hh"
 #include "HadrontherapyAnalysisManager.hh"
+#include "G4RunManager.hh"
+#include "HadrontherapyPrimaryGeneratorAction.hh"
+#include "G4ParticleGun.hh"
+
+#include <fstream>
+#include <unistd.h>
+#include <iostream>
+#include <sstream>
+#include <iomanip>
 #include "globals.hh"
-#include <fstream>
-
+
+// Units definition: CLHEP/Units/SystemOfUnits.h
+//
 HadrontherapyMatrix* HadrontherapyMatrix::instance = NULL;
-// Static method that only return a pointer to the matrix object
-HadrontherapyMatrix* HadrontherapyMatrix::getInstance() 
-{
-  return instance;
-}
-// This STATIC method delete (!) the old matrix and rewrite a new object returning a pointer to it
-HadrontherapyMatrix* HadrontherapyMatrix::getInstance(G4int voxelX, G4int voxelY, G4int voxelZ)  
-{
-    if (instance) delete instance;
-    instance = new HadrontherapyMatrix(voxelX, voxelY, voxelZ);
-    instance -> Initialize(); 	
-    return instance;
-}
-
-HadrontherapyMatrix::HadrontherapyMatrix(G4int voxelX, G4int voxelY, G4int voxelZ):
-    matrix(0)
+G4bool HadrontherapyMatrix::secondaries = false;
+	// Only return a pointer to matrix
+HadrontherapyMatrix* HadrontherapyMatrix::GetInstance() 
+{
+	return instance;
+}
+	// This STATIC method delete (!) the old matrix and rewrite a new object returning a pointer to it
+	// TODO A check on the parameters is required!
+HadrontherapyMatrix* HadrontherapyMatrix::GetInstance(G4int voxelX, G4int voxelY, G4int voxelZ, G4double mass)  
+{
+	if (instance) delete instance;
+	instance = new HadrontherapyMatrix(voxelX, voxelY, voxelZ, mass);
+	instance -> Initialize();// XXX
+	return instance;
+}
+HadrontherapyMatrix::HadrontherapyMatrix(G4int voxelX, G4int voxelY, G4int voxelZ, G4double mass):
+    filename("Dose.out"),
+    doseUnit(MeV/g)
 {  
-// Number of the voxels of the phantom
-// For Y = Z = 1 the phantom is divided in slices (and not in voxels)
-// orthogonal to the beam axis
-  numberVoxelX = voxelX;
-  numberVoxelY = voxelY;
-  numberVoxelZ = voxelZ; 
-  // Create the dose matrix
-  matrix = new G4double[numberVoxelX*numberVoxelY*numberVoxelZ];
-  if (matrix) G4cout << "Matrix: Memory space to store physical dose into " <<  
-                        numberVoxelX*numberVoxelY*numberVoxelZ <<
-		        " voxels has been allocated " << G4endl;
-  else G4Exception("Can't allocate memory to store physical dose!");
-}
-
+	// Number of the voxels of the phantom
+	// For Y = Z = 1 the phantom is divided in slices (and not in voxels)
+	// orthogonal to the beam axis
+	numberOfVoxelAlongX = voxelX;
+	numberOfVoxelAlongY = voxelY;
+	numberOfVoxelAlongZ = voxelZ; 
+	massOfVoxel = mass;
+	// Create the dose matrix
+	matrix = new G4double[numberOfVoxelAlongX*numberOfVoxelAlongY*numberOfVoxelAlongZ];
+	if (matrix)
+	{
+		G4cout << "HadrontherapyMatrix: Memory space to store physical dose into " <<  
+		numberOfVoxelAlongX*numberOfVoxelAlongY*numberOfVoxelAlongZ <<
+		" voxels has been allocated " << G4endl;
+	}
+	else G4Exception(" HadrontherapyMatrix::HadrontherapyMatrix. Can't allocate memory to store physical dose!");
+		// Hit voxel (TrackID) marker
+		// This array mark the status of voxel, if a hit occur, with the trackID of the particle
+		// Must be initialized
+	hitTrack = new G4int[numberOfVoxelAlongX*numberOfVoxelAlongY*numberOfVoxelAlongZ];
+	ClearHitTrack();
+}
+
+/////////////////////////////////////////////////////////////////////////////
 HadrontherapyMatrix::~HadrontherapyMatrix()
 {
     delete[] matrix;
-}
-
-void HadrontherapyMatrix::flush()
-{
-	if(matrix)
-	for(int i=0; i<numberVoxelX*numberVoxelY*numberVoxelZ; i++)
-	{
-	  matrix[i] = 0;
-	}
-}
+    delete[] hitTrack;
+		// clear fluences/dose data
+    Clear();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+void HadrontherapyMatrix::Clear()
+{
+    for (size_t i=0; i<ionStore.size(); i++)
+    {
+	delete[] ionStore[i].dose; 
+	delete[] ionStore[i].fluence; 
+    }
+    ionStore.clear();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Initialise the elements of the matrix to zero
 void HadrontherapyMatrix::Initialize()
 { 
-// Initialise the elements of the matrix to zero
-  for(G4int i = 0; i < numberVoxelX; i++)
-    {
-      for(G4int j = 0; j < numberVoxelY; j++)
-	   {
-	      for(G4int k = 0; k < numberVoxelZ; k++)
-
-	      matrix[Index(i,j,k)] = 0.;
-	   } 
-    }
-}
+    Clear();
+    for(int i=0;i<numberOfVoxelAlongX*numberOfVoxelAlongY*numberOfVoxelAlongZ;i++)
+    {
+		matrix[i] = 0;
+    }
+}
+	/////////////////////////////////////////////////////////////////////////////
+	/////////////////////////////////////////////////////////////////////////////
+	// Print generated nuclides list
+void HadrontherapyMatrix::PrintNuclides()
+{
+    for (size_t i=0; i<ionStore.size(); i++)
+    {
+		G4cout << ionStore[i].name << G4endl;
+    }
+}
+	/////////////////////////////////////////////////////////////////////////////
+	// Clear Hit voxel (TrackID) markers
+void HadrontherapyMatrix::ClearHitTrack()
+{
+	for(G4int i=0; i<numberOfVoxelAlongX*numberOfVoxelAlongY*numberOfVoxelAlongZ; i++) hitTrack[i] = 0;
+}
+	// Return Hit status
+G4int* HadrontherapyMatrix::GetHitTrack(G4int i, G4int j, G4int k)
+{
+	return &(hitTrack[Index(i,j,k)]);
+}
+/////////////////////////////////////////////////////////////////////////////
+// Dose methods...
+// Fill DOSE/fluence matrix for particle/ion: 
+// If fluence parameter is true (default value is FALSE) then fluence at voxel (i, j, k) is increased. 
+// The energyDeposit parameter fill the dose matrix for voxel (i,j,k) 
+/////////////////////////////////////////////////////////////////////////////
+
+G4bool HadrontherapyMatrix::Fill(G4int trackID,
+				 G4ParticleDefinition* particleDef,
+				 G4int i, G4int j, G4int k, 
+				 G4double energyDeposit,
+				 G4bool fluence) 
+{
+    if (energyDeposit <=0. && !fluence || !secondaries) return false;
+    // Get Particle Data Group particle ID 
+    G4int PDGencoding = particleDef -> GetPDGEncoding();
+    PDGencoding -= PDGencoding%10;
+	
+    // Search for already allocated data...
+    for (size_t l=0; l < ionStore.size(); l++)
+    {
+		if (ionStore[l].PDGencoding == PDGencoding ) 
+		{   // Is it a primary or a secondary particle? 
+			if ( trackID ==1 && ionStore[l].isPrimary || trackID !=1 && !ionStore[l].isPrimary)
+			{
+				if (energyDeposit > 0.) ionStore[l].dose[Index(i, j, k)] += energyDeposit/massOfVoxel;
+				
+					// Fill a matrix per each ion with the fluence
+				if (fluence) ionStore[l].fluence[Index(i, j, k)]++;
+				return true;
+			}
+		}
+    }
+	
+    G4int Z = particleDef-> GetAtomicNumber();
+    G4int A = particleDef-> GetAtomicMass();
+
+    G4String fullName = particleDef -> GetParticleName();
+    G4String name = fullName.substr (0, fullName.find("[") ); // cut excitation energy  
+  // Let's put a new particle in our store...
+    ion newIon = 
+    {
+		(trackID == 1) ? true:false,
+		PDGencoding,
+		name,
+		name.length(), 
+		Z, 
+		A, 
+		new G4double[numberOfVoxelAlongX * numberOfVoxelAlongY * numberOfVoxelAlongZ],
+		new unsigned int[numberOfVoxelAlongX * numberOfVoxelAlongY * numberOfVoxelAlongZ]
+    }; 
+		// Initialize data
+    if (newIon.dose && newIon.fluence)
+    {
+		for(G4int m=0; m<numberOfVoxelAlongX*numberOfVoxelAlongY*numberOfVoxelAlongZ; m++)
+		{
+			newIon.dose[m] = 0.;
+			newIon.fluence[m] = 0;
+		}
+		if (energyDeposit > 0.) newIon.dose[Index(i, j, k)] += energyDeposit/massOfVoxel;
+		if (fluence) newIon.fluence[Index(i, j, k)]++;
+		
+		ionStore.push_back(newIon);
+		
+		// TODO Put some verbosity check
+		/*
+		 G4cout << "Memory space to store the DOSE/FLUENCE into " <<  
+		 numberOfVoxelAlongX*numberOfVoxelAlongY*numberOfVoxelAlongZ << 
+		 " voxels has been allocated for the nuclide " << newIon.name << 
+		 " (Z = " << Z << ", A = " << A << ")" << G4endl ;
+		 */
+		return true;
+    }
+    else // XXX Out of memory! XXX
+    {
+		return false;
+    }
+	
+}
+	
+	/////////////////////////////////////////////////////////////////////////////
+	/////////////////////////////////////////////////////////////////////////////
+	// Methods to store data to filenames...
+	////////////////////////////////////////////////////////////////////////////
+	////////////////////////////////////////////////////////////////////////////
+	//
+	// General method to store matrix data to filename
+void HadrontherapyMatrix::StoreMatrix(G4String file, void* data, size_t psize)
+{
+    if (data)
+    {
+		ofs.open(file, std::ios::out);
+		if (ofs.is_open())
+		{
+			for(G4int i = 0; i < numberOfVoxelAlongX; i++) 
+				for(G4int j = 0; j < numberOfVoxelAlongY; j++) 
+					for(G4int k = 0; k < numberOfVoxelAlongZ; k++) 
+					{
+						G4int n = Index(i, j, k);
+							// Check for data type: u_int, G4double, XXX 
+						if (psize == sizeof(unsigned int))
+						{
+							unsigned int* pdata = (unsigned int*)data;
+							if (pdata[n]) ofs << i << '\t' << j << '\t' <<
+								k << '\t' << pdata[n] << G4endl;
+						}
+						else if (psize == sizeof(G4double))
+						{
+							G4double* pdata = (G4double*)data;
+							if (pdata[n]) ofs << i << '\t' << j << '\t' <<
+								k << '\t' << pdata[n] << G4endl;
+						}
+					}
+			ofs.close();
+		}
+    }
+}
+
+	// Store fluence per single ion in multiple files
+void HadrontherapyMatrix::StoreFluenceData()
+{
+    for (size_t i=0; i < ionStore.size(); i++){
+		StoreMatrix(ionStore[i].name + "_Fluence.out", ionStore[i].fluence, sizeof(unsigned int));
+    }
+}
+	// Store dose per single ion in multiple files
+void HadrontherapyMatrix::StoreDoseData()
+{
+	
+    for (size_t i=0; i < ionStore.size(); i++){
+		StoreMatrix(ionStore[i].name + "_Dose.out", ionStore[i].dose, sizeof(G4double));
+    }
+}
+	/////////////////////////////////////////////////////////////////////////
+	// Store dose for all ions into a single file and into ntuples.
+	// Please note that this function is called via messenger commands
+	// defined in the HadrontherapyAnalysisFileMessenger.cc class file
+void HadrontherapyMatrix::StoreDoseFluenceAscii()
+{
+    // Sort like periodic table
+    std::sort(ionStore.begin(), ionStore.end());
+#define width 15L
+    ofs.open(filename, std::ios::out);
+    if (ofs.is_open())
+    {
+
+	//
+	// Write the voxels index and the list of particles/ions 
+	ofs << std::setprecision(6) << std::left <<
+	    "i\tj\tk\t"; 
+/*	    
+	    G4RunManager *runManager = G4RunManager::GetRunManager();
+	    HadrontherapyPrimaryGeneratorAction *pPGA = (HadrontherapyPrimaryGeneratorAction*)runManager -> GetUserPrimaryGeneratorAction();
+	    G4String name = pPGA -> GetParticleGun() -> GetParticleDefinition() -> GetParticleName();
+*/         
+	// Total dose 
+	ofs << std::setw(width) << "Dose";
+
+	for (size_t l=0; l < ionStore.size(); l++)
+	{
+	    G4String a = (ionStore[l].isPrimary) ? "_1":""; // is it a primary?
+	    ofs << std::setw(width) << ionStore[l].name + a <<
+		std::setw(width) << ionStore[l].name  + a;
+	}
+	ofs << G4endl;
+
+/*
+	// PDGencoding
+	ofs << std::setprecision(6) << std::left <<
+	"0\t0\t0\t"; 
+
+	// Total dose 
+	ofs << std::setw(width) << '0';
+	for (size_t l=0; l < ionStore.size(); l++)
+	{
+	ofs << std::setw(width) << ionStore[l].PDGencoding  <<
+	std::setw(width) << ionStore[l].PDGencoding;
+	}
+	ofs << G4endl;
+*/
+	// Write data
+	for(G4int i = 0; i < numberOfVoxelAlongX; i++) 
+	    for(G4int j = 0; j < numberOfVoxelAlongY; j++) 
+		for(G4int k = 0; k < numberOfVoxelAlongZ; k++) 
+		{
+		    G4int n = Index(i, j, k);
+		    // Write only not identically null data lines
+		    if (matrix[n])
+		    {
+			ofs << G4endl;
+			ofs << i << '\t' << j << '\t' << k << '\t';
+			// Total dose 
+			ofs << std::setw(width) << matrix[n]/(doseUnit); 
+			{
+			    for (size_t l=0; l < ionStore.size(); l++)
+			    {
+				// Fill ASCII file rows
+				ofs << std::setw(width) << ionStore[l].dose[n]/(doseUnit) <<
+				    std::setw(width) << ionStore[l].fluence[n]; 
+			    }
+			}
+		    }
+		}
+	ofs.close();
+    }
+}
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef G4ANALYSIS_USE_ROOT
+void HadrontherapyMatrix::StoreDoseFluenceRoot()
+{
+    HadrontherapyAnalysisManager* analysis = HadrontherapyAnalysisManager::GetInstance();
+    for(G4int i = 0; i < numberOfVoxelAlongX; i++) 
+	for(G4int j = 0; j < numberOfVoxelAlongY; j++) 
+	    for(G4int k = 0; k < numberOfVoxelAlongZ; k++) 
+	    {
+		G4int n = Index(i, j, k);
+		for (size_t l=0; l < ionStore.size(); l++)
+
+		{
+		    // Do the same work for .root file: fill dose/fluence ntuple  
+		    analysis -> FillVoxelFragmentTuple( i, j, k, 
+							ionStore[l].A, 
+							ionStore[l].Z, 
+							ionStore[l].dose[n]/(doseUnit), 
+							ionStore[l].fluence[n] );
+
+
+		}
+	    }
+}
+#endif
 
 void HadrontherapyMatrix::Fill(G4int i, G4int j, G4int k, 
 			       G4double energyDeposit)
 {
-  if (matrix)
-    matrix[Index(i,j,k)] += energyDeposit;
-  
-  // Store the energy deposit in the matrix element corresponding 
-  // to the phantom voxel  i, j, k
-}
-
+    if (matrix)
+		matrix[Index(i,j,k)] += energyDeposit;
+	
+    // Store the energy deposit in the matrix element corresponding 
+    // to the phantom voxel  
+}
 void HadrontherapyMatrix::TotalEnergyDeposit()
 {
+  // Convert energy deposited to dose.
   // Store the information of the matrix in a ntuple and in 
   // a 1D Histogram
 
-  G4int k;
-  G4int j;
-  G4int i;
-  
-  if (matrix)
+#ifdef G4ANALYSIS_USE_ROOT
+    HadrontherapyAnalysisManager* analysis = HadrontherapyAnalysisManager::GetInstance();
+#endif
+    if (matrix)
     {  
-      std::ofstream ofs;    	
-      ofs.open("DoseDistribution.out"); 
-      
-      for(G4int l = 0; l < numberVoxelZ; l++) 
-	{
-	  k = l;
-	  
-	  for(G4int m = 0; m < numberVoxelY; m++) 
-	    { 
-	      j = m * numberVoxelZ + k; 
-		
-		for(G4int n = 0; n <  numberVoxelX; n++)
-		  {
-		    i =  n* numberVoxelZ * numberVoxelY + j;
-		    if(matrix[i] != 0)
-		      {	
-			ofs << n << '\t' << m << '\t' <<
-			  k << '\t' << matrix[i] << G4endl;
-		       	
-#ifdef ANALYSIS_USE
-			HadrontherapyAnalysisManager* analysis = 
-			HadrontherapyAnalysisManager::getInstance();
-			analysis -> FillEnergyDeposit(n, m, k, matrix[i]);
-			analysis -> BraggPeak(n, matrix[i]);
+	for(G4int i = 0; i < numberOfVoxelAlongX; i++) 
+	    for(G4int j = 0; j < numberOfVoxelAlongY; j++) 
+		for(G4int k = 0; k < numberOfVoxelAlongZ; k++)
+		{
+		    G4int n = Index(i,j,k);
+	            matrix[n] = matrix[n] / massOfVoxel;
+#ifdef G4ANALYSIS_USE_ROOT
+		    analysis -> FillEnergyDeposit(i, j, k, matrix[n]/doseUnit);
+		    analysis -> BraggPeak(i, matrix[n]/doseUnit);
 #endif
-		      }
-}       
-	      }
-	  }
-    }
-}
+		}
+    }
+}
+
