Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions include/MAssembly.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,15 @@ class MAssembly
//! Default destructor
virtual ~MAssembly();

//! Each interface must be able to parse a command line -
//! Each interface must be able to parse a command line -
//! this function is called by main()
bool ParseCommandLine(int argc, char** argv);


//! Return true if the last call to ParseCommandLine() found a command line error
//! ParseCommandLine() also returns false when it did its work and the UI must not be
//! launched, e.g. for --help, --auto, and --test - this flag distinguishes the two
bool HasCommandLineError() const { return m_HasCommandLineError; }

//! Called when hit Control-C: Set the interrupt which will end the analysis in the supervisor
void SetInterrupt(bool Flag = true) { m_Supervisor->SetHardInterrupt(Flag); }

Expand Down Expand Up @@ -82,7 +87,7 @@ class MAssembly

// protected methods:
protected:

// private methods:
private:

Expand All @@ -95,17 +100,17 @@ class MAssembly
private:
//! True if the GUI is used
bool m_UseGui;

//! The store for all user data of the GUI:
MSupervisor* m_Supervisor;

//! The interrupt flag - the analysis will stop when this flag is set
bool m_Interrupt;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About m_Interrupt: is it correct that this was just not used before? I can only find m_Interrupt being used (but also defined) in the apps now.



//! True if the last call to ParseCommandLine() found a command line error
bool m_HasCommandLineError;


#ifdef ___CLING___
public:
ClassDef(MAssembly, 1)
ClassDef(MAssembly, 1)
#endif

};
Expand Down
147 changes: 89 additions & 58 deletions src/MAssembly.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -29,35 +29,23 @@
// Standard libs:
#include <iostream>
#include <sstream>
#include <vector>
#include <csignal>
using namespace std;

// ROOT libs:
#include "TROOT.h"
#include "TCanvas.h"
#include "TView.h"
#include "TGMsgBox.h"
#include "TH2.h"
#include "TCanvas.h"
#include "TApplication.h"
#include "TRandom.h"

// MEGAlib libs:
#include "MGlobal.h"
#include "MAssert.h"
#include "MStreams.h"
#include "MString.h"
#include "MTimer.h"
#include "MFile.h"

// Nuclearizer libs:
#include "MFretalonRegistry.h"
#include "MReadOutDataTAC.h"
#include "MReadOutDataEnergy.h"
#include "MReadOutAssembly.h"
#include "MModule.h"
#include "MGUIExpoCombinedViewer.h"
#include "MModuleTransmitterRealta.h"
#include "MModuleLoaderSimulationsCosima.h"
#include "MModuleLoaderMeasurementsROA.h"
Expand Down Expand Up @@ -96,13 +84,13 @@ ClassImp(MAssembly)
MAssembly::MAssembly()
{
// standard constructor

m_Interrupt = false;

m_UseGui = true;

m_HasCommandLineError = false;

g_Verbosity = c_Error;
//! Register new read out data:

// Register new read-out data:
MReadOutDataTAC TAC;
MFretalonRegistry::Instance().Register(TAC);

Expand All @@ -111,16 +99,16 @@ MAssembly::MAssembly()

// Create the supervisor
m_Supervisor = MSupervisor::GetSupervisor();

// Fixed seed to reproduce DEE results
gRandom->SetSeed(20170912);

MString Cfg = "~/.nuclearizer.cfg";
MFile::ExpandFileName(Cfg);
m_Supervisor->SetConfigurationFileName(Cfg);

m_Supervisor->UseMultiThreading(true);

m_Supervisor->AddAvailableModule(new MModuleLoaderSimulationsCosima());
m_Supervisor->AddAvailableModule(new MModuleLoaderMeasurementsROA());
m_Supervisor->AddAvailableModule(new MModuleLoaderMeasurementsHDF());
Expand All @@ -135,7 +123,7 @@ MAssembly::MAssembly()
m_Supervisor->AddAvailableModule(new MModuleStripPairingMultiRoundChiSquare());
m_Supervisor->AddAvailableModule(new MModuleStripPairingChiSquare());
m_Supervisor->AddAvailableModule(new MModuleDepthCalibration());

m_Supervisor->AddAvailableModule(new MModuleEventSaver());
m_Supervisor->AddAvailableModule(new MModuleSaverMeasurementsL0());
m_Supervisor->AddAvailableModule(new MModuleSaverMeasurementsFITS());
Expand All @@ -152,7 +140,7 @@ MAssembly::MAssembly()
m_Supervisor->AddAvailableModule(new MModuleDiagnosticsEnergyPerStrip());

m_Supervisor->Load();

m_Supervisor->SetUIProgramName("Nuclearizer");
m_Supervisor->SetUIPicturePath("$(NUCLEARIZER)/resource/icons/Nuclearizer.xpm");
m_Supervisor->SetUISubTitle("The detector calibrator of the COmpton Spectrometer and Imager, COSI");
Expand Down Expand Up @@ -180,9 +168,9 @@ bool MAssembly::ParseCommandLine(int argc, char** argv)
Usage<<endl;
Usage<<" Usage: Nuclearizer <options>"<<endl;
Usage<<endl;
Usage<<" -c --configuration <filename>.xml.cfg:"<<endl;
Usage<<" -c --configuration <filename>.cfg:"<<endl;
Usage<<" Use this file as configuration file."<<endl;
Usage<<" If no configuration file is give ~/.nuclearizer.xml.cfg is used"<<endl;
Usage<<" If no configuration file is given ~/.nuclearizer.cfg is used"<<endl;
Usage<<" -C --change-configuration <pattern>:"<<endl;
Usage<<" Replace any value in the configuration file (-C can be used multiple times)"<<endl;
Usage<<" E.g. to change the roa file, one would set pattern to:"<<endl;
Expand All @@ -197,77 +185,120 @@ bool MAssembly::ParseCommandLine(int argc, char** argv)
Usage<<" Perform a test run to see if nuclearizer can be started up correctly."<<endl;
Usage<<" -v --verbosity:"<<endl;
Usage<<" Verbosity: 0: Quiet, 1: Errors, 2: Warnings, 3: Info"<<endl;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe for clarity (there's many colons here):

Suggested change
Usage<<" Verbosity: 0: Quiet, 1: Errors, 2: Warnings, 3: Info"<<endl;
Usage<<" Verbosity: 0 = Quiet, 1 = Errors, 2 = Warnings, 3 = Info"<<endl;

?

Usage<<" -h --help:"<<endl;
Usage<<" You know the answer..."<<endl;
Usage<<" -h --help -? ?:"<<endl;
Usage<<" Print these command line options"<<endl;
Usage<<" Help gets preference over all other options"<<endl;
Usage<<endl;


// Each call starts without an error, otherwise an error of an earlier call would stick
m_HasCommandLineError = false;

// Store some options temporarily:
MString Option;

// Check for help
for (int i = 1; i < argc; i++) {
Option = argv[i];
if (Option == "-h" || Option == "--help" || Option == "?" || Option == "-?") {
if (Option == "--help" || Option == "-h" || Option == "-?" || Option == "?") {

@fhagemann fhagemann Aug 13, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of interest: why was the order of the Options changed? Is it good practice to have the written-out option first, so it's easier for people looking at the code which option is being processed by that code?

cout<<Usage.str()<<endl;
return false;
}
}

// First check if all options are ok:
for (int i = 1; i < argc; i++) {
Option = argv[i];

// Single argument
if (Option == "-c" || Option == "--configuration" ||
Option == "-g" || Option == "--geometry" ||
Option == "-m" || Option == "--multithreading") {
if (!((argc > i+1) && argv[i+1][0] != '-')){
cout<<"Error: Option "<<argv[i][1]<<" needs a second argument!"<<endl;
if (Option == "--configuration" || Option == "-c" ||
Option == "--change-configuration" || Option == "-C" ||
Option == "--geometry" || Option == "-g" ||
Option == "--multithreading" || Option == "-m" ||
Option == "--verbosity" || Option == "-v") {
if (argc <= i + 1 || argv[i + 1][0] == '-') {
cout<<"ERROR: Command-line parser: Option "<<Option<<" needs a second argument!"<<endl;
cout<<Usage.str()<<endl;
m_HasCommandLineError = true;
return false;
}
}
// No argument
else if (Option == "--auto" || Option == "-a" ||
Option == "--test" || Option == "-t") {
// Nothing to check
}
// Anything else which looks like an option is unknown - the arguments of the
// above options never start with a "-", thus they cannot end up here
else if (Option.BeginsWith("-") == true) {
cout<<"WARNING: Command-line parser: Unknown option: "<<Option<<endl;
}
}

// Now parse all low level options
for (int i = 1; i < argc; i++) {
Option = argv[i];
if (Option == "--configuration" || Option == "-c") {
m_Supervisor->Load(argv[++i]);
cout<<"Command-line parser: Use configuration file "<<argv[i]<<endl;
// If the configuration file cannot be read, we continue with an empty one
if (m_Supervisor->Load(argv[++i]) == false) {
cout<<"WARNING: Command-line parser: Unable to load configuration file "<<argv[i]<<endl;
} else {
cout<<"Command-line parser: Use configuration file "<<argv[i]<<endl;
}
} else if (Option == "--verbosity" || Option == "-v") {
g_Verbosity = atoi(argv[++i]);
const MString Value = argv[++i];
if (Value.Is<int>() == false) {
cout<<"ERROR: Command-line parser: Option "<<Option<<" needs an integer argument, not \""<<Value<<"\"!"<<endl;
cout<<Usage.str()<<endl;
m_HasCommandLineError = true;
return false;
}
int Verbosity = Value.ToInt();
if (Verbosity < c_Quiet || Verbosity > c_Info) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen in megalib that there is also c_Chatty and c_Extreme.
I guess we are not allowing for those in nuclearizer, hence they are excluded?
What if someone wants a "chatty" megalib?

cout<<"ERROR: Command-line parser: Option "<<Option<<" needs an argument between "<<c_Quiet<<" and "<<c_Info<<", not \""<<Value<<"\"!"<<endl;
cout<<Usage.str()<<endl;
m_HasCommandLineError = true;
return false;
}
g_Verbosity = Verbosity;
cout<<"Command-line parser: Verbosity "<<g_Verbosity<<endl;
} else if (Option == "--multithreading" || Option == "-m") {
m_Supervisor->UseMultiThreading((atoi(argv[++i]) != 0 ? true : false));
cout<<"Command-line parser: Using multithreading: "<<(atoi(argv[i]) != 0 ? "yes" : "no")<<endl;
const MString Value = argv[++i];
if (Value.Is<int>() == false) {
cout<<"ERROR: Command-line parser: Option "<<Option<<" needs an integer argument, not \""<<Value<<"\"!"<<endl;
cout<<Usage.str()<<endl;
m_HasCommandLineError = true;
return false;
}
const bool UseMultiThreading = (Value.ToInt() != 0);
m_Supervisor->UseMultiThreading(UseMultiThreading);
cout<<"Command-line parser: Using multithreading: "<<(UseMultiThreading == true ? "yes" : "no")<<endl;
} else if (Option == "--test" || Option == "-t") {
// Parse later
} else if (Option == "--auto" || Option == "-a") {
// Parse later
}
Comment on lines 275 to 279

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this? (I guess // Parse later refers to the // Now parse all high level options block later in this function?)

}

// Look if we need to change the configuration
for (int i = 1; i < argc; i++) {
Option = argv[i];
if (Option == "--change-configuration" || Option == "-C") {
if (m_Supervisor->ChangeConfiguration(argv[++i]) == false) {
cout<<"ERROR: Command-line parser: Unable to change this configuration value: "<<argv[i]<<endl;
cout<<"ERROR: Command-line parser: Unable to change this configuration value: "<<argv[i]<<endl;
} else {
cout<<"Command-line parser: Changing this configuration value: "<<argv[i]<<endl;
}
}
}
}

for (int i = 1; i < argc; i++) {
Option = argv[i];
if (Option == "--geometry" || Option == "-g") {
m_Supervisor->SetGeometryFileName(argv[++i]);
cout<<"Command-line parser: Use geometry file "<<argv[i]<<endl;
}
}

// Now parse all high level options
for (int i = 1; i < argc; i++) {
Option = argv[i];
Expand All @@ -279,21 +310,21 @@ bool MAssembly::ParseCommandLine(int argc, char** argv)
m_Supervisor->Exit();
return false;
} else if (Option == "--test" || Option == "-t") {
m_UseGui = false;
gROOT->SetBatch(true);
m_Supervisor->UseUI(false);
m_Supervisor->Analyze(true);
m_Supervisor->Exit();
return false;
}
m_UseGui = false;
gROOT->SetBatch(true);
m_Supervisor->UseUI(false);
m_Supervisor->Analyze(true);
m_Supervisor->Exit();
return false;
}
}

if (m_UseGui == true) {
if (m_Supervisor->LaunchUI() == false) {
return false;
return false;
}
}

return true;
}

Expand Down
2 changes: 2 additions & 0 deletions src/MModuleRevan.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ MModuleRevan::MModuleRevan() : MModule()
// Allow the use of multiple threads and instances
m_AllowMultiThreading = true;
m_AllowMultipleInstances = false;

m_RawEventAnalyzer = nullptr;
}


Expand Down
8 changes: 5 additions & 3 deletions src/MNuclearizerMain.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ void CatchSignal(int a)


//! In the beginning Andreas created main and Andreas said "Let there be code!"
//! After many years of coding and debugging, Andreas saw all that he had made,
//! After many years of coding and debugging, Andreas saw all that he had made,
//! and it was very good.
int main(int argc, char** argv)
{
Expand All @@ -83,10 +83,12 @@ int main(int argc, char** argv)
MAssembly Nuclearizer;
g_Prg = &Nuclearizer;
if (Nuclearizer.ParseCommandLine(argc, argv) == false) {
return 0;
// ParseCommandLine() also returns false when it did all its work and the UI must not
// be launched, e.g. for --help, --auto, and --test - only a rejected command line is a failure
return Nuclearizer.HasCommandLineError() == true ? 1 : 0;
} else {
AppNuclearizer->Run();
}
}

return 0;
}
Expand Down
Loading
Loading