Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 27 // Author: Ivana Hrivnacova, 26/08/2022 (ivana@ipno.in2p3.fr) 28 29 #include "G4AnalysisUtilities.hh" 30 31 #include "G4UIdirectory.hh" 32 #include "G4UIcommand.hh" 33 #include "G4UIparameter.hh" 34 #include "G4Tokenizer.hh" 35 36 #include <vector> 37 38 using namespace G4Analysis; 39 40 //_____________________________________________________________________________ 41 template <unsigned int DIM, typename HT> 42 G4THnMessenger<DIM, HT>::G4THnMessenger(G4THnToolsManager<DIM, HT>* manager) 43 : fManager(manager) 44 { 45 CreateDirectory(); 46 47 CreateCmd(); 48 SetCmd(); 49 for (unsigned int idim = 0; idim < DIM; ++idim) { 50 fSetDimensionCmd[idim] = CreateSetBinsCommand(idim); 51 } 52 53 DeleteCmd(); 54 55 CreateSetTitleCommand(); 56 57 auto maxDim = (DIM < kMaxDim) ? DIM + 1 : kMaxDim; 58 for (unsigned int idim = 0; idim < maxDim; ++idim) { 59 fSetAxisCmd[idim] = CreateSetAxisCommand(idim); 60 } 61 62 CreateListCommand(); 63 CreateGetCommand(); 64 CreateGetVectorCommand(); 65 66 // Initialize data 67 for (unsigned int idim = 0; idim < DIM; ++idim) { 68 fTmpId[idim] = G4Analysis::kInvalidId; 69 fTmpBins[idim] = G4HnDimension(); 70 fTmpInfo[idim] = G4HnDimensionInformation(); 71 } 72 } 73 74 // 75 // private functions 76 // 77 78 //_____________________________________________________________________________ 79 template <unsigned int DIM, typename HT> 80 G4String G4THnMessenger<DIM, HT>::GetObjectType() const 81 { 82 return (G4Analysis::IsProfile<HT>()) ? 83 std::to_string(DIM - 1) + "D profile " : std::to_string(DIM) + "D histogram"; 84 } 85 86 //_____________________________________________________________________________ 87 template <unsigned int DIM, typename HT> 88 G4bool G4THnMessenger<DIM, HT>::IsProfileLastDimension(unsigned int idim) const 89 { 90 return (idim == DIM - 1) && (G4Analysis::IsProfile<HT>()); 91 } 92 93 //_____________________________________________________________________________ 94 template <unsigned int DIM, typename HT> 95 std::unique_ptr<G4UIcommand> G4THnMessenger<DIM, HT>::CreateCommand( 96 G4String name, G4String guidance) 97 { 98 G4String fullName = "/analysis/" + G4Analysis::GetHnType<HT>() + "/" + name; 99 G4String fullGuidance = guidance + GetObjectType(); 100 101 auto command = std::make_unique<G4UIcommand>(fullName, this); 102 command->SetGuidance(fullGuidance); 103 104 return command; 105 } 106 107 //_____________________________________________________________________________ 108 template <unsigned int DIM, typename HT> 109 void G4THnMessenger<DIM, HT>::CreateDimensionParameters( 110 unsigned int idim, std::vector<G4UIparameter*>& parameters) const 111 { 112 // Create [nbins], valMin, valMax, valUnit, valFcn, [valBinScheme] parameters. 113 // The parameters in [] are omitted for the last dimension for profiles 114 115 std::string xyz{"xyz"}; 116 std::string axis = xyz.substr(idim, 1); 117 118 if (! IsProfileLastDimension(idim)) { 119 auto parName = axis + "nBins"; 120 auto guidance = 121 std::string("Number of ") + axis + "-bins (default = 100)\n" 122 "Can be reset with /analysis/hn/set command"; 123 124 auto param = new G4UIparameter(parName.c_str(), 'i', false); 125 param->SetGuidance(guidance.c_str()); 126 param->SetDefaultValue(100); 127 parameters.push_back(param); 128 } 129 130 auto parName = axis + "valMin"; 131 auto guidance = 132 std::string("Minimum ") + axis + "-value, expressed in unit (default = 0.)\n" 133 "Can be reset with /analysis/hn/set command"; 134 auto param = new G4UIparameter(parName.c_str(), 'd', false); 135 param->SetGuidance(guidance.c_str()); 136 param->SetDefaultValue(0.); 137 parameters.push_back(param); 138 139 parName = axis + "valMax"; 140 guidance = 141 std::string("Maximum ") + axis + "-value, expressed in unit (default = 1.)\n" 142 "Can be reset with /analysis/hn/set command"; 143 param = new G4UIparameter(parName.c_str(), 'd', false); 144 param->SetGuidance(guidance.c_str()); 145 param->SetDefaultValue(1.); 146 parameters.push_back(param); 147 148 parName = axis + "valUnit"; 149 guidance = 150 std::string("The unit applied to filled ") + axis + "-values and \n" 151 "Can be reset with /analysis/hn/set command"; 152 param = new G4UIparameter(parName.c_str(), 's', true); 153 param->SetGuidance(guidance.c_str()); 154 param->SetDefaultValue("none"); 155 parameters.push_back(param); 156 157 parName = axis + "valFcn"; 158 guidance = 159 std::string("The function applied to filled ") + axis + "-values (log, log10, exp, none).\n" 160 "Note that the unit parameter cannot be omitted in this case,\n" 161 "but none value should be used instead."; 162 param = new G4UIparameter(parName.c_str(), 's', true); 163 param->SetGuidance(guidance.c_str()); 164 param->SetParameterCandidates("log log10 exp none"); 165 param->SetDefaultValue("none"); 166 parameters.push_back(param); 167 168 if (! IsProfileLastDimension(idim)) { 169 parName = axis + "valBinScheme"; 170 guidance = 171 std::string("The binning scheme (linear, log).\n" 172 "Note that the unit and fcn parameters cannot be omitted in this case,\n" 173 "but none value should be used instead."); 174 param = new G4UIparameter(parName.c_str(), 's', true); 175 param->SetGuidance(guidance.c_str()); 176 param->SetParameterCandidates("linear log"); 177 param->SetDefaultValue("linear"); 178 parameters.push_back(param); 179 } 180 } 181 182 //_____________________________________________________________________________ 183 template <unsigned int DIM, typename HT> 184 void G4THnMessenger<DIM, HT>::AddIdParameter(G4UIcommand& command) 185 { 186 // add parameter 187 auto htId = new G4UIparameter("id", 'i', false); 188 htId->SetGuidance("Histogram id"); 189 htId->SetParameterRange("id>=0"); 190 command.SetParameter(htId); 191 } 192 193 //_____________________________________________________________________________ 194 template <unsigned int DIM, typename HT> 195 G4String G4THnMessenger<DIM, HT>::GetTAddress(G4int id) const 196 { 197 auto ht = fManager->GetT(id); 198 if ( ht != nullptr ) { 199 std::ostringstream os; 200 os << static_cast<void*>(ht); 201 return os.str(); 202 } 203 return {}; 204 } 205 206 //_____________________________________________________________________________ 207 template <unsigned int DIM, typename HT> 208 G4String G4THnMessenger<DIM, HT>::GetTVectorAddress() const 209 { 210 auto htVector = fManager->GetTVector(); 211 if ( htVector != nullptr ) { 212 std::ostringstream os; 213 os << static_cast<void*>(htVector); 214 return os.str(); 215 } 216 return {}; 217 } 218 219 //_____________________________________________________________________________ 220 template <unsigned int DIM, typename HT> 221 void G4THnMessenger<DIM, HT>::CreateDirectory() const 222 { 223 G4String dirName = "/analysis/" + G4Analysis::GetHnType<HT>() + "/"; 224 G4String guidance = GetObjectType() + " control"; 225 226 auto directory = std::make_unique<G4UIdirectory>(dirName); 227 directory->SetGuidance(guidance.c_str()); 228 } 229 230 //_____________________________________________________________________________ 231 template <unsigned int DIM, typename HT> 232 void G4THnMessenger<DIM, HT>::CreateCmd() 233 { 234 fCreateCmd = CreateCommand("create", "Create "); 235 fCreateCmd->AvailableForStates(G4State_PreInit, G4State_Idle); 236 237 auto htName = new G4UIparameter("name", 's', false); 238 htName->SetGuidance("Histogram name (label)"); 239 fCreateCmd->SetParameter(htName); 240 241 auto htTitle = new G4UIparameter("title", 's', false); 242 htTitle->SetGuidance("Histogram title"); 243 fCreateCmd->SetParameter(htTitle); 244 245 std::vector<G4UIparameter*> parameters; 246 for (unsigned int idim = 0; idim < DIM; ++idim) { 247 CreateDimensionParameters(idim, parameters); 248 for (size_t ipar = 0; ipar < parameters.size(); ++ipar) { 249 // the first three parameters can be omittes in create command 250 if (ipar < 3) parameters[ipar]->SetOmittable(true); 251 fCreateCmd->SetParameter(parameters[ipar]); 252 } 253 parameters.clear(); 254 } 255 } 256 257 //_____________________________________________________________________________ 258 template <unsigned int DIM, typename HT> 259 void G4THnMessenger<DIM, HT>::SetCmd() 260 { 261 fSetCmd = CreateCommand("set", "Set "); 262 fSetCmd->AvailableForStates(G4State_PreInit, G4State_Idle); 263 264 // Add Id parameter 265 AddIdParameter(*fSetCmd); 266 267 // Update guidance 268 fSetCmd->SetGuidance("\n nbins; valMin; valMax; unit; function; binScheme"); 269 270 std::vector<G4UIparameter*> parameters; 271 for (unsigned int idim = 0; idim < DIM; ++idim) { 272 CreateDimensionParameters(idim, parameters); 273 for (auto parameter: parameters) { 274 fSetCmd->SetParameter(parameter); 275 } 276 parameters.clear(); 277 } 278 } 279 280 //_____________________________________________________________________________ 281 template <unsigned int DIM, typename HT> 282 void G4THnMessenger<DIM, HT>::DeleteCmd() 283 { 284 fDeleteCmd = CreateCommand("delete", "Delete "); 285 fDeleteCmd->AvailableForStates(G4State_PreInit, G4State_Idle); 286 287 // Add Id parameter 288 AddIdParameter(*fDeleteCmd); 289 290 auto parKeepSetting = new G4UIparameter("keepSetting", 'b', true); 291 G4String guidance = 292 "If set true, activation, plotting, etc. options will be kept\n" 293 "and applied when a new object with the same id is created."; 294 parKeepSetting->SetGuidance(guidance.c_str()); 295 parKeepSetting->SetDefaultValue("false"); 296 fDeleteCmd->SetParameter(parKeepSetting); 297 } 298 299 //_____________________________________________________________________________ 300 template <unsigned int DIM, typename HT> 301 std::unique_ptr<G4UIcommand> 302 G4THnMessenger<DIM, HT>::CreateSetBinsCommand(unsigned int idim) 303 { 304 G4String xyz{"XYZ"}; 305 auto axis = xyz.substr(idim, 1); 306 307 auto command = CreateCommand("set" + axis, "Set " + axis + " parameters for the "); 308 command->AvailableForStates(G4State_PreInit, G4State_Idle); 309 310 // Add Id parameter 311 AddIdParameter(*command); 312 313 // Update guidance 314 G4String guidance = 315 "\n nAXISbins; AXISvalMin; AXISvalMax; AXISunit; AXISfunction; AXISbinScheme"; 316 // update AXIS with xyz 317 std::string::size_type n = 0; 318 std::string ts{"AXIS"}; 319 while ( ( n = guidance.find(ts, n)) != std::string::npos ) { 320 guidance.replace(n, ts.size(), axis); 321 n += ts.size(); 322 } 323 command->SetGuidance(guidance); 324 325 std::vector<G4UIparameter*> parameters; 326 CreateDimensionParameters(idim, parameters); 327 for (auto parameter: parameters) { 328 command->SetParameter(parameter); 329 } 330 331 return command; 332 } 333 334 //_____________________________________________________________________________ 335 template <unsigned int DIM, typename HT> 336 void G4THnMessenger<DIM, HT>::CreateSetTitleCommand() 337 { 338 fSetTitleCmd = CreateCommand("setTitle", "Set title for the "); 339 fSetTitleCmd->AvailableForStates(G4State_PreInit, G4State_Idle); 340 341 // Add Id parameter 342 AddIdParameter(*fSetTitleCmd); 343 344 auto parTitle = new G4UIparameter("title", 's', true); 345 auto guidance = GetObjectType() + " title"; 346 parTitle->SetGuidance(guidance.c_str()); 347 parTitle->SetDefaultValue("none"); 348 fSetTitleCmd->SetParameter(parTitle); 349 } 350 351 //_____________________________________________________________________________ 352 template <unsigned int DIM, typename HT> 353 std::unique_ptr<G4UIcommand> 354 G4THnMessenger<DIM, HT>::CreateSetAxisCommand(unsigned int idim) 355 { 356 G4String xyz{"XYZ"}; 357 auto axis = xyz.substr(idim, 1); 358 359 G4String commandName = "set" + axis + "axis"; 360 G4String guidance = "Set " + axis + "-axis title for the ";; 361 362 auto command = CreateCommand(std::move(commandName), guidance); 363 command->AvailableForStates(G4State_PreInit, G4State_Idle); 364 365 // Add Id parameter 366 AddIdParameter(*command); 367 368 auto parAxis = new G4UIparameter("axis", 's', false); 369 guidance = GetObjectType() + " " + std::move(axis) + "-axis title"; 370 parAxis->SetGuidance(guidance.c_str()); 371 command->SetParameter(parAxis); 372 373 return command; 374 } 375 376 //_____________________________________________________________________________ 377 template <unsigned int DIM, typename HT> 378 void G4THnMessenger<DIM, HT>::CreateListCommand() 379 { 380 fListCmd = CreateCommand("list", "List all/activate "); 381 fListCmd->AvailableForStates(G4State_Idle, G4State_GeomClosed, G4State_EventProc); 382 383 auto parOnlyIfActive = new G4UIparameter("onlyIfActive", 'b', true); 384 parOnlyIfActive->SetGuidance("Option whether to list only active objects"); 385 parOnlyIfActive->SetDefaultValue("true"); 386 fListCmd->SetParameter(parOnlyIfActive); 387 } 388 389 //_____________________________________________________________________________ 390 template <unsigned int DIM, typename HT> 391 void G4THnMessenger<DIM, HT>::CreateGetCommand() 392 { 393 fGetTCmd = CreateCommand("get", "Get the address of the "); 394 fGetTCmd->SetGuidance( "This command is only for Geant4 internal use."); 395 fGetTCmd->AvailableForStates(G4State_Idle, G4State_GeomClosed, G4State_EventProc); 396 397 // Add Id parameter 398 AddIdParameter(*fGetTCmd); 399 } 400 401 //_____________________________________________________________________________ 402 template <unsigned int DIM, typename HT> 403 void G4THnMessenger<DIM, HT>::CreateGetVectorCommand() 404 { 405 fGetTVectorCmd = CreateCommand("getVector", "Get the address of the vector of the "); 406 fGetTVectorCmd->SetGuidance( "This command is only for Geant4 internal use."); 407 fGetTVectorCmd->AvailableForStates(G4State_Idle, G4State_GeomClosed, G4State_EventProc); 408 } 409 410 //_____________________________________________________________________________ 411 template <unsigned int DIM, typename HT> 412 void G4THnMessenger<DIM, HT>::GetBinData( 413 unsigned int idim, G4int& counter, const std::vector<G4String>& parameters, 414 G4HnDimension& bins) const 415 { 416 G4int nbins = (! IsProfileLastDimension(idim)) ? 417 G4UIcommand::ConvertToInt(parameters[counter++]) : 0; 418 419 bins = {nbins, 420 G4UIcommand::ConvertToDouble(parameters[counter]), 421 G4UIcommand::ConvertToDouble(parameters[counter + 1])}; 422 counter += 2; 423 } 424 425 //_____________________________________________________________________________ 426 template <unsigned int DIM, typename HT> 427 void G4THnMessenger<DIM, HT>::GetBinInfoData( 428 unsigned int idim, G4int& counter, const std::vector<G4String>& parameters, 429 G4HnDimension& bins, G4HnDimensionInformation& info) const 430 { 431 // get bin data (this will shift the counter for hnInfo data) 432 GetBinData(idim, counter, parameters, bins); 433 434 // get dimension information data 435 if (! IsProfileLastDimension(idim)) { 436 info = {parameters[counter], parameters[counter + 1], parameters[counter + 2]}; 437 counter += 3; 438 } 439 else { 440 info = {parameters[counter], parameters[counter + 1]}; 441 counter += 2; 442 } 443 444 // apply unit to minValue and maxValue 445 bins.fMinValue *= info.fUnit; 446 bins.fMaxValue *= info.fUnit; 447 } 448 449 //_____________________________________________________________________________ 450 template <unsigned int DIM, typename HT> 451 void G4THnMessenger<DIM, HT>::GetData( 452 G4int& counter, const std::vector<G4String>& parameters, 453 std::array<G4HnDimension, DIM>& bins, 454 std::array<G4HnDimensionInformation, DIM>& info) const 455 { 456 for (unsigned int idim = 0; idim < DIM; ++idim) { 457 // get bin data (this will shift the counter for hnInfo data) 458 GetBinInfoData(idim, counter, parameters, bins[idim], info[idim]); 459 } 460 } 461 462 // 463 // public functions 464 // 465 466 //_____________________________________________________________________________ 467 template <unsigned int DIM, typename HT> 468 G4String G4THnMessenger<DIM, HT>::GetCurrentValue (G4UIcommand* command) 469 { 470 if ( command == fGetTCmd.get() ) return fTValue; 471 472 if ( command == fGetTVectorCmd.get() ) return fTVectorValue; 473 474 return ""; 475 } 476 477 //_____________________________________________________________________________ 478 template <unsigned int DIM, typename HT> 479 void G4THnMessenger<DIM, HT>::SetNewValue(G4UIcommand* command, G4String newValues) 480 { 481 // tokenize parameters in a vector 482 std::vector<G4String> parameters; 483 G4Analysis::Tokenize(newValues, parameters); 484 // check consistency 485 if ( parameters.size() != command->GetParameterEntries() ) { 486 // Should never happen but let's check anyway for consistency 487 G4Analysis::Warn( 488 "Got wrong number of \"" + command->GetCommandName() + 489 "\" parameters: " + to_string(parameters.size()) + 490 " instead of " + to_string(command->GetParameterEntries()) + " expected", 491 fkClass, "WarnAboutParameters"); 492 return; 493 } 494 495 std::array<G4HnDimension, DIM> bins; 496 std::array<G4HnDimensionInformation, DIM> info; 497 498 if ( command == fCreateCmd.get() ) { 499 auto counter = 0; 500 const auto& name = parameters[counter++]; 501 const auto& title = parameters[counter++]; 502 GetData(counter, parameters, bins, info); 503 fManager->Create(name, title, bins, info); 504 return; 505 } 506 507 if ( command == fSetCmd.get() ) { 508 auto counter = 0; 509 const auto& id = G4UIcommand::ConvertToInt(parameters[counter++]); 510 GetData(counter, parameters, bins, info); 511 fManager->Set(id, bins, info); 512 return; 513 } 514 515 if ( command == fDeleteCmd.get() ) { 516 auto counter = 0; 517 const auto& id = G4UIcommand::ConvertToInt(parameters[counter++]); 518 const auto& keepSetting = G4UIcommand::ConvertToBool(parameters[counter++]); 519 fManager->Delete(id, keepSetting); 520 return; 521 } 522 523 if ( command == fSetTitleCmd.get() ) { 524 auto counter = 0; 525 const auto& id = G4UIcommand::ConvertToInt(parameters[counter++]); 526 const auto& title = parameters[counter++]; 527 fManager->SetTitle(id, title); 528 return; 529 } 530 531 for (unsigned int idim = 0; idim < DIM; ++idim) { 532 if ( command == fSetDimensionCmd[idim].get() ) { 533 auto counter = 0; 534 fTmpId[idim] = G4UIcommand::ConvertToInt(parameters[counter++]); 535 GetBinInfoData(idim, counter, parameters, fTmpBins[idim], fTmpInfo[idim]); 536 537 if ( DIM > 1 && idim > 0) { 538 // the setX, setY, setZ must be apply consequently 539 if (fTmpId[idim - 1] != fTmpId[idim]) { 540 G4Analysis::Warn( 541 "Command setX, setY, setZ must be called successively in this order.\n" 542 "Command was ignored.", fkClass, "SetNewValue"); 543 return; 544 } 545 } 546 if ( idim == DIM - 1) { 547 // Apply parameters when all dimensions are set 548 fManager->Set(fTmpId[idim], fTmpBins, fTmpInfo); 549 return; 550 } 551 } 552 } 553 554 if ( command == fSetTitleCmd.get() ) { 555 auto counter = 0; 556 const auto& id = G4UIcommand::ConvertToInt(parameters[counter++]); 557 const auto& title = parameters[counter++]; 558 fManager->SetTitle(id, title); 559 return; 560 } 561 562 auto maxDim = (DIM < kMaxDim) ? DIM + 1 : kMaxDim; 563 for (unsigned int idim = 0; idim < maxDim; ++idim) { 564 if ( command == fSetAxisCmd[idim].get() ) { 565 auto counter = 0; 566 const auto& id = G4UIcommand::ConvertToInt(parameters[counter++]); 567 const auto& axisTitle = parameters[counter++]; 568 fManager->SetAxisTitle(idim, id, axisTitle); 569 return; 570 } 571 } 572 573 if ( command == fListCmd.get() ) { 574 auto onlyIfActive = G4UIcommand::ConvertToBool(parameters[0]); 575 fManager->List(G4cout, onlyIfActive); 576 return; 577 } 578 579 if ( command == fGetTCmd.get() ) { 580 const auto& id = G4UIcommand::ConvertToInt(newValues); 581 fTValue = GetTAddress(id); 582 return; 583 } 584 585 if ( command == fGetTVectorCmd.get() ) { 586 fTVectorValue = GetTVectorAddress(); 587 return; 588 } 589 } 590