laura is hosted by Hepforge, IPPP Durham
Laura++  v3r3
A maximum likelihood fitting package for performing Dalitz-plot analysis.
LauSimFitSlave.cc
Go to the documentation of this file.
1 
2 // Copyright University of Warwick 2013 - 2015.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 // Authors:
7 // Thomas Latham
8 // John Back
9 // Paul Harrison
10 
15 #include <cstdlib>
16 #include <iostream>
17 
18 #include "TMatrixD.h"
19 #include "TMessage.h"
20 #include "TObjArray.h"
21 #include "TObjString.h"
22 #include "TSocket.h"
23 #include "TSystem.h"
24 
25 #include "LauSimFitSlave.hh"
26 #include "LauFitNtuple.hh"
27 
28 
30 
31 
33  sMaster_(0),
34  messageFromMaster_(0),
35  slaveId_(0),
36  nSlaves_(0),
37  parValues_(0),
38  fitNtuple_(0)
39 {
40 }
41 
43 {
44  delete sMaster_;
45  delete messageFromMaster_;
46  delete[] parValues_;
47  delete fitNtuple_;
48 }
49 
50 void LauSimFitSlave::runSlave(const TString& dataFileName, const TString& dataTreeName,
51  const TString& histFileName, const TString& tableFileName,
52  const TString& addressMaster, const UInt_t portMaster)
53 {
54  // Establish the connection to the master process
55  this->connectToMaster( addressMaster, portMaster );
56 
57  // Initialise the fit model
58  this->initialise();
59 
60  // NB call to addConParameters() is intentionally not included here cf.
61  // LauAbsFitModel::run() since this has to be dealt with by the master
62  // to avoid multiple inclusions of each penalty term
63  // Print a warning if constraints on combinations of parameters have been specified
64  const std::vector<StoreConstraints>& storeCon = this->constraintsStore();
65  if ( ! storeCon.empty() ) {
66  std::cerr << "WARNING in LauSimFitSlave::runSlave : Constraints have been added but these will be ignored - they should have been added to the master process" << std::endl;
67  }
68 
69  // Setup saving of fit results to ntuple/LaTeX table etc.
70  this->setupResultsOutputs( histFileName, tableFileName );
71 
72  // This reads in the given dataFile and creates an input
73  // fit data tree that stores them for all events and experiments.
74  Bool_t dataOK = this->verifyFitData(dataFileName,dataTreeName);
75  if (!dataOK) {
76  std::cerr << "ERROR in LauSimFitSlave::runSlave : Problem caching the fit data." << std::endl;
77  return;
78  }
79 
80  // Now process the various requests from the master
81  this->processMasterRequests();
82 
83  std::cout << "INFO in LauSimFitSlave::runSlave : Fit slave " << this->slaveId() << " has finished successfully" << std::endl;
84 }
85 
86 void LauSimFitSlave::setupResultsOutputs( const TString& histFileName, const TString& /*tableFileName*/ )
87 {
88  // Create and setup the fit results ntuple
89  std::cout << "INFO in LauSimFitSlave::setupResultsOutputs : Creating fit ntuple." << std::endl;
90  if (fitNtuple_ != 0) {delete fitNtuple_; fitNtuple_ = 0;}
91  fitNtuple_ = new LauFitNtuple(histFileName, this->useAsymmFitErrors());
92 }
93 
94 void LauSimFitSlave::connectToMaster( const TString& addressMaster, const UInt_t portMaster )
95 {
96  if ( sMaster_ != 0 ) {
97  std::cerr << "ERROR in LauSimFitSlave::connectToMaster : master socket already present" << std::endl;
98  return;
99  }
100 
101  // Open connection to master
102  sMaster_ = new TSocket(addressMaster, portMaster);
103  sMaster_->Recv( messageFromMaster_ );
104 
105  messageFromMaster_->ReadUInt( slaveId_ );
106  messageFromMaster_->ReadUInt( nSlaves_ );
107 
108  Bool_t useAsymErrs(kFALSE);
109  messageFromMaster_->ReadBool( useAsymErrs );
110  this->useAsymmFitErrors(useAsymErrs);
111 
112  delete messageFromMaster_;
113  messageFromMaster_ = 0;
114 
115  std::cout << "INFO in LauSimFitSlave::connectToMaster : Established connection to master on port " << portMaster << std::endl;
116  std::cout << " : We are slave " << slaveId_ << " of " << nSlaves_ << std::endl;
117  if ( useAsymErrs ) {
118  std::cout << " : The fit will determine asymmetric errors" << std::endl;
119  }
120 }
121 
123 {
124  // Listen for requests from the master and act accordingly
125 
126  TMessage messageToMaster(kMESS_ANY);
127 
128  while ( kTRUE ) {
129 
130  sMaster_->Recv( messageFromMaster_ );
131 
132  if ( messageFromMaster_->What() == kMESS_STRING ) {
133 
134  TString msgStr;
135  messageFromMaster_->ReadTString( msgStr );
136 
137  std::cout << "INFO in LauSimFitSlave::processMasterRequests : Received message from master: " << msgStr << std::endl;
138 
139  if ( msgStr == "Send Parameters" ) {
140 
141  // Send the fit parameters
142 
143  TObjArray array;
144  this->prepareInitialParArray( array );
145 
146  // Create array to efficiently exchange parameter values with master
147  if ( parValues_ != 0 ) {
148  delete[] parValues_;
149  parValues_ = 0;
150  }
151  UInt_t nPar = array.GetEntries();
152  parValues_ = new Double_t[nPar];
153 
154  messageToMaster.Reset( kMESS_OBJECT );
155  messageToMaster.WriteObject( &array );
156  sMaster_->Send( messageToMaster );
157 
158  } else if ( msgStr == "Read Expt" ) {
159 
160  // Read the data for this experiment
161  UInt_t iExp(0);
162  messageFromMaster_->ReadUInt( iExp );
163 
164  this->setCurrentExperiment( iExp );
165 
166  UInt_t nEvents = this->readExperimentData();
167  if ( nEvents < 1 ) {
168  std::cerr << "WARNING in LauSimFitSlave::processMasterRequests : Zero events in experiment " << iExp << ", the master should skip this experiment..." << std::endl;
169  }
170 
171  messageToMaster.Reset( kMESS_ANY );
172  messageToMaster.WriteUInt( slaveId_ );
173  messageToMaster.WriteUInt( nEvents );
174  sMaster_->Send( messageToMaster );
175 
176  } else if ( msgStr == "Cache" ) {
177 
178  // Perform the caching
179 
180  this->cacheInputFitVars();
181 
182  messageToMaster.Reset( kMESS_ANY );
183  messageToMaster.WriteUInt( slaveId_ );
184  messageToMaster.WriteBool( kTRUE );
185  sMaster_->Send( messageToMaster );
186 
187  } else if ( msgStr == "Asym Error Calc" ) {
188 
189  Bool_t asymErrorCalc(kFALSE);
190  messageFromMaster_->ReadBool( asymErrorCalc );
191  this->withinAsymErrorCalc( asymErrorCalc );
192 
193  messageToMaster.Reset( kMESS_ANY );
194  messageToMaster.WriteUInt( slaveId_ );
195  messageToMaster.WriteBool( asymErrorCalc );
196  sMaster_->Send( messageToMaster );
197 
198  } else if ( msgStr == "Write Results" ) {
199 
200  this->writeOutAllFitResults();
201 
202  messageToMaster.Reset( kMESS_ANY );
203  messageToMaster.WriteUInt( slaveId_ );
204  messageToMaster.WriteBool( kTRUE );
205  sMaster_->Send( messageToMaster );
206 
207  } else if ( msgStr == "Finish" ) {
208 
209  std::cout << "INFO in LauSimFitSlave::processMasterRequests : Message from master to finish" << std::endl;
210  break;
211 
212  } else {
213 
214  std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Unexpected message from master" << std::endl;
215  gSystem->Exit( EXIT_FAILURE );
216 
217  }
218 
219  } else if ( messageFromMaster_->What() == kMESS_OBJECT ) {
220 
221  std::cout << "INFO in LauSimFitSlave::processMasterRequests : Received message from master: Finalise" << std::endl;
222 
223  Int_t status(0);
224  Double_t NLL(0.0);
225  Double_t EDM(0.0);
226  messageFromMaster_->ReadInt( status );
227  messageFromMaster_->ReadDouble( NLL );
228  messageFromMaster_->ReadDouble( EDM );
229 
230  TObjArray * objarray = dynamic_cast<TObjArray*>( messageFromMaster_->ReadObject( messageFromMaster_->GetClass() ) );
231  if ( ! objarray ) {
232  std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Error reading parameters from master" << std::endl;
233  gSystem->Exit( EXIT_FAILURE );
234  }
235 
236  TMatrixD * covMat = dynamic_cast<TMatrixD*>( messageFromMaster_->ReadObject( messageFromMaster_->GetClass() ) );
237  if ( ! covMat ) {
238  std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Error reading covariance matrix from master" << std::endl;
239  gSystem->Exit( EXIT_FAILURE );
240  }
241 
242  TObjArray array;
243  LauAbsFitter::FitStatus fitStat { status, NLL, EDM };
244  this->finaliseExperiment( fitStat, objarray, covMat, array );
245 
246  delete objarray; objarray = 0;
247  delete covMat; covMat = 0;
248 
249  // Send the finalised parameters back to the master
250  messageToMaster.Reset( kMESS_ANY );
251  messageToMaster.WriteUInt( slaveId_ );
252  messageToMaster.WriteBool( kTRUE );
253  messageToMaster.WriteObject( &array );
254  sMaster_->Send( messageToMaster );
255 
256  } else if ( messageFromMaster_->What() == kMESS_ANY ) {
257 
258  UInt_t nPars(0);
259  UInt_t nFreePars(0);
260  messageFromMaster_->ReadUInt( nPars );
261  messageFromMaster_->ReadUInt( nFreePars );
262 
263  if ( nPars != this->nTotParams() ) {
264  std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Unexpected number of parameters received from master" << std::endl;
265  std::cerr << " : Received " << nPars << " when expecting " << this->nTotParams() << std::endl;
266  gSystem->Exit( EXIT_FAILURE );
267  }
268 
269  messageFromMaster_->ReadFastArray( parValues_, nPars );
270 
271  this->setParsFromMinuit( parValues_, nFreePars );
272 
273  Double_t negLogLike = this->getTotNegLogLikelihood();
274 
275  messageToMaster.Reset( kMESS_ANY );
276  messageToMaster.WriteDouble( negLogLike );
277  sMaster_->Send( messageToMaster );
278 
279  } else {
280  std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Unexpected message type" << std::endl;
281  gSystem->Exit( EXIT_FAILURE );
282  }
283 
284  delete messageFromMaster_;
285  messageFromMaster_ = 0;
286  }
287 }
288 
290 {
291  // Write out histograms at end
292  if (fitNtuple_ != 0) {
294  }
295 }
296 
UInt_t nTotParams() const
Access the total number of fit parameters.
virtual void runSlave(const TString &dataFileName, const TString &dataTreeName, const TString &histFileName, const TString &tableFileName="", const TString &addressMaster="localhost", const UInt_t portMaster=9090)
Start the slave process for simultaneous fitting.
virtual void setupResultsOutputs(const TString &histFileName, const TString &tableFileName)
Setup saving of fit results to ntuple/LaTeX table etc.
Bool_t withinAsymErrorCalc() const
Query whether the fit is calculating the asymmetric errors.
Definition: LauFitObject.hh:74
ClassImp(LauAbsCoeffSet)
UInt_t slaveId_
Slave id number.
void processMasterRequests()
Listen for requests from the master and act accordingly.
virtual void writeOutAllFitResults()
Write out any fit results.
virtual ~LauSimFitSlave()
Destructor.
virtual UInt_t readExperimentData()=0
Read in the data for the current experiment.
LauFitNtuple * fitNtuple_
The fit ntuple.
virtual void finaliseExperiment(const LauAbsFitter::FitStatus &fitStat, const TObjArray *parsFromMaster, const TMatrixD *covMat, TObjArray &parsToMaster)=0
Perform all finalisation actions.
void connectToMaster(const TString &addressMaster, const UInt_t portMaster)
Establish the connection to the master process.
TSocket * sMaster_
A socket to enable parallel setup.
void writeOutFitResults()
Write out fit results.
void setCurrentExperiment(const UInt_t curExpt)
Set the ID of the current experiment.
const std::vector< StoreConstraints > & constraintsStore() const
Const access to the constraints store.
Struct to store fit status information.
Definition: LauAbsFitter.hh:41
virtual void prepareInitialParArray(TObjArray &array)=0
Package the initial fit parameters for transmission to the master.
TMessage * messageFromMaster_
Message from master to the slaves.
virtual void setParsFromMinuit(Double_t *par, Int_t npar)=0
This function sets the parameter values from Minuit.
UInt_t slaveId() const
Obtain the ID number of this slave.
File containing declaration of LauSimFitSlave class.
Bool_t useAsymmFitErrors() const
Report whether or not calculation of asymmetric errors is enabled.
Definition: LauFitObject.hh:43
virtual void initialise()=0
Initialise the fit model.
virtual Double_t getTotNegLogLikelihood()=0
Calculates the total negative log-likelihood.
The base class for any slave process for simultaneous/combined fits.
virtual void cacheInputFitVars()=0
Cache the input data values to calculate the likelihood during the fit.
friend class LauFitNtuple
LauFitNtuple is a friend class.
UInt_t nSlaves_
The total number of slaves.
Double_t * parValues_
Parameter values array (for reading from the master)
File containing declaration of LauFitNtuple class.
virtual Bool_t verifyFitData(const TString &dataFileName, const TString &dataTreeName)=0
Open the input file and verify that all required variables are present.