The data model controls how you query the data in your ntuple. The ntuples that this project was designed to work with come in basically two types

  1. Fully object oriented. In this case you are likely to have custom objects. There is very little if anything to do here.
  2. Flat related arrays. For example, elePx, elePy, and elePz give the momentum of the electron. So they are related, but in different arrays. Unfortunately, LINQ doesn’t provide an easy way to deal with these in that case. It is possible to adjust the data model to help with this.

The data model does not, of course, change the underlying ntuple – just how you code against it. In the end everything is translated back into simple C++ code.

There are several different things you can do to alter the data model:

  • Group or ungroup variables. For example, instead of elePx, elePy, and elePz, you can access electrons.Px, electrons.Py, and electrons.Pz. The advantage is you can now write something like the following to select pT of all electrons:
    from e in events from ele in events.electrons select Math.Sqrt(ele.elePx*ele.elePx + ele.elePy*ele.elePy)
  • Renaming of variables. Don’t want to type pTANTIKT04TOPOJETS to refer to a jet’s pT? You can rename it to just be referred to as pT.
  • Indirect Array References. Say you have another integer variable called eleTrackIndex which points into a set of arrays that are tracks. Using the XML you can instruct LINQToTTree to recode so you can write the following to select out the Px of the associated track (assuming it has a Px array for tracks, of course!). Note that if eleTrackIndex is a 2D array then you can access a list of tracks associated with an electron!
    from e in events from ele in events.electrons select ele.eleTrackIndex.Px

You can also use these in pretty much any combination – so you can rename an index variable, or the put it in a grouping, etc.

A word of warning: you can definitely cause crashes by messing up the XML file. Unfortunately, since they will likely happen deep inside ROOT, I’m afraid the crashes are unlikely to be obvious. These will be because you’ve walked off the end of an array, etc. In general, the tool that creates the C# file does its best to protect you, but it doesn’t have the complete information from the TTree, so it is quite possible to really screw things up!

The XML Files

There are two XML files that are made. One of them you should almost never touch – the .ntupom. Sometimes there are paths in it that are hard coded and you might have some trouble with them – but rarely should you have to futz with them! The second one, .ntup is the one you can use to effect all the changes discussed on this page.

The second file contains groups of variables. By default the TTree parser tool that you ran to make these files analyzes the TTree and makes a guess as to what variables should belong to together. It then creates groups called group1 and group2, etc.


Each group in the file is labeled group1 and group2, etc. You can modify these to new names as you please (electrons or muons, etc.). This is all that is required to do the grouping.

If one group is too large and you wish to split it – go ahead – just respect the layout and hierarchy of the XML file. You should not, however, move a variable from one group to another. The fact that they are in two different groups implies that they have different numbers of entries in an event. If you move them, and use them, you are likely to run off the end of the array, which will cause a C++ exception to be thrown.

You can also add a comment to the group. Simply add the attribute Comment="Anti Kt4 Topo EM" to the ArrayGroup node.

The infrastructure generates a .NET class for each group. The class name is just the name of the group and the name of the root Tree contactinated. If the tree is called CollectionTree and the group is called Jets, then the class will be called CollectionTreeJets. This can be awkward - use the ClassName="Jet" attribute in the ArrayGroup node to use your own. If you have to refer to this in your code (you probably will) this makes it much more readable!

There is one special group called ungrouped which appears first in the XML file. This contains variable names that either had unique numbers of entries or never had any entries (were always zero). If several of the zero-entry variables belong together you could move them over into a new group, but make sure you know what you are doing. And feel free to move variables from any other group into the ungrouped variable listing!

It is possible to list a variable twice, and the system is quite happy to do it. However, there are some caveats!! For example, make sure that the second group it appears in has the same dimensionality as the variable. You can always repeat a variable in the special ungrouped group.


Each variable entry in the XML file gives you a change to rename.

<VariableInfo NETName="mubcid" TTreeName="mubcid" />

By altering the attribute NETName you can change how you will code against it. Under no circumstances can you alter the TTreeName. This is used as an lookup into the ntupom file and is also expected to be the actual name of the tree in ROOT.


You do this by adding the IndexToGroup attribute to the XML line. Its value is the name of the group that it should be pointing to. For example you could do something like the following

<VariableInfo NETName="jetmuassoc" TTreeName="jetmuassoc" IndexToGroup="group1" />

Now in your C# code when you refer to jetmuassoc you’ll get an object of type group1 (with all of group1’s variables available). It goes without saying that if you do this to a random variable you’ll end up in a bad way as the array lookup will mean nothing!

Adding Intelisense Comments

One of the best features about programming in the Visual Studio IDE is the intelisense – the editor generates a drop down list of method names when you type a “.” or a “->” (in C++ or in C#, etc.). It displays both the possibilities and if you hover for a second it will also display any comments associated with the item.

As of v0.22 LINQtoROOT will generate these comments. Some are generated by it, others are generated automatically:

  • If you want to add a comment to a grouping, in the XML add an attribute to the <ArrayGroup… entry called Comment. Any text you put in this comment will be copied over into the intelisense database used by Visual Studio.
  • If you want to add a comment to any variable name, just add a "Comment” attribute to any VaribleInfo entry. That comment will also be placed in Visual Studio’s intelisense database.

Finally, anytime you rename a variable, LINQtoROOT will put the original name in the comment block so you can easily see what is going on under-the-covers.

Last edited Oct 12, 2011 at 9:08 AM by gwatts, version 7


No comments yet.