std::cerr << "ERROR in LauAbsFitModel::fitSlave : Problem caching the fit data." << std::endl;
gSystem->Exit(EXIT_FAILURE);
}
// Now process the various requests from the master
TMessage messageToMaster(kMESS_ANY);
while ( kTRUE ) {
sMaster_->Recv( messageFromMaster_ );
if ( messageFromMaster_->What() == kMESS_STRING ) {
TString msgStr;
messageFromMaster_->ReadTString( msgStr );
std::cout << "INFO in LauAbsFitModel::fitSlave : Received message from master: " << msgStr << std::endl;
if ( msgStr == "Send Parameters" ) {
// Update initial fit parameters if required (e.g. if using random numbers).
this->checkInitFitParams();
// Send the fit parameters
TObjArray array;
for ( LauParameterPList::iterator iter = fitVars_.begin(); iter != fitVars_.end(); ++iter ) {
array.Add( *iter );
}
messageToMaster.Reset( kMESS_OBJECT );
messageToMaster.WriteObject( &array );
sMaster_->Send( messageToMaster );
} else if ( msgStr == "Read Expt" ) {
// Read the data for this experiment
messageFromMaster_->ReadUInt( iExpt_ );
inputFitData_->readExperimentData( iExpt_ );
UInt_t nEvent = inputFitData_->nEvents();
this->eventsPerExpt( nEvent );
if ( nEvent < 1 ) {
std::cerr << "ERROR in LauAbsFitModel::fitSlave : Zero events in experiment " << firstExpt_ << ", the master should skip this experiment..." << std::endl;
}
messageToMaster.Reset( kMESS_ANY );
messageToMaster.WriteUInt( slaveId_ );
messageToMaster.WriteUInt( nEvent );
sMaster_->Send( messageToMaster );
} else if ( msgStr == "Cache" ) {
// Perform the caching
this->cacheInputFitVars();
messageToMaster.Reset( kMESS_ANY );
messageToMaster.WriteUInt( slaveId_ );
messageToMaster.WriteBool( kTRUE );
sMaster_->Send( messageToMaster );
} else if ( msgStr == "Write Results" ) {
this->writeOutAllFitResults();
messageToMaster.Reset( kMESS_ANY );
messageToMaster.WriteUInt( slaveId_ );
messageToMaster.WriteBool( kTRUE );
sMaster_->Send( messageToMaster );
} else if ( msgStr == "Finish" ) {
std::cout << "INFO in LauAbsFitModel::fitSlave : Message from master to finish" << std::endl;
break;
} else {
std::cerr << "ERROR in LauAbsFitModel::fitSlave : Unexpected message from master" << std::endl;
gSystem->Exit( EXIT_FAILURE );
}
} else if ( messageFromMaster_->What() == kMESS_OBJECT ) {
std::cout << "INFO in LauAbsFitModel::fitSlave : Received message from master: Finalise" << std::endl;
std::cout << "INFO in LauSimFitMaster::initSockets : Initialising slaves" << std::endl;
for ( UInt_t iSlave(0); iSlave<nSlaves_; ++iSlave ) {
TMessage message( kMESS_ANY );
message.WriteUInt(iSlave);
message.WriteUInt(nSlaves_);
sSlaves_[iSlave]->Send(message);
socketMonitor_->Add(sSlaves_[iSlave]);
}
std::cout << " : Now start fit\n" << std::endl;
ss->Close();
delete ss;
}
/*
* OLD VERSION THAT JUST GETS THE NAMES - COULD HAVE A SERIES OF EXCHANGES TO GET THE NAMES, INIT VALUES, RANGES, ETC. INSTEAD OF PASSING PARAMETERS
* THIS INCREASES THE GENERALITY OF THE CODE, I.E. THERE IS NO NEED FOR THE SLAVES TO KNOW ANY LAURA++ CLASS BUT THIS ONE, BUT MAKES IT RATHER MORE DENSE
* FOR THE MOMENT I WILL STICK WITH THE METHOD OF PASSING LAUPARAMETER OBJECTS AROUND AND CONSIDER GOING BACK TO THIS GENERAL METHOD ONCE EVERYTHING IS WORKING
std::cerr << "ERROR in LauSimFitMaster::printParInfo : Discrepancy in parameter name and value records, this is very strange!!" << std::endl;
}
std::cout << " : " << parName << " = " << parValue << " and has index " << *iter << "\n";
}
std::cout << std::endl;
}
std::cout << "INFO in LauSimFitMaster::printParInfo : " << "There are " << nParams_ << " parameters in total" << std::endl;
}
void LauSimFitMaster::checkParameter( const LauParameter* param, UInt_t index ) const
{
const LauParameter* storedPar = params_[index];
TString parName = storedPar->name();
if ( param->name() != parName ) {
std::cerr << "ERROR in LauSimFitMaster::checkParameter : Parameter name is different!! This shouldn't happen!!" << std::endl;
}
if ( param->initValue() != storedPar->initValue() ) {
std::cerr << "WARNING in LauSimFitMaster::checkParameter : Initial value for parameter " << parName << " is different, will use the value first set: " << storedPar->initValue() << std::endl;
}
if ( param->minValue() != storedPar->minValue() ) {
std::cerr << "WARNING in LauSimFitMaster::checkParameter : Minimum allowed value for parameter " << parName << " is different, will use the value first set: " << storedPar->minValue() << std::endl;
}
if ( param->maxValue() != storedPar->maxValue() ) {
std::cerr << "WARNING in LauSimFitMaster::checkParameter : Maximum allowed value for parameter " << parName << " is different, will use the value first set: " << storedPar->maxValue() << std::endl;
}
if ( param->fixed() != storedPar->fixed() ) {
std::cerr << "WARNING in LauSimFitMaster::checkParameter : Fixed/floating property of parameter " << parName << " is different, will use the value first set: " << (storedPar->fixed() ? "fixed" : "floating") << std::endl;
}
if ( param->firstStage() != storedPar->firstStage() ) {
std::cerr << "WARNING in LauSimFitMaster::checkParameter : First stage property of parameter " << parName << " is different, will use the value first set: " << (storedPar->firstStage() ? "true" : "false") << std::endl;
}
if ( param->secondStage() != storedPar->secondStage() ) {
std::cerr << "WARNING in LauSimFitMaster::checkParameter : Second stage property of parameter " << parName << " is different, will use the value first set: " << (storedPar->secondStage() ? "true" : "false") << std::endl;
std::cout << "INFO in LauSimFitMaster::runSimFit : First experiment = " << firstExpt << std::endl;
std::cout << "INFO in LauSimFitMaster::runSimFit : Number of experiments = " << nExpt << std::endl;
// Start the cumulative timer
cumulTimer_.Start();
numberOKFits_ = 0, numberBadFits_ = 0;
fitStatus_ = -1;
// Create and setup the fit results ntuple
std::cout << "INFO in LauSimFitMaster::runSimFit : Creating fit ntuple." << std::endl;
if (fitNtuple_ != 0) {delete fitNtuple_; fitNtuple_ = 0;}
fitNtuple_ = new LauFitNtuple(fitNtupleFileName, useAsymmErrors);
// Loop over the number of experiments
for (iExpt_ = firstExpt; iExpt_ < (firstExpt+nExpt); ++iExpt_) {
// Start the timer to see how long each fit takes
timer_.Start();
// Instruct the slaves to read the data for this experiment
Bool_t readOK = this->readData();
if ( ! readOK ) {
std::cerr << "ERROR in LauSimFitMaster::runSimFit : One or more slaves reported problems with reading data for experiment " << iExpt_ << ", skipping..." << std::endl;
timer_.Stop();
continue;
}
// Instruct the slaves to perform the caching
this->cacheInputData();
// Do the fit
this->fitExpt( useAsymmErrors, twoStageFit );
// Stop the timer and see how long the program took so far
timer_.Stop();
timer_.Print();
// Instruct the slaves to finalise the results
this->finalise();
// Keep track of how many fits succeeded or failed
if (fitStatus_ == 3) {
++numberOKFits_;
} else {
++numberBadFits_;
}
}
// Print out total timing info.
std::cout << "INFO in LauSimFitMaster::runSimFit : Cumulative timing:" << std::endl;
cumulTimer_.Stop();
cumulTimer_.Print();
// Print out stats on OK fits.
std::cout << "INFO in LauSimFitMaster::runSimFit : Number of OK Fits = " << numberOKFits_ << std::endl;
std::cout << "INFO in LauSimFitMaster::runSimFit : Number of Failed Fits = " << numberBadFits_ << std::endl;
Double_t fitEff(0.0);
if (nExpt != 0) {fitEff = numberOKFits_/(1.0*nExpt);}
std::cout << "INFO in LauSimFitMaster::runSimFit : Fit efficiency = " << fitEff*100.0 << "%." << std::endl;
// Instruct the slaves to write out any fit results (ntuples etc...).
this->writeOutResults();
}
Bool_t LauSimFitMaster::readData()
{
if ( socketMonitor_ == 0 ) {
std::cerr << "ERROR in LauSimFitMaster::readData : Sockets not initialised." << std::endl;
return kFALSE;
}
// Construct a message, requesting to read the data for the given experiment
TString msgStr("Read Expt");
TMessage message( kMESS_STRING );
message.WriteTString( msgStr );
message.WriteUInt( iExpt_ );
// Send the message to the slaves
for ( UInt_t iSlave(0); iSlave<nSlaves_; ++iSlave ) {
sSlaves_[iSlave]->Send(message);
}
TSocket* sActive(0);
UInt_t responsesReceived(0);
Bool_t ok(kTRUE);
while ( responsesReceived != nSlaves_ ) {
// Get the next queued response
sActive = socketMonitor_->Select();
// Extract from the message the ID of the slave and the number of events read
sActive->Recv( messageFromSlave_ );
UInt_t iSlave(0);
UInt_t nEvents(0);
messageFromSlave_->ReadUInt( iSlave );
messageFromSlave_->ReadUInt( nEvents );
if ( nEvents <= 0 ) {
std::cerr << "ERROR in LauSimFitMaster::readData : Slave " << iSlave << " reports no events found for experiment " << iExpt_ << std::endl;
ok = kFALSE;
} else {
std::cerr << "INFO in LauSimFitMaster::readData : Slave " << iSlave << " reports " << nEvents << " events found for experiment " << iExpt_ << std::endl;
}
++responsesReceived;
}
return ok;
}
Bool_t LauSimFitMaster::cacheInputData()
{
if ( socketMonitor_ == 0 ) {
std::cerr << "ERROR in LauSimFitMaster::cacheInputData : Sockets not initialised." << std::endl;
return kFALSE;
}
// Construct a message, requesting it to read the data for the given experiment
TString msgStr("Cache");
TMessage message( kMESS_STRING );
message.WriteTString( msgStr );
for ( UInt_t iSlave(0); iSlave<nSlaves_; ++iSlave ) {
// Send the message to the slave
sSlaves_[iSlave]->Send(message);
}
TSocket* sActive(0);
UInt_t responsesReceived(0);
Bool_t allOK(kTRUE);
while ( responsesReceived != nSlaves_ ) {
// Get the next queued response
sActive = socketMonitor_->Select();
// Extract from the message the ID of the slave and the success/failure flag
sActive->Recv( messageFromSlave_ );
UInt_t iSlave(0);
Bool_t ok(kTRUE);
messageFromSlave_->ReadUInt( iSlave );
messageFromSlave_->ReadBool( ok );
if ( ! ok ) {
std::cerr << "ERROR in LauSimFitMaster::cacheInputData : Slave " << iSlave << " reports an error performing caching" << std::endl;