1313// / \brief Implementation of the MaterialManager class
1414
1515#include " DetectorsBase/MaterialManager.h"
16+ #include " DetectorsBase/MaterialManagerParam.h"
1617#include " TVirtualMC.h"
1718#include " TString.h" // for TString
1819#include < TGeoMedium.h>
2627#endif
2728#include < cassert>
2829#include < set>
30+ #include " rapidjson/document.h"
31+ #include " rapidjson/istreamwrapper.h"
32+ #include " rapidjson/ostreamwrapper.h"
33+ #include " rapidjson/prettywriter.h"
2934
3035using namespace o2 ::base;
36+ namespace rj = rapidjson;
37+
38+ namespace
39+ {
40+ // / helper to read/write cuts and processes from/to JSON
41+ template <typename K, typename V>
42+ void writeSingleJSONParamBatch (std::unordered_map<K, const char *> const & idToName, std::map<K, V> const & valMap, V defaultValue, rapidjson::Value& parent, rapidjson::Document::AllocatorType& a)
43+ {
44+ for (auto & itName : idToName) {
45+ auto itVal = valMap.find (itName.first );
46+ if (itVal != valMap.end ()) {
47+ parent.AddMember (rj::Value (itName.second , std::strlen (itName.second ), a), rj::Value (itVal->second ), a);
48+ continue ;
49+ }
50+ parent.AddMember (rj::Value (itName.second , std::strlen (itName.second ), a), rj::Value (defaultValue), a);
51+ }
52+ }
53+
54+ // / specific names of keys wo expect and write in cut and process JSON files
55+ static constexpr const char * jsonKeyID = " local_id" ;
56+ static constexpr const char * jsonKeyIDGlobal = " global_id" ;
57+ static constexpr const char * jsonKeyDefault = " default" ;
58+ static constexpr const char * jsonKeyCuts = " cuts" ;
59+ static constexpr const char * jsonKeyProcesses = " processes" ;
60+ static constexpr const char * jsonKeyEnableSpecialCuts = " enableSpecialCuts" ;
61+ static constexpr const char * jsonKeyEnableSpecialProcesses = " enableSpecialProcesses" ;
62+ } // namespace
3163
3264const std::unordered_map<EProc, const char *> MaterialManager::mProcessIDToName = {
3365 {EProc::kPAIR , " PAIR" },
@@ -178,12 +210,16 @@ void MaterialManager::Cut(ESpecial special, int globalindex, ECut cut, Float_t v
178210 return ;
179211 }
180212 if (special == ESpecial::kFALSE ) {
181- mDefaultCutMap [cut] = val;
213+ auto ins = mDefaultCutMap .insert ({cut, val});
214+ if (ins.second ) {
215+ TVirtualMC::GetMC ()->SetCut (it->second , val);
216+ }
182217 // / Explicit template definition to cover this which differs from global cut setting
183- TVirtualMC::GetMC ()->SetCut (it->second , val);
184218 } else if (mApplySpecialCuts ) {
185- mMediumCutMap [globalindex][cut] = val;
186- TVirtualMC::GetMC ()->Gstpar (globalindex, it->second , val);
219+ auto ins = mMediumCutMap [globalindex].insert ({cut, val});
220+ if (ins.second ) {
221+ TVirtualMC::GetMC ()->Gstpar (globalindex, it->second , val);
222+ }
187223 }
188224}
189225
@@ -198,12 +234,16 @@ void MaterialManager::Process(ESpecial special, int globalindex, EProc process,
198234 return ;
199235 }
200236 if (special == ESpecial::kFALSE ) {
201- mDefaultProcessMap [process] = val;
237+ auto ins = mDefaultProcessMap .insert ({process, val});
238+ if (ins.second ) {
239+ TVirtualMC::GetMC ()->SetProcess (it->second , val);
240+ }
202241 // / Explicit template definition to cover this which differs from global process setting
203- TVirtualMC::GetMC ()->SetProcess (it->second , val);
204242 } else if (mApplySpecialProcesses ) {
205- mMediumProcessMap [globalindex][process] = val;
206- TVirtualMC::GetMC ()->Gstpar (globalindex, it->second , val);
243+ auto ins = mMediumProcessMap [globalindex].insert ({process, val});
244+ if (ins.second ) {
245+ TVirtualMC::GetMC ()->Gstpar (globalindex, it->second , val);
246+ }
207247 }
208248}
209249
@@ -326,6 +366,169 @@ TGeoMedium* MaterialManager::getTGeoMedium(const char* mediumname)
326366 return med;
327367}
328368
369+ void MaterialManager::loadCutsAndProcessesFromJSON (ESpecial special, std::string const & filename)
370+ {
371+ const std::string filenameIn = filename.empty () ? o2::MaterialManagerParam::Instance ().inputFile : filename;
372+ if (filenameIn.empty ()) {
373+ return ;
374+ }
375+ std::ifstream is (filenameIn);
376+ if (!is.is_open ()) {
377+ LOG (error) << " Cannot open file " << filenameIn;
378+ return ;
379+ }
380+ auto digestCutsFromJSON = [this ](int globalindex, rj::Value& cuts) {
381+ auto special = globalindex < 0 ? ESpecial::kFALSE : ESpecial::kTRUE ;
382+ for (auto & cut : cuts.GetObject ()) {
383+ auto name = cut.name .GetString ();
384+ bool found = false ;
385+ for (auto & cn : mCutIDToName ) {
386+ if (std::strcmp (name, cn.second ) == 0 ) {
387+ Cut (special, globalindex, cn.first , cut.value .GetFloat ());
388+ found = true ;
389+ }
390+ }
391+ if (!found) {
392+ LOG (warn) << " Unknown cut parameter " << name;
393+ }
394+ }
395+ };
396+ auto digestProcessesFromJSON = [this ](int globalindex, rj::Value& processes) {
397+ auto special = globalindex < 0 ? ESpecial::kFALSE : ESpecial::kTRUE ;
398+ for (auto & proc : processes.GetObject ()) {
399+ auto name = proc.name .GetString ();
400+ for (auto & pn : mProcessIDToName ) {
401+ if (std::strcmp (name, pn.second ) == 0 ) {
402+ Process (special, globalindex, pn.first , proc.value .GetInt ());
403+ }
404+ }
405+ }
406+ };
407+
408+ rj::IStreamWrapper isw (is);
409+ rj::Document d;
410+ d.ParseStream (isw);
411+
412+ if (special == ESpecial::kFALSE && d.HasMember (jsonKeyDefault)) {
413+ // defaults
414+ auto & defaultParams = d[jsonKeyDefault];
415+ if (defaultParams.HasMember (jsonKeyCuts)) {
416+ digestCutsFromJSON (-1 , defaultParams[jsonKeyCuts]);
417+ }
418+ if (defaultParams.HasMember (jsonKeyProcesses)) {
419+ digestProcessesFromJSON (-1 , defaultParams[jsonKeyProcesses]);
420+ }
421+ } else if (special == ESpecial::kTRUE ) {
422+ // read whether to apply special cuts and processes at all
423+ if (d.HasMember (jsonKeyEnableSpecialCuts)) {
424+ enableSpecialCuts (d[jsonKeyEnableSpecialCuts].GetBool ());
425+ }
426+ if (d.HasMember (jsonKeyEnableSpecialProcesses)) {
427+ enableSpecialProcesses (d[jsonKeyEnableSpecialProcesses].GetBool ());
428+ }
429+ // special
430+ for (auto & m : d.GetObject ()) {
431+ if (m.name .GetString ()[0 ] == ' \0 ' || !m.value .IsArray ()) {
432+ // do not parse anything with empty key, these at the most meant to be comments
433+ continue ;
434+ }
435+ for (auto & batch : m.value .GetArray ()) {
436+ if (std::strcmp (m.name .GetString (), jsonKeyDefault) == 0 ) {
437+ // don't do defaults here
438+ continue ;
439+ }
440+ // set via their global indices
441+ auto index = getMediumID (m.name .GetString (), batch[jsonKeyID].GetInt ());
442+ if (index < 0 ) {
443+ continue ;
444+ }
445+ if (batch.HasMember (jsonKeyCuts)) {
446+ digestCutsFromJSON (index, batch[jsonKeyCuts]);
447+ }
448+ if (batch.HasMember (jsonKeyProcesses)) {
449+ digestProcessesFromJSON (index, batch[jsonKeyProcesses]);
450+ }
451+ }
452+ }
453+ }
454+ }
455+
456+ void MaterialManager::writeCutsAndProcessesToJSON (std::string const & filename)
457+ {
458+ const std::string filenameOut = filename.empty () ? o2::MaterialManagerParam::Instance ().outputFile : filename;
459+ if (filenameOut.empty ()) {
460+ return ;
461+ }
462+
463+ // write parameters as global AND module specific
464+ std::ofstream os (filenameOut);
465+ if (!os.is_open ()) {
466+ LOG (error) << " Cannot create file " << filenameOut;
467+ return ;
468+ }
469+
470+ rj::Document d;
471+ rj::Document::AllocatorType& a = d.GetAllocator ();
472+ d.SetObject ();
473+
474+ // add each local medium with params per module
475+ for (auto & itMed : mMediumMap ) {
476+ // prepare array for module
477+ rj::Value toAdd (rj::kArrayType );
478+ // extract each medium's local and global index
479+ for (auto & locToGlob : itMed.second ) {
480+ auto globalindex = locToGlob.second ;
481+ auto itCut = mMediumCutMap .find (globalindex);
482+ auto itProc = mMediumProcessMap .find (globalindex);
483+ // prepare a batch summarising localID, globaldID, cuts and processes
484+ rj::Value oLoc (rj::kObjectType );
485+ // IDs
486+ oLoc.AddMember (rj::Value (jsonKeyID, std::strlen (jsonKeyID), a), rj::Value (locToGlob.first ), a);
487+ oLoc.AddMember (rj::Value (jsonKeyIDGlobal, std::strlen (jsonKeyIDGlobal)), rj::Value (locToGlob.second ), a);
488+ // add medium and material name
489+ auto mediumIt = mTGeoMediumMap .find ({itMed.first , locToGlob.first });
490+ const char * medName = mediumIt->second ->GetName ();
491+ const char * matName = mediumIt->second ->GetMaterial ()->GetName ();
492+ // not using variables for key names cause they are only written for info but not read
493+ oLoc.AddMember (rj::Value (" medium_name" , 11 , a), rj::Value (medName, std::strlen (medName), a), a);
494+ oLoc.AddMember (rj::Value (" material_name" , 13 , a), rj::Value (matName, std::strlen (matName), a), a);
495+ // prepare for cuts
496+ if (itCut != mMediumCutMap .end ()) {
497+ rj::Value cutMap (rj::kObjectType );
498+ writeSingleJSONParamBatch (mCutIDToName , itCut->second , -1 .f , cutMap, a);
499+ oLoc.AddMember (rj::Value (jsonKeyCuts, std::strlen (jsonKeyCuts), a), cutMap, a);
500+ }
501+ // prepare for processes
502+ if (itProc != mMediumProcessMap .end ()) {
503+ rj::Value procMap (rj::kObjectType );
504+ writeSingleJSONParamBatch (mProcessIDToName , itProc->second , -1 , procMap, a);
505+ oLoc.AddMember (rj::Value (jsonKeyProcesses, std::strlen (jsonKeyProcesses), a), procMap, a);
506+ }
507+ // append this medium to module array
508+ toAdd.PushBack (oLoc, a);
509+ }
510+ // append the entire module array
511+ d.AddMember (rj::Value (itMed.first .c_str (), itMed.first .size (), a), toAdd, a);
512+ }
513+ // also add default parameters
514+ rj::Value cutMapDef (rj::kObjectType );
515+ rj::Value procMapDef (rj::kObjectType );
516+ writeSingleJSONParamBatch (mCutIDToName , mDefaultCutMap , -1 .f , cutMapDef, a);
517+ writeSingleJSONParamBatch (mProcessIDToName , mDefaultProcessMap , -1 , procMapDef, a);
518+ rj::Value defaultParams (rj::kObjectType );
519+ defaultParams.AddMember (rj::Value (jsonKeyCuts, std::strlen (jsonKeyCuts), a), cutMapDef, a);
520+ defaultParams.AddMember (rj::Value (jsonKeyProcesses, std::strlen (jsonKeyProcesses), a), procMapDef, a);
521+ d.AddMember (rj::Value (jsonKeyDefault, std::strlen (jsonKeyDefault), a), defaultParams, a);
522+
523+ d.AddMember (rj::Value (jsonKeyEnableSpecialCuts, std::strlen (jsonKeyEnableSpecialCuts), a), rj::Value (mApplySpecialCuts ), a);
524+ d.AddMember (rj::Value (jsonKeyEnableSpecialProcesses, std::strlen (jsonKeyEnableSpecialProcesses), a), rj::Value (mApplySpecialProcesses ), a);
525+ // now write to file
526+ rj::OStreamWrapper osw (os);
527+ rj::PrettyWriter<rj::OStreamWrapper> writer (osw);
528+ writer.SetIndent (' ' , 2 );
529+ d.Accept (writer);
530+ }
531+
329532void MaterialManager::loadCutsAndProcessesFromFile (const char * modname, const char * filename)
330533{
331534 // Implementation of a method to set cuts and processes as done in AliRoot.
@@ -446,6 +649,8 @@ void MaterialManager::SpecialProcess(const char* modname, int localindex, EProc
446649 int globalindex = getMediumID (modname, localindex);
447650 if (globalindex != -1 ) {
448651 Process (ESpecial::kTRUE , globalindex, parID, val);
652+ } else {
653+ LOG (warn) << " SpecialProcess: NO GLOBALINDEX FOUND FOR " << modname << " " << localindex;
449654 }
450655}
451656
0 commit comments