laura is hosted by Hepforge, IPPP Durham
Laura++  v3r5
A maximum likelihood fitting package for performing Dalitz-plot analysis.
LauSimFitSlave.cc
Go to the documentation of this file.
1 
2 /*
3 Copyright 2015 University of Warwick
4 
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8 
9  http://www.apache.org/licenses/LICENSE-2.0
10 
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 */
17 
18 /*
19 Laura++ package authors:
20 John Back
21 Paul Harrison
22 Thomas Latham
23 */
24 
29 #include <cstdlib>
30 #include <iostream>
31 
32 #include "TMatrixD.h"
33 #include "TMessage.h"
34 #include "TObjArray.h"
35 #include "TObjString.h"
36 #include "TSocket.h"
37 #include "TSystem.h"
38 
39 #include "LauSimFitSlave.hh"
40 #include "LauFitNtuple.hh"
41 
42 
44 
45 
47  sMaster_(0),
48  messageFromMaster_(0),
49  slaveId_(0),
50  nSlaves_(0),
51  parValues_(0),
52  fitNtuple_(0)
53 {
54 }
55 
57 {
58  delete sMaster_;
59  delete messageFromMaster_;
60  delete[] parValues_;
61  delete fitNtuple_;
62 }
63 
64 void LauSimFitSlave::runSlave(const TString& dataFileName, const TString& dataTreeName,
65  const TString& histFileName, const TString& tableFileName,
66  const TString& addressMaster, const UInt_t portMaster)
67 {
68  // Establish the connection to the master process
69  this->connectToMaster( addressMaster, portMaster );
70 
71  // Initialise the fit model
72  this->initialise();
73 
74  // NB call to addConParameters() is intentionally not included here cf.
75  // LauAbsFitModel::run() since this has to be dealt with by the master
76  // to avoid multiple inclusions of each penalty term
77  // Print a warning if constraints on combinations of parameters have been specified
78  const std::vector<StoreConstraints>& storeCon = this->constraintsStore();
79  if ( ! storeCon.empty() ) {
80  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;
81  }
82 
83  // Setup saving of fit results to ntuple/LaTeX table etc.
84  this->setupResultsOutputs( histFileName, tableFileName );
85 
86  // This reads in the given dataFile and creates an input
87  // fit data tree that stores them for all events and experiments.
88  Bool_t dataOK = this->verifyFitData(dataFileName,dataTreeName);
89  if (!dataOK) {
90  std::cerr << "ERROR in LauSimFitSlave::runSlave : Problem caching the fit data." << std::endl;
91  return;
92  }
93 
94  // Now process the various requests from the master
95  this->processMasterRequests();
96 
97  std::cout << "INFO in LauSimFitSlave::runSlave : Fit slave " << this->slaveId() << " has finished successfully" << std::endl;
98 }
99 
100 void LauSimFitSlave::setupResultsOutputs( const TString& histFileName, const TString& /*tableFileName*/ )
101 {
102  // Create and setup the fit results ntuple
103  std::cout << "INFO in LauSimFitSlave::setupResultsOutputs : Creating fit ntuple." << std::endl;
104  if (fitNtuple_ != 0) {delete fitNtuple_; fitNtuple_ = 0;}
105  fitNtuple_ = new LauFitNtuple(histFileName, this->useAsymmFitErrors());
106 }
107 
108 void LauSimFitSlave::connectToMaster( const TString& addressMaster, const UInt_t portMaster )
109 {
110  if ( sMaster_ != 0 ) {
111  std::cerr << "ERROR in LauSimFitSlave::connectToMaster : master socket already present" << std::endl;
112  return;
113  }
114 
115  // Open connection to master
116  sMaster_ = new TSocket(addressMaster, portMaster);
117  sMaster_->Recv( messageFromMaster_ );
118 
119  messageFromMaster_->ReadUInt( slaveId_ );
120  messageFromMaster_->ReadUInt( nSlaves_ );
121 
122  Bool_t useAsymErrs(kFALSE);
123  messageFromMaster_->ReadBool( useAsymErrs );
124  this->useAsymmFitErrors(useAsymErrs);
125 
126  delete messageFromMaster_;
127  messageFromMaster_ = 0;
128 
129  std::cout << "INFO in LauSimFitSlave::connectToMaster : Established connection to master on port " << portMaster << std::endl;
130  std::cout << " : We are slave " << slaveId_ << " of " << nSlaves_ << std::endl;
131  if ( useAsymErrs ) {
132  std::cout << " : The fit will determine asymmetric errors" << std::endl;
133  }
134 }
135 
137 {
138  // Listen for requests from the master and act accordingly
139 
140  TMessage messageToMaster(kMESS_ANY);
141 
142  while ( kTRUE ) {
143 
144  sMaster_->Recv( messageFromMaster_ );
145 
146  if ( messageFromMaster_->What() == kMESS_STRING ) {
147 
148  TString msgStr;
149  messageFromMaster_->ReadTString( msgStr );
150 
151  std::cout << "INFO in LauSimFitSlave::processMasterRequests : Received message from master: " << msgStr << std::endl;
152 
153  if ( msgStr == "Send Parameters" ) {
154 
155  // Send the fit parameters
156 
157  TObjArray array;
158  this->prepareInitialParArray( array );
159 
160  // Create array to efficiently exchange parameter values with master
161  if ( parValues_ != 0 ) {
162  delete[] parValues_;
163  parValues_ = 0;
164  }
165  UInt_t nPar = array.GetEntries();
166  parValues_ = new Double_t[nPar];
167 
168  messageToMaster.Reset( kMESS_OBJECT );
169  messageToMaster.WriteObject( &array );
170  sMaster_->Send( messageToMaster );
171 
172  } else if ( msgStr == "Read Expt" ) {
173 
174  // Read the data for this experiment
175  UInt_t iExp(0);
176  messageFromMaster_->ReadUInt( iExp );
177 
178  this->setCurrentExperiment( iExp );
179 
180  UInt_t nEvents = this->readExperimentData();
181  if ( nEvents < 1 ) {
182  std::cerr << "WARNING in LauSimFitSlave::processMasterRequests : Zero events in experiment " << iExp << ", the master should skip this experiment..." << std::endl;
183  }
184 
185  messageToMaster.Reset( kMESS_ANY );
186  messageToMaster.WriteUInt( slaveId_ );
187  messageToMaster.WriteUInt( nEvents );
188  sMaster_->Send( messageToMaster );
189 
190  } else if ( msgStr == "Cache" ) {
191 
192  // Perform the caching
193 
194  this->cacheInputFitVars();
195 
196  messageToMaster.Reset( kMESS_ANY );
197  messageToMaster.WriteUInt( slaveId_ );
198  messageToMaster.WriteBool( kTRUE );
199  sMaster_->Send( messageToMaster );
200 
201  } else if ( msgStr == "Asym Error Calc" ) {
202 
203  Bool_t asymErrorCalc(kFALSE);
204  messageFromMaster_->ReadBool( asymErrorCalc );
205  this->withinAsymErrorCalc( asymErrorCalc );
206 
207  messageToMaster.Reset( kMESS_ANY );
208  messageToMaster.WriteUInt( slaveId_ );
209  messageToMaster.WriteBool( asymErrorCalc );
210  sMaster_->Send( messageToMaster );
211 
212  } else if ( msgStr == "Write Results" ) {
213 
214  this->writeOutAllFitResults();
215 
216  messageToMaster.Reset( kMESS_ANY );
217  messageToMaster.WriteUInt( slaveId_ );
218  messageToMaster.WriteBool( kTRUE );
219  sMaster_->Send( messageToMaster );
220 
221  } else if ( msgStr == "Finish" ) {
222 
223  std::cout << "INFO in LauSimFitSlave::processMasterRequests : Message from master to finish" << std::endl;
224  break;
225 
226  } else {
227 
228  std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Unexpected message from master" << std::endl;
229  gSystem->Exit( EXIT_FAILURE );
230 
231  }
232 
233  } else if ( messageFromMaster_->What() == kMESS_OBJECT ) {
234 
235  std::cout << "INFO in LauSimFitSlave::processMasterRequests : Received message from master: Finalise" << std::endl;
236 
237  Int_t status(0);
238  Double_t NLL(0.0);
239  Double_t EDM(0.0);
240  messageFromMaster_->ReadInt( status );
241  messageFromMaster_->ReadDouble( NLL );
242  messageFromMaster_->ReadDouble( EDM );
243 
244  TObjArray * objarray = dynamic_cast<TObjArray*>( messageFromMaster_->ReadObject( messageFromMaster_->GetClass() ) );
245  if ( ! objarray ) {
246  std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Error reading parameters from master" << std::endl;
247  gSystem->Exit( EXIT_FAILURE );
248  }
249 
250  TMatrixD * covMat = dynamic_cast<TMatrixD*>( messageFromMaster_->ReadObject( messageFromMaster_->GetClass() ) );
251  if ( ! covMat ) {
252  std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Error reading covariance matrix from master" << std::endl;
253  gSystem->Exit( EXIT_FAILURE );
254  }
255 
256  TObjArray array;
257  LauAbsFitter::FitStatus fitStat { status, NLL, EDM };
258  this->finaliseExperiment( fitStat, objarray, covMat, array );
259 
260  delete objarray; objarray = 0;
261  delete covMat; covMat = 0;
262 
263  // Send the finalised parameters back to the master
264  messageToMaster.Reset( kMESS_ANY );
265  messageToMaster.WriteUInt( slaveId_ );
266  messageToMaster.WriteBool( kTRUE );
267  messageToMaster.WriteObject( &array );
268  sMaster_->Send( messageToMaster );
269 
270  } else if ( messageFromMaster_->What() == kMESS_ANY ) {
271 
272  UInt_t nPars(0);
273  UInt_t nFreePars(0);
274  messageFromMaster_->ReadUInt( nPars );
275  messageFromMaster_->ReadUInt( nFreePars );
276 
277  if ( nPars != this->nTotParams() ) {
278  std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Unexpected number of parameters received from master" << std::endl;
279  std::cerr << " : Received " << nPars << " when expecting " << this->nTotParams() << std::endl;
280  gSystem->Exit( EXIT_FAILURE );
281  }
282 
283  messageFromMaster_->ReadFastArray( parValues_, nPars );
284 
285  this->setParsFromMinuit( parValues_, nFreePars );
286 
287  Double_t negLogLike = this->getTotNegLogLikelihood();
288 
289  messageToMaster.Reset( kMESS_ANY );
290  messageToMaster.WriteDouble( negLogLike );
291  sMaster_->Send( messageToMaster );
292 
293  } else {
294  std::cerr << "ERROR in LauSimFitSlave::processMasterRequests : Unexpected message type" << std::endl;
295  gSystem->Exit( EXIT_FAILURE );
296  }
297 
298  delete messageFromMaster_;
299  messageFromMaster_ = 0;
300  }
301 }
302 
304 {
305  // Write out histograms at end
306  if (fitNtuple_ != 0) {
308  }
309 }
310 
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:88
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:55
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:57
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.