These instructions are geared towards feature in version 0.41 of the tool.

The goal for this project’s start up is about a minute from a root file to using this library to make plots once the basic tools are installed. Sadly, I am not there yet.

Installation

There are several bits that must be installed on your machine in order to use this library:

  • Visual Studio 2010 to get the C++ and C# compilers (and a decent editing and debugging environment).
    • I have never tested the free versions of the tools (the Express versions), but presumably all the bits are there.
    • You can skip all the extra stuff (like Office development tools, etc.)
  • ROOT
    • What version you install is up to you, but you have to make sure that the version is supported by these tools (e.g. 5.28 or 5.30, for example). I do my best to keep up to date with what the ROOT team releases, but I’m sometimes a minor update behind. Sorry! Use nuget to see the list (see below).
    • Generally I install it using the installer package (the msi). It will put it in a place that is easily discoverable by this library and you'll not have to do extra setup.
  • Configure the Visual Stuido to use nuget, the open source library package manager for Windows. Add the ROOT.NET package feed to the list of feeds to make the the LINQtoROOT library easily installable.
    • Follow the links on the nuget website to install the nuget package manager.
    • To add the ROOT.NET package feed, from the IDE's menu select Tools -> Options and then select "Package Manager" –> Package Sources to add a new source. The URL for the package source is http://deeptalk.phys.washington.edu/rootNuGet/nuget. The feed can be called anything, of course.

Work Flow

There are a few steps that you have to go through, some of them automated, in order to run a query against a root file (or a collection of root files). When I’m creating a project myself it takes less than 5 minutes.

  1. Custom Objects. If your TTree contains custom objects then you must build an extra layer to translate those objects. If your TTree is made up of int, double, vector<double>, vector<vector<double>>, etc., then the tool can handle this without having to do the extension. While this is possible, it is not well supported currently. How to implement these are described separately.
  2. Create a C# library or console application project and install the nuget libraries there.
  3. Generate a data model you can write LINQ queries against from your TTree. Associated arrays and objects can be gathered together in objects, leaf names can be renamed, etc., to make your queries make more sense.
  4. Fill in the code to do the actual work.

The steps are detailed below.

Create the C# Library or Console Application

To run LINQ queries some code must be generated in both C++ and C#. Currently, only C# is created. If you want to use another .NET language to run your queries (like F# or VB.NET) then you must create a C# library and put your LINQToROOT base code in there. All the queries can then be coded from any language that can deal with standard LINQ.

  1. In a Visual Studio solution create a library or application based on the C# language.
  2. Right click on the project’s References folder and start up the Manage Nuget Packages dialog box.
  3. Select the ROOT nuget feed you added from the “Online” sub-list. In the “Search online” area type in “LINQToTTree”. Please note that it can take a while for this search to complete – the webserver is slow (for as yet ununderstood reasons). Adding this library will add some template files and also a lot of libraries!

Generating and Editing your Data Model

This is a two step process:

  1. Use a special command to generate the data model from an example ROOT file. This is done once, or only when the ROOT file format changes.
  2. Edit the resulting XML files to change it to make it easier to write queries against.

Generating The Data Model XML Files

You’ll need a ROOT file with enough events in it for the generator to recognize patterns. It scans the entire file looking for patterns. For example, if “ele_px” and “ele_py” are both arrays and it noticed that they always have the same number of entries, then it will always put them together in the same object so you can reference them as “obj.ele_px” or “obj.ele_py” (or “obj.px” and “obj.py” with renaming, see below).

Do the following steps to do this parsing:

  1. From the IDE’s menus, select “View –> Other Windows –> Package Manager Console”. This brings up a small powershell command window.
  2. In that window enter the command “Write-TTree-MetaData <path-to-root-file>”. It is fine if the file is located on a share (like a SAMBA share from a large Linux disk server, etc.). If the path has any spaces in it make sure to enclose the path in double-quotes!
    • You’ll get some errors about not being able to translate some leaves in the TTree. For example, strings are not currently supported. Or an unknown custom object. Inspect them to make sure nothing important was left behind.
    • For custom objects you can’t use this command. See instructions here (that are not well supported currently).
    • A separate CMD window will pop up. Sorry, this is a side-effect of running ROOT. Just ignore it.
    • By default the object model will be put in a namespace "ROOTLINQ" in your project. Add the "-Namespace MYNS" to put them in the namespace MYNS instead.
    • Powershell help will give you more details about this command. 
  3. A dialog box from the IDE will prompt you to re-load the project. Click Reload.

You will see several files added to the project. Those ending in .ntup you are welcome to edit. Be very very careful about editing files that end with .ntupom!!!

In some cases it is necessary to make sure that pre-built dictionary objects are loaded. Instructions here detail how to do that. You’ll see error messages in the following if this occurs.

Editing Your Data Model

You can rename variables, group them, and create indices from one set of groupings into another by altering the XML files produced above. Have at it – this is by far one of the best things you can do to simplify access to your TTree and make your code more readable! As an example, if one of your leaves is an index into the jet array (say the track-jet association), then you can encode that information in your data model so you can directly reference the associated jet from the track. You can also rename the groupings from, say, group6 to Jets, or similar.

Everyone should spend a bit of time cleaning things up after this run – it can make the difference between a clear and concise LINQ query and an incomprehensible one.

Once you are done editing then do a build. At that point the IDE’s intellisense will pick up all your changes and make writing LINQ queries a series of tab strokes! Winking smile

The Main Program

The main program is, finally, where you can code up your analysis. Getting it setup is fairly easy.

  1. If you have custom objects:
    1. Add a reference to the wrapper library you created above (if you needed it for custom objects).
    2. Add the dll and lib files from the classes that were built for the custom objects. If you forget to to do this you’ll get a very cryptic error message that won’t at all give you a clue as to what is wrong, so make sure you do this (only if you have custom objects).
    3. Set the type of these dll and lib files to be “Content” on the properties info box (right click on the item in your project), and set to “Copy if newer” as the copy option. These dll’s, etc. must be copied to the output directory of the executable so that they can be found and loaded when the right time arrives.
  2. Some pointers on LINQ references
  3. Start coding! Some examples on making plots, counting events, and batching operations for efficiency can be found here.

Here is a sample program that counts the number of events and also makes a plot or two.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using LINQToTreeHelpers.FutureUtils;
using LINQToTTreeLib;
using LINQToTreeHelpers;

namespace CommandLineTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var f = new FileInfo(@"\\lint-shark\HEP Data\hvmc\user.Sidoti.105013.J4_pythia_jetjet.e574_s934_s946_r2299.HVESD_ntuple_v003.110522165651\user.Sidoti.000385.AANT._00002.root");
            var q = ROOTLINQ.QueryableCollectionTree.Create(f);

            // Create a standard root file that will contain the results
            var output = new FutureTFile("junk.root");

            var numEvents = q.FutureCount();

            var jets = from evt in q
                       from j in evt.Jets
                       select j;

            jets.FuturePlot("jetpt", "Jet pT; pT [GeV]", 100, 0.0, 200.0, j => j.pT / 1000.0).Save(output);
            jets.FuturePlot("jeteta", "Jet eta; eta", 100, -4.0, 4.0, j => j.Eta).Save(output);
            jets.FuturePlot("jetphi", "Jet phi; phi", 100, -Math.PI, Math.PI, j => j.Phi).Save(output);

            output.Close();

            Console.WriteLine("We saw {0} events.", numEvents.Value);
        }
    }
}

Source Control

Everyone does this differently, of course. But what I’ve found that works best is to put everything that gets added to your project into source control. So, put in the packages.config file that is added by nuget, and the template files added by the LINTToROOT package, and the .ntup and .ntupom files that are added by parsing your root tuple. You can then use nuget on other machines to update the packages to make sure all the libraries are installed.

Last edited Aug 24, 2013 at 2:06 PM by gwatts, version 15

Comments

No comments yet.