void SelectionCollection::initOptions(Options *options, SelectionTypeOption selectionTypeOption) { const char * const debug_levels[] = { "no", "basic", "compile", "eval", "full" }; const char *const *postypes = PositionCalculationCollection::typeEnumValues; options->addOption(StringOption("selrpos") .enumValueFromNullTerminatedArray(postypes) .store(&impl_->rpost_).defaultValue(postypes[0]) .description("Selection reference positions")); if (selectionTypeOption == IncludeSelectionTypeOption) { options->addOption(StringOption("seltype") .enumValueFromNullTerminatedArray(postypes) .store(&impl_->spost_).defaultValue(postypes[0]) .description("Default selection output positions")); } else { impl_->spost_ = postypes[0]; } GMX_RELEASE_ASSERT(impl_->debugLevel_ >= 0 && impl_->debugLevel_ <= 4, "Debug level out of range"); options->addOption(StringOption("seldebug").hidden(impl_->debugLevel_ == 0) .enumValue(debug_levels) .defaultValue(debug_levels[impl_->debugLevel_]) .storeEnumIndex(&impl_->debugLevel_) .description("Print out selection trees for debugging")); }
void FileNameOptionManager::addDefaultFileNameOption( IOptionsContainer *options, const char *name) { options->addOption( StringOption(name).store(&impl_->defaultFileName_) .description("Set the default filename for all file options")); }
void TimeUnitManager::addTimeUnitOption(Options *options, const char *name) { options->addOption(StringOption(name).enumValue(g_timeUnits) .defaultValue(g_timeUnits[timeUnit()]) .storeEnumIndex(&timeUnit_) .description("Unit for time values")); }
void AnalysisDataPlotSettings::initOptions(IOptionsContainer *options) { options->addOption(StringOption("xvg").enumValue(g_plotFormats) .defaultValue("xmgrace") .storeEnumIndex(&plotFormat_) .description("Plot formatting")); }
void CmdLineOptions::add_optional(std::string const &name, std::string const &description, std::string const &default_value) { std::unique_lock<std::mutex> l(mutex_); if (is_arg(name) || is_switch(name)) { throw OptionDefined(); } std::string niceName(name); trim(niceName); argOptionList_.push_back(StringOption(niceName, description, default_value)); }
Options * SelectionCollection::initOptions() { static const char * const debug_levels[] = {"no", "basic", "compile", "eval", "full", NULL}; /* static const char * const desc[] = { "This program supports selections in addition to traditional", "index files. Use [TT]-select help[tt] for additional information,", "or type 'help' in the selection prompt.", NULL, }; options.setDescription(desc); */ Options &options = _impl->_options; const char **postypes = gmx_ana_poscalc_create_type_enum(true); if (postypes == NULL) { // TODO: Use an out-of-memory exception here GMX_THROW(InternalError("Could not create position calculation enum")); } options.addOption(StringOption("selrpos").enumValue(postypes + 1) .store(&_impl->_rpost).defaultValue(postypes[1]) .description("Selection reference positions")); options.addOption(StringOption("seltype").enumValue(postypes + 1) .store(&_impl->_spost).defaultValue(postypes[1]) .description("Default selection output positions")); GMX_RELEASE_ASSERT(_impl->_debugLevel >= 0 && _impl->_debugLevel <= 4, "Debug level out of range"); options.addOption(StringOption("seldebug").hidden(_impl->_debugLevel == 0) .enumValue(debug_levels) .defaultValue(debug_levels[_impl->_debugLevel]) .storeEnumIndex(&_impl->_debugLevel) .description("Print out selection trees for debugging")); sfree(postypes); return &_impl->_options; }
int CommandLineHelpModule::run(int argc, char *argv[]) { // Add internal topics lazily here. addTopic(HelpTopicPointer(new CommandsHelpTopic(*impl_)), false); const char *const exportFormats[] = { "rst", "completion" }; std::string exportFormat; Options options(NULL, NULL); options.addOption(StringOption("export").store(&exportFormat) .enumValue(exportFormats)); CommandLineParser(&options).parse(&argc, argv); if (!exportFormat.empty()) { ModificationCheckingFileOutputRedirector redirector(impl_->outputRedirector_); const std::unique_ptr<IHelpExport> exporter( impl_->createExporter(exportFormat, &redirector)); impl_->exportHelp(exporter.get()); return 0; } TextOutputStream &outputFile = impl_->outputRedirector_->standardOutput(); TextWriter writer(&outputFile); HelpLinks links(eHelpOutputFormat_Console); initProgramLinks(&links, *impl_); CommandLineHelpContext context(&writer, eHelpOutputFormat_Console, &links, impl_->binaryName_); context.setShowHidden(impl_->bHidden_); if (impl_->moduleOverride_ != NULL) { context.setModuleDisplayName(impl_->programContext_.displayName()); impl_->moduleOverride_->writeHelp(context); return 0; } impl_->context_ = &context; HelpManager helpManager(impl_->rootTopic_, context.writerContext()); try { for (int i = 1; i < argc; ++i) { helpManager.enterTopic(argv[i]); } } catch (const InvalidInputError &ex) { fprintf(stderr, "%s\n", ex.what()); return 2; } helpManager.writeCurrentTopic(); return 0; }
//! \cond internal void initTestUtils(const char *dataPath, const char *tempPath, bool usesMpi, bool usesHardwareDetection, int *argc, char ***argv) { #if !defined NDEBUG && \ !((defined __clang__ || (defined(__GNUC__) && !defined(__ICC) && __GNUC__ == 7)) \ && defined __OPTIMIZE__) gmx_feenableexcept(); #endif const CommandLineProgramContext &context = initForCommandLine(argc, argv); try { if (!usesMpi && gmx_node_num() > 1) { // We cannot continue, since some tests might be using // MPI_COMM_WORLD, which could deadlock if we would only // continue with the master rank here. if (gmx_node_rank() == 0) { fprintf(stderr, "NOTE: You are running %s on %d MPI ranks, " "but it is does not contain MPI-enabled tests. " "The test will now exit.\n", context.programName(), gmx_node_num()); } finalizeForCommandLine(); std::exit(1); } if (usesHardwareDetection) { callAddGlobalTestEnvironment(); } g_testContext = gmx::compat::make_unique<TestProgramContext>(context); setProgramContext(g_testContext.get()); // Use the default finder that does not respect GMXLIB, since the tests // generally can only get confused by a different set of data files. setLibraryFileFinder(nullptr); ::testing::InitGoogleMock(argc, *argv); if (dataPath != nullptr) { TestFileManager::setInputDataDirectory( Path::join(CMAKE_SOURCE_DIR, dataPath)); } if (tempPath != nullptr) { TestFileManager::setGlobalOutputTempDirectory(tempPath); } bool bHelp = false; std::string sourceRoot; Options options; // TODO: A single option that accepts multiple names would be nicer. // Also, we recognize -help, but GTest doesn't, which leads to a bit // unintuitive behavior. options.addOption(BooleanOption("h").store(&bHelp) .description("Print GROMACS-specific unit test options")); options.addOption(BooleanOption("help").store(&bHelp).hidden()); options.addOption(BooleanOption("?").store(&bHelp).hidden()); // TODO: Make this into a FileNameOption (or a DirectoryNameOption). options.addOption(StringOption("src-root").store(&sourceRoot) .description("Override source tree location (for data files)")); // The potential MPI test event listener must be initialized first, // because it should appear in the start of the event listener list, // before other event listeners that may generate test failures // (currently, such an event listener is used by the reference data // framework). if (usesMpi) { initMPIOutput(); } // TODO: Consider removing this option from test binaries that do not need it. initReferenceData(&options); initTestOptions(&options); try { CommandLineParser(&options).parse(argc, *argv); options.finish(); } catch (const UserInputError &) { printHelp(options); throw; } if (bHelp) { printHelp(options); } if (!sourceRoot.empty()) { g_testContext->overrideSourceRoot(sourceRoot); TestFileManager::setInputDataDirectory( Path::join(sourceRoot, dataPath)); } } catch (const std::exception &ex) { printFatalErrorMessage(stderr, ex); int retcode = processExceptionAtExitForCommandLine(ex); // TODO: It could be nice to destroy things in proper order such that // g_testContext would not contain hanging references at this point, // but in practice that should not matter. g_testContext.reset(); std::exit(retcode); } }
//! \cond GMX_TEST_OPTIONS(IntegrationTestOptions, options) { options->addOption(StringOption("max-backup") .store(&IntegrationTestFixture::s_maxBackup) .description("Maximum number of backup files of old test output to write (-1 prevents backups being created)")); }
//! \cond internal void initTestUtils(const char *dataPath, const char *tempPath, int *argc, char ***argv) { #ifndef NDEBUG gmx_feenableexcept(); #endif const CommandLineProgramContext &context = initForCommandLine(argc, argv); try { g_testContext.reset(new TestProgramContext(context)); setProgramContext(g_testContext.get()); // Use the default finder that does not respect GMXLIB, since the tests // generally can only get confused by a different set of data files. setLibraryFileFinder(NULL); ::testing::InitGoogleMock(argc, *argv); if (dataPath != NULL) { TestFileManager::setInputDataDirectory( Path::join(CMAKE_SOURCE_DIR, dataPath)); } if (tempPath != NULL) { TestFileManager::setGlobalOutputTempDirectory(tempPath); } bool bHelp = false; std::string sourceRoot; Options options(NULL, NULL); // TODO: A single option that accepts multiple names would be nicer. // Also, we recognize -help, but GTest doesn't, which leads to a bit // unintuitive behavior. options.addOption(BooleanOption("h").store(&bHelp) .description("Print GROMACS-specific unit test options")); options.addOption(BooleanOption("help").store(&bHelp).hidden()); options.addOption(BooleanOption("?").store(&bHelp).hidden()); // TODO: Make this into a FileNameOption (or a DirectoryNameOption). options.addOption(StringOption("src-root").store(&sourceRoot) .description("Override source tree location (for data files)")); // The potential MPI test event listener must be initialized first, // because it should appear in the start of the event listener list, // before other event listeners that may generate test failures // (currently, such an event listener is used by the reference data // framework). initMPIOutput(); // TODO: Consider removing this option from test binaries that do not need it. initReferenceData(&options); initTestOptions(&options); try { CommandLineParser(&options).parse(argc, *argv); options.finish(); } catch (const UserInputError &) { printHelp(options); throw; } if (bHelp) { printHelp(options); } if (!sourceRoot.empty()) { g_testContext->overrideSourceRoot(sourceRoot); TestFileManager::setInputDataDirectory( Path::join(sourceRoot, dataPath)); } } catch (const std::exception &ex) { printFatalErrorMessage(stderr, ex); int retcode = processExceptionAtExitForCommandLine(ex); // TODO: It could be nice to destroy things in proper order such that // g_testContext would not contain hanging references at this point, // but in practice that should not matter. g_testContext.reset(); std::exit(retcode); } }
void Angle::initOptions(Options *options, TrajectoryAnalysisSettings * /*settings*/) { static const char *const desc[] = { "g_angle computes different types of angles between vectors.", "It supports both vectors defined by two positions and normals of", "planes defined by three positions.", "The z axis or the local normal of a sphere can also be used as", "one of the vectors.", "There are also convenience options 'angle' and 'dihedral' for", "calculating bond angles and dihedrals defined by three/four", "positions.[PAR]", "The type of the angle is specified with [TT]-g1[tt] and [TT]-g2[tt].", "If [TT]-g1[tt] is [TT]angle[tt] or [TT]dihedral[tt], [TT]-g2[tt]", "should not be specified.", "In this case, [TT]-group1[tt] should specify one selection,", "and it should contain triplets or quartets of positions that define", "the angles to be calculated.[PAR]", "If [TT]-g1[tt] is [TT]vector[tt] or [TT]plane[tt], [TT]-group1[tt]", "should specify a selection that has either pairs ([TT]vector[tt])", "or triplets ([TT]plane[tt]) of positions. For vectors, the positions", "set the endpoints of the vector, and for planes, the three positions", "are used to calculate the normal of the plane. In both cases,", "[TT]-g2[tt] specifies the other vector to use (see below).[PAR]", "With [TT]-g2 vector[tt] or [TT]-g2 plane[tt], [TT]-group2[tt] should", "specify another set of vectors. Both selections should specify the", "same number of vectors.[PAR]", "With [TT]-g2 sphnorm[tt], [TT]-group2[tt] should specify a single", "position that is the center of the sphere. The second vector is then", "calculated as the vector from the center to the midpoint of the", "positions specified by [TT]-group1[tt].[PAR]", "With [TT]-g2 z[tt], [TT]-group2[tt] is not necessary, and angles", "between the first vectors and the positive Z axis are calculated.[PAR]", "With [TT]-g2 t0[tt], [TT]-group2[tt] is not necessary, and angles", "are calculated from the vectors as they are in the first frame.[PAR]", "There are two options for output:", "[TT]-oav[tt] writes an xvgr file with the time and the average angle", "for each frame.", "[TT]-oall[tt] writes all the individual angles." /* TODO: Consider if the dump option is necessary and how to best * implement it. "[TT]-od[tt] can be used to dump all the individual angles,", "each on a separate line. This format is better suited for", "further processing, e.g., if angles from multiple runs are needed." */ }; static const char *const cGroup1TypeEnum[] = { "angle", "dihedral", "vector", "plane" }; static const char *const cGroup2TypeEnum[] = { "none", "vector", "plane", "t0", "z", "sphnorm" }; options->setDescription(concatenateStrings(desc)); options->addOption(FileNameOption("oav").filetype(eftPlot).outputFile() .store(&fnAverage_).defaultBasename("angaver") .description("Average angles as a function of time")); options->addOption(FileNameOption("oall").filetype(eftPlot).outputFile() .store(&fnAll_).defaultBasename("angles") .description("All angles as a function of time")); // TODO: Add histogram output. options->addOption(StringOption("g1").enumValue(cGroup1TypeEnum) .defaultEnumIndex(0).store(&g1type_) .description("Type of analysis/first vector group")); options->addOption(StringOption("g2").enumValue(cGroup2TypeEnum) .defaultEnumIndex(0).store(&g2type_) .description("Type of second vector group")); // TODO: Allow multiple angles to be computed in one invocation. // Most of the code already supports it, but requires a solution for // Redmine issue #1010. // TODO: Consider what is the best way to support dynamic selections. // Again, most of the code already supports it, but it needs to be // considered how should -oall work, and additional checks should be added. sel1info_ = options->addOption(SelectionOption("group1") .required().onlyStatic().storeVector(&sel1_) .description("First analysis/vector selection")); sel2info_ = options->addOption(SelectionOption("group2") .onlyStatic().storeVector(&sel2_) .description("Second analysis/vector selection")); }
double numberOrStringOptionChooser(const std::string &category, int index, const std::string &name, bool isNumber, const std::string &title, bool isInteractive, double minimum, double maximum, double step) { double valn = 0.; std::string vals = ""; if(isNumber) NumberOption(GMSH_GET, category.c_str(), index, name.c_str(), valn); else StringOption(GMSH_GET, category.c_str(), index, name.c_str(), vals); int nn = (isInteractive ? 2 : 3); int width = nn * BB + (nn + 1) * WB, height = 2 * BH + 3 * WB; std::string t = title; if(t.empty()) t = (isNumber ? "Number Chooser" : "String Chooser"); Fl_Window *win = new paletteWindow(width, height, false, t.c_str()); win->set_modal(); win->hotspot(win); inputValueFloat *number = 0; Fl_Input *string = 0; if(isNumber){ number = new inputValueFloat(WB, WB, width - 2 * WB, BH); number->value(valn); if(isInteractive){ static opt_data d; d.category = category; d.index = index; d.name = name; number->minimum(minimum); number->maximum(maximum); number->step(step, 1); number->callback(interactive_cb, (void*)&d); number->when(FL_WHEN_RELEASE); } } else{ string = new Fl_Input(WB, WB, width - 2 * WB, BH); string->value(vals.c_str()); } Fl_Button *ok = new Fl_Return_Button (width - nn * BB - nn * WB, 2 * WB + BH, BB, BH, "OK"); Fl_Button *def = new Fl_Button (width - (nn - 1) * BB - (nn - 1) * WB, 2 * WB + BH, BB, BH, "Default"); Fl_Button *cancel = 0; if(!isInteractive) cancel = new Fl_Button (width - BB - WB, 2 * WB + BH, BB, BH, "Cancel"); win->end(); win->show(); if(number) number->take_focus(); if(string) string->take_focus(); bool done = false; while(win->shown()){ if(done) break; Fl::wait(); for (;;) { Fl_Widget* o = Fl::readqueue(); if (!o) break; if (o == win || o == cancel) { done = true; break; } if(o == ok){ if(isNumber){ valn = number->value(); NumberOption(GMSH_SET|GMSH_GUI, category.c_str(), index, name.c_str(), valn); } else{ vals = string->value(); StringOption(GMSH_SET|GMSH_GUI, category.c_str(), index, name.c_str(), vals); } done = true; break; } if(o == def){ if(isNumber){ NumberOption(GMSH_GET_DEFAULT, category.c_str(), index, name.c_str(), valn); number->value(valn); if(isInteractive) number->do_callback(); } else{ StringOption(GMSH_GET_DEFAULT, category.c_str(), index, name.c_str(), vals); string->value(vals.c_str()); } break; } } } delete win; if(isNumber){ NumberOption(GMSH_GET, category.c_str(), index, name.c_str(), valn); return valn; } else return 0.; }
int CommandLineHelpModule::run(int argc, char *argv[]) { // Add internal topics lazily here. addTopic(HelpTopicPointer(new CommandsHelpTopic(*impl_))); const char *const exportFormats[] = { "rst", "completion" }; std::string exportFormat; Options options(NULL, NULL); options.addOption(StringOption("export").store(&exportFormat) .enumValue(exportFormats)); CommandLineParser(&options).parse(&argc, argv); if (!exportFormat.empty()) { boost::scoped_ptr<HelpExportInterface> exporter; if (exportFormat == "rst") { exporter.reset(new HelpExportReStructuredText(*impl_)); } else if (exportFormat == "completion") { exporter.reset(new HelpExportCompletion(*impl_)); } else { GMX_THROW(NotImplementedError("This help format is not implemented")); } impl_->exportHelp(exporter.get()); return 0; } File &outputFile = impl_->outputRedirector_->standardOutput(); HelpLinks links(eHelpOutputFormat_Console); initProgramLinks(&links, *impl_); boost::scoped_ptr<CommandLineHelpContext> context( new CommandLineHelpContext(&outputFile, eHelpOutputFormat_Console, &links)); context->setShowHidden(impl_->bHidden_); if (impl_->moduleOverride_ != NULL) { context->setModuleDisplayName(impl_->programContext_.displayName()); impl_->moduleOverride_->writeHelp(*context); return 0; } impl_->context_ = context.get(); HelpManager helpManager(*impl_->rootTopic_, context->writerContext()); try { for (int i = 1; i < argc; ++i) { helpManager.enterTopic(argv[i]); } } catch (const InvalidInputError &ex) { fprintf(stderr, "%s\n", ex.what()); return 2; } helpManager.writeCurrentTopic(); return 0; }
Options * Angle::initOptions(TrajectoryAnalysisSettings *settings) { static const char *const desc[] = { "g_angle computes different types of angles between vectors.", "It supports both vectors defined by two positions and normals of", "planes defined by three positions.", "The z axis or the local normal of a sphere can also be used as", "one of the vectors.", "There are also convenience options 'angle' and 'dihedral' for", "calculating bond angles and dihedrals defined by three/four", "positions.[PAR]", "The type of the angle is specified with [TT]-g1[tt] and [TT]-g2[tt].", "If [TT]-g1[tt] is [TT]angle[tt] or [TT]dihedral[tt], [TT]-g2[tt]", "should not be specified.", "In this case, one selection is required, and it should contain", "triplets or quartets of positions that define the angles to be", "calculated.", "If [TT]-g1[tt] is not [TT]angle[tt] or [TT]dihedral[tt], [TT]-g2[tt]", "should not be [TT]none[tt], and the two options define two vectors", "for the calculation. For vectors ([TT]vector[tt]), a selection with", "pairs of positions is required, and for planes ([TT]plane[tt]),", "triplets of positions are required.", "If both vectors are specified by positions, the number of vectors", "should be the same in both selections.", "[TT]-g2 sphnorm[tt] requires a reference selection that defines", "the center of the sphere.", "[TT]-g2 z[tt] does not require any selection.[PAR]", "With [TT]-split1[tt], the positions for [TT]-g1[tt] are specified", "using N separate selections with M positions each, instead of the", "default M*N positions in one selection.", "[TT]-split2[tt] does the same for [TT]-g2[tt].[PAR]", "There are two options for output:", "[TT]-o[tt] writes an xvgr file with the time and the average angle", "for each frame.", "With [TT]-all[tt], also the individual angles are written (only", "supported for static selections).", "[TT]-od[tt] can be used to dump all the individual angles,", "each on a separate line. This format is better suited for", "further processing, e.g., if angles from multiple runs are needed.", NULL }; static const char *const cGroup1TypeEnum[] = { "angle", "dihedral", "vector", "plane", NULL }; static const char *const cGroup2TypeEnum[] = { "none", "vector", "plane", "t0", "z", "sphnorm", NULL }; _options.setDescription(desc); _options.addOption(FileNameOption("o").filetype(eftPlot).writeOnly() .store(&_fnAngle).defaultValueIfSet("angle")); _options.addOption(FileNameOption("od").filetype(eftPlot).writeOnly() .store(&_fnDump).defaultValueIfSet("angdump")); _options.addOption(StringOption("g1").enumValue(cGroup1TypeEnum) .defaultEnumIndex(0).store(&_g1type) .description("Type of analysis/first vector group")); _options.addOption(StringOption("g2").enumValue(cGroup2TypeEnum) .defaultEnumIndex(0).store(&_g2type) .description("Type of second vector group")); _options.addOption(BooleanOption("split1").store(&_bSplit1) .description("Each position of first group in separate selection")); _options.addOption(BooleanOption("split2").store(&_bSplit2) .description("Each position of second group in separate selection")); _options.addOption(BooleanOption("multi").store(&_bMulti) .description("Analyze multiple sets of angles/dihedrals")); _options.addOption(BooleanOption("all").store(&_bAll) .description("Print individual angles together with the average")); _options.addOption(BooleanOption("dumpd").store(&_bDumpDist) .description("Write also distances with -od")); _options.addOption(SelectionOption("group1").multiValue().required() .dynamicOnlyWhole().storeVector(&_sel1).getAdjuster(&_sel1Adj) .description("First analysis/vector selection")); _options.addOption(SelectionOption("group2").multiValue() .dynamicOnlyWhole().storeVector(&_sel2).getAdjuster(&_sel2Adj) .description("Second analysis/vector selection")); return &_options; }