Is there something like a vector of TiXmlElements?

Hello everyone,

is it possible to have something like a vector consisting of several TiXmlElements?

I am currently working on the TRestRawVetoAnalysisProcess and would like to define several veto groups in the rml-file like for example:

<vetoGroup name="top"    signalIDs="1,2,3" />
<vetoGroup name="bottom" signalIDs="4,5,6" />
...

To read them from the file, I use something like

TiXmlElement* vetoGroup1 = GetElementWithName("vetoGroup", "top");
TiXmlElement* vetoGroup2 = GetElementWithName("vetoGroup", "bottom");
... 

To read the parameters from the elements like here signalIDs, I cannot use an iteration, but have to write a block with GetFieldValue... for each TiXmlElement.
It would be better to have something like

vector<TiXmlElement> vetoGroup;
...
vetoGroup[0] = GetElementWithName("vetoGroup", "top");
...

Like this, it doesn’t work, but is there a way to get similar results?
It is not a critical issue, but it would improve the readability of the code and I could make it more “dynamic”.

Hi Konrad,

the problem of this implementation is that it seems you need to know the names of the vetos beforehand. You should let the user define those names.

See for example TRestGeant4Metadata when we extract the activeVolume key.

    TiXmlElement* volumeDefinition = GetElement("activeVolume", storageDefinition);
 1000     while (volumeDefinition != NULL) {
 1001         Double_t chance = StringToDouble(GetFieldValue("chance", volumeDefinition));
 1002         TString name = GetFieldValue("name", volumeDefinition);
 1003         // first we verify its in the list of valid volumes
 1004         ....
 1012         }
 1013         volumeDefinition = GetNextElement(volumeDefinition);
 1014     }
 1015 

To do your code more generic you should do something similar with your vetoGroup and inside the loop for each vetoEntry fill for example a std::map<string, std::vector<int>> each element of the map containing the name of a VETO and its signal ids.

This is to follow the TRestMetadata philosophy. You extract the information from the RML and place it in data members at the TRestXXX class that will be then stored inside the ROOT file.

In the approach I propose, may be other approaches with different data structures, you would need to define a unique metadata member.

std::map<string,std::vector<int>> fVetoGroup;

or

using namespace std;
map<string,vector<int>> fVetoGroup;

Each element would be filled by each iteration in the previous loop.

The metadata member should be implemented as output at PrintMetadata method. So that when we do: vetoProcess->PrintMetadata() we identify the veto groups that were defined.

Then, when you write the object to the ROOT file, your fVetoGroup member will be saved to disk when we do vetoProcess->Write(). This is done automatically by restManager when the process belongs to a data chain.

When loading using restRoot File.root the process will appear as md0_XX, and it should print out the vetos you defined in the RML.

Hope that helps. Regarding code simplification. Not sure if it can be improved. But once you get used the code is clear enough.

Later when implementing ProcessEvent you will need to loop on the map object and generate an observable name.

map<string, vector<int>>::iterator it;
for (it = fVetoGroup.begin(); it != fVetoGroup.end(); it++)
{

string obsAmpName = it->first + "_amplitude";
string obsTimeName = it->first + "_peakTime";


...


SetObservableValue( obsAmpName, xxx);

SetObservableValue( obsAmpName, yyy);

}

Where xxx and yyy is the calculated value for the corresponding VETO group. Which in fact could be just a single signal.

Hi Javier,
thanks, that helps a lot! It was bothering me too that I had to fix the veto group names in the code. I will try the approach as you suggested.

1 Like