예제 #1
0
        /// <summary>
        /// Return all trees that are in a given directory. Make sure that if we have multiple
        /// cycles in the directory we only process the first one we encounter.
        /// </summary>
        /// <param name="dir"></param>
        /// <returns></returns>
        public IEnumerable<ROOTClassShell> ParseTDirectory(ROOTNET.Interface.NTDirectory dir)
        {
            var converter = new ParseTTree();
            converter.ProxyGenerationLocation = ProxyGenerationLocation;

            HashSet<string> seenTreeNames = new HashSet<string>();

            foreach (var key in dir.ListOfKeys.Cast<ROOTNET.Interface.NTKey>())
            {
                var c = ROOTNET.NTClass.GetClass(key.GetClassName());
                if (c != null)
                {
                    if (c.InheritsFrom("TTree"))
                    {
                        if (!seenTreeNames.Contains(key.Name))
                        {
                            seenTreeNames.Add(key.Name);
                            var t = key.ReadObj() as ROOTNET.Interface.NTTree;
                            if (t != null)
                            {
                                foreach (var cshell in converter.GenerateClasses(t))
                                {
                                    yield return cshell;
                                }
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Normalize the naming of an object. We don't really care about the names for a hash... so...
        /// </summary>
        /// <param name="namedObj"></param>
        private void InternalAccumulateNamedHash(ROOTNET.Interface.NTNamed namedObj)
        {
            string oName = namedObj.Name;
            string oTitle = namedObj.Title;

            namedObj.Name = "name_" + _namedObjectCount.ToString();
            namedObj.Title = "title_" + _namedObjectCount.ToString();

            InternalAccumulateHash(namedObj);

            namedObj.Name = oName;
            namedObj.Title = oTitle;
        }
 /// <summary>
 /// Dip into and return the buffer data. Avoids a memory allocation.
 /// </summary>
 /// <param name="buffer"></param>
 /// <returns></returns>
 private static IEnumerable<SByte> BufferAsBytes(ROOTNET.Interface.NTBuffer buffer)
 {
     int l = buffer.Length();
     var bufferData = buffer.Buffer();
     for (int i = 0; i < l; i++)
     {
         // Access the byte, but make sure to bomb with a clear error message if something
         // funny happens (we've seen real problems in the field).
         SByte r;
         try
         {
             r = bufferData[i];
         } catch (Exception e)
         {
             throw new InvalidOperationException($"Fatal error accessing the {i} element of an array that is {l} long.", e);
         }
         yield return r;
     }
 }
예제 #4
0
 /// <summary>
 /// Given a branch that is a template, parse it and add to the class hierarchy.
 /// </summary>
 /// <param name="branch"></param>
 /// <returns></returns>
 private IEnumerable<ROOTClassShell> ExtractROOTTemplateClass(ROOTClassShell container, ROOTNET.Interface.NTBranch branch)
 {
     return ExtractROOTTemplateClass(container, branch.Name, branch.GetClassName());
 }
예제 #5
0
 public ImplicitTestForTheObjectInterface(ROOTNET.Interface.NTString obj)
 {
     _s = obj;
 }
예제 #6
0
 public static double TMVASelectorSimpleCutsTest (ROOTNET.NTMVA.NReader reader, double a1, double a2, double aux)
 {
     throw new NotImplementedException("THis should never get called!");
 }
예제 #7
0
 /// <summary>
 /// Reformat the name.
 /// </summary>
 /// <param name="h"></param>
 /// <param name="format">string.Format argument, arg {0} will be the old histogram name</param>
 /// <returns></returns>
 private static ROOTNET.Interface.NTH1 AppendName(ROOTNET.Interface.NTH1 h, string format)
 {
     h.Name = string.Format(format, h.Name);
     return h;
 }
예제 #8
0
        /// <summary>
        /// Create the classes for dealing with a simple leaf. There a bunch of different things that 
        /// could be stored in here:
        /// 1) Simple itmes like "int" or "float"
        /// 2) Arrays, like int[10], int[nTracks]
        /// 3) vector[int], TLorentzVector (unsplit) - objects that ROOT both knows about and also
        ///     are not split.
        /// 4) unsplit, unknown objects whose structure is defined by a Streamer.
        ///
        /// Sorting out which situation is non-trival, unfortunate.

        /// 1) There is the item type (leaf.TypeName). This could be "int" or "vector-blah-blah"
        /// 2) In the title there may be a "[stuff]" whihc means if it was "int" it becomes "int[]". :-)
        ///    This is for dealing with a c-style array.
        /// </summary>
        /// <param name="leaf"></param>
        /// <returns></returns>
        private IClassItem ExtractUnsplitKnownClass(ROOTNET.Interface.NTLeaf leaf)
        {
            return ExtractSimpleItem(new SimpleLeafInfo(leaf));
        }
예제 #9
0
 public SimpleLeafInfo(ROOTNET.Interface.NTLeaf leaf)
 {
     Name = leaf.Name;
     Title = leaf.Title;
     TypeName = leaf.TypeName;
 }
예제 #10
0
        /// <summary>
        /// A class has been defined only in the local tree. We need to parse through it and extract
        /// enough into to build a class on our own so that it can be correctly referenced in LINQ.
        /// </summary>
        /// <param name="container"></param>
        /// <param name="branch"></param>
        /// <param name="cls"></param>
        /// <returns></returns>
        private IEnumerable<ROOTClassShell> BuildMetadataForTTreeClassFromBranches(ROOTClassShell container, ROOTNET.Interface.NTBranch branch, ROOTNET.Interface.NTClass cls)
        {
            //
            // Get a unique classname. Attempt to do "the right thing". In particular, if this is a clones array of some
            // struct, it is not a "named" class, so use the name of the clones array instead.
            //

            string className = cls.Name;
            bool mightBeClonesArray = false;
            if (branch is ROOTNET.Interface.NTBranchElement)
            {
                var cn = (branch as ROOTNET.Interface.NTBranchElement).ClonesName.SanitizedName();
                if (!string.IsNullOrWhiteSpace(cn))
                {
                    className = cn;
                    mightBeClonesArray = true;
                }
            }

            if (_classNameCounter.ContainsKey(className))
            {
                _classNameCounter[className] += 1;
                className = string.Format("{0}_{1}", className, _classNameCounter[className]);
            }
            else
            {
                _classNameCounter[className] = 0;
            }

            //
            // We will define the class, and it will be exactly what is given to use by the
            // tree.
            //

            var varName = branch.Name.SanitizedName();
            container.Add(new ItemSimpleType(varName, className) { NotAPointer = true });

            //
            // We are going to build our own class type here.
            //

            var treeClass = new ROOTClassShell(className) { IsTopLevelClass = false };

            //
            // Now, loop over the branches and add them in, returning any classes we had to generate.
            //

            foreach (var c in ExtractClassesFromBranchList(treeClass, branch.ListOfBranches.Cast<ROOTNET.Interface.NTBranch>()))
            {
                yield return c;
            }

            //
            // The arrays in a tclones arrays are funny. The proxy generated parses them as seperate arrays, but their length is
            // basically the size of the tclonesarray. So we have to use that as the length. This is implied be cause we've marked
            // this class as a tclones array class already (above - the IsTTreeSubClass). So for the index we mark it as an index,
            // but we just marked the bound as "implied" - this will be picked up by the code when it is generated later on.
            //

            if (mightBeClonesArray)
            {
                var cBoundName = string.Format("{0}_", varName);
                var cstyleArrayIndicies = from item in treeClass.Items
                                          where item is ItemCStyleArray
                                          let citem = item as ItemCStyleArray
                                          from index in citem.Indicies
                                          where !index.indexConst && index.indexBoundName == cBoundName
                                          select index;
                bool foundTClonesArray = false;
                foreach (var item in cstyleArrayIndicies)
                {
                    item.indexBoundName = "implied";
                    foundTClonesArray = true;
                }
                treeClass.IsTClonesArrayClass = foundTClonesArray;

            }

            //
            // If this is a tclones array - and it is a real array, then we don't want to de-reference anything.
            //

            if (treeClass.IsTClonesArrayClass)
            {
                foreach (var item in treeClass.Items)
                {
                    item.NotAPointer = true;
                }
            }

            //
            // Finally, the one we just built!
            //

            yield return treeClass;
        }
예제 #11
0
        /// <summary>
        /// There is a plain class that needs to be extracted. We usually end up here becuase it is a split class of
        /// some sort. For now, we will assume it is a real root class.
        /// </summary>
        /// <param name="branch"></param>
        /// <returns></returns>
        private IEnumerable<ROOTClassShell> ExtractROOTPlainClass(ROOTClassShell container, ROOTNET.Interface.NTBranch branch)
        {
            //
            // Double chekc that this is a root class. Since we are looking at the Tree, ROOT's system would certianly have declared it
            // internally. If we can't find the cls info, then we are in trouble.
            // 

            var cls = ROOTNET.NTClass.GetClass(branch.GetClassName());
            if (cls == null)
            {
                throw new NotImplementedException("The class '" + branch.GetClassName() + "' is not known to ROOT's type systems - and I can't proceed unless it is");
            }
            if (cls.Name == "string")
            {
                throw new NotImplementedException("The class 'string' is not translated yet!");
            }

            //
            // There are several ways this class can be encoded in the file. They broadly break down
            // into two classes:
            //
            //  1) A class that is fully defined by ROOT. TLorentzVector would be such a thing.
            //      Custom classes that ROOT has a full dictionary for are equivalent and that
            //      we have a good wrapper for.
            //  2) A class that is only defined by the contents of the ROOT file. This could be
            //      as a series of leaves in the TTree (this would be the case of a split class)
            //      or in the streamer, which is a non-split class' case.
            //

            //
            // If it has some public data members, then it is a real ROOT class, and whatever was done to define it and make it known
            // to ROOT here we assume will also be done when the full blown LINQ interface is run (i.e. some loaded C++ files).
            //

            if (!cls.IsShellTClass())
            {
                container.Add(new ItemROOTClass(branch.Name, branch.GetClassName()));
                return Enumerable.Empty<ROOTClassShell>();
            }

            //
            // If we are here, then we are dealing with a locally defined class. One that ROOT made up on the fly. In short, not one
            // that we are going to have a translation for. So, we have to build the meta data for it. This
            // meta data can come from the tree branch list or from the streamer.
            //

            return BuildMetadataForTTreeClassFromBranches(container, branch, cls);
        }
예제 #12
0
        /// <summary>
        /// Extract a class from a "good" streamer.
        /// </summary>
        /// <param name="cls"></param>
        /// <param name="streamer"></param>
        /// <returns></returns>
        private IEnumerable<ROOTClassShell> ExtractClassFromStreamer(ROOTClassShell container, string itemName, ROOTNET.Interface.NTClass cls, ROOTNET.Interface.NTVirtualStreamerInfo sInfo)
        {
            // This guy is a class with elements, so go get the elements...

            var c = new ROOTClassShell(cls.Name.SanitizedName()) { IsTopLevelClass = false };
            if (container != null)
                container.Add(new ItemROOTClass() { Name = itemName, ItemType = cls.Name.SanitizedName(), NotAPointer = false });
            var clist = new List<ROOTClassShell>();
            clist.Add(c);

            foreach (var item in sInfo.Elements.Cast<ROOTNET.Interface.NTStreamerElement>())
            {
                if (item == null)
                    throw new ArgumentNullException("Streamer element was null");
                if (item.TypeName == "BASE")
                {
                    SimpleLogging.Log(string.Format("Item '{0}' has a subclass of type '{1}' - we can't parse inherritance yet", itemName, item.FullName));
                    continue;
                }
                var itemCls = item.ClassPointer;
                if (itemCls == null)
                {
                    // This is going to be something like "int", or totally unknown!
                    c.Add(ExtractSimpleItem(new SimpleLeafInfo() { Name = item.FullName, TypeName = item.TypeName, Title = item.FullName }));
                } else if (!itemCls.IsShellTClass())
                {
                    try
                    {
                        // We know about this class, and can use ROOT infrasturcutre to do the parsing for it.
                        // Protect against funny template arguments we can't deal with now - just skip them.
                        var itemC = ExtractSimpleItem(new SimpleLeafInfo() { Name = item.FullName, TypeName = itemCls.Name, Title = item.FullName });
                        c.Add(itemC);
                    }
                    catch (Exception e)
                    {
                        SimpleLogging.Log(string.Format("Unable to deal with streamer type '{0}', skiping member '{1}': {2}", itemCls.Name, item.FullName, e.Message));
                    }
                }
                else
                {
                    // Unknown to ROOT class. How we handle this, exactly, depends if it is a template class or if it is
                    // a raw class.
                    if (itemCls.IsTemplateClass())
                    {
                        var newClassDefs = ExtractROOTTemplateClass(c, item.FullName, itemCls.Name);
                        clist.AddRange(newClassDefs);
                    }
                    else
                    {
                        var newClassDefs = new List<ROOTClassShell>(ExtractUnsplitUnknownClass(c, item.FullName, itemCls));
                        clist.AddRange(newClassDefs);
                    }
                }
            }

            return clist;
        }
예제 #13
0
        /// <summary>
        /// Extract info for a sub-class from a branch! The last one is the top level class we are currently parsing!
        /// </summary>
        /// <param name="branch"></param>
        /// <returns></returns>
        private IEnumerable<ROOTClassShell> ExtractClass(ROOTClassShell container, ROOTNET.Interface.NTBranch branch)
        {
            ///
            /// First, figure out what kind of class this is. For example, might it be a stl vector? If so,
            /// then we need to parse that up!
            /// 

            if (branch.GetClassName().Contains("<"))
            {
                return ExtractROOTTemplateClass(container, branch);
            }
            else
            {
                return ExtractROOTPlainClass(container, branch);
            }
        }
예제 #14
0
 /// <summary>
 /// Extract the unsplit unknown class by parsing the streamer.
 /// </summary>
 /// <param name="cls"></param>
 /// <returns></returns>
 private IEnumerable<ROOTClassShell> ExtractUnsplitUnknownClass(ROOTNET.Interface.NTClass cls)
 {
     return ExtractUnsplitUnknownClass(null, null, cls);
 }
예제 #15
0
        /// <summary>
        /// The class has no def in a TClass. It has no def in the way the branches and leaves are layed out. So,
        /// we, really, have only one option here. Parse the streamer!
        /// </summary>
        /// <param name="leaf"></param>
        /// <returns></returns>
        private IEnumerable<ROOTClassShell> ExtractUnsplitUnknownClass(ROOTClassShell container, string itemName, ROOTNET.Interface.NTClass cls)
        {
            // Make sure that we are ok here.
            var streamer = cls.StreamerInfo;
            if (streamer == null)
                return Enumerable.Empty<ROOTClassShell>();

            return ExtractClassFromStreamer(container, itemName, cls, streamer);
        }
예제 #16
0
        /// <summary>
        /// Look at everything we have in this tree and see if we can't generate a class correctly.
        /// </summary>
        /// <param name="tree"></param>
        /// <returns></returns>
        public IEnumerable<ROOTClassShell> GenerateClasses(ROOTNET.Interface.NTTree tree)
        {
            if (tree == null)
                throw new ArgumentNullException("tree must not be null");

            ///
            /// The outlying class is going to be called by the name of the tree.
            /// 

            var masterClass = new ROOTClassShell(tree.Name);

            var subClassesByName = from sc in ExtractClassesFromBranchList(masterClass, tree.ListOfBranches.Cast<ROOTNET.Interface.NTBranch>())
                                   group sc by sc.Name;
            var subClasses = from scg in subClassesByName
                             where scg.ClassesAreIdnetical()
                             select scg.First();
            foreach (var sc in subClasses)
            {
                yield return sc;
            }


            ///
            /// Last thing we need to do is create a proxy for the class.
            /// 

            FileInfo f = MakeProxy(tree);
            masterClass.NtupleProxyPath = f.FullName;

            ///
            /// Work around a ROOT bug that doesn't allow for unloading of classes
            /// in the STL after a query is run. Actually, it will unload them, but somehow keeps
            /// references in memory.
            /// 

            masterClass.ClassesToGenerate = ExtractSTLDictionaryReferences(f);

            ///
            /// Analyze the TTree arrays.
            /// 

            var at = new ArrayAnalyzer();
            var groupInfo = at.AnalyzeTTree(masterClass, tree, 100);

            ///
            /// Any item that isn't an array should be added to the list and
            /// put in the "ungrouped" array.
            /// 

            AddNonArrays(masterClass, groupInfo, "ungrouped");

            ///
            /// Write out the user info
            /// 

            masterClass.UserInfoPath = WriteUserInfo(groupInfo, tree.SanitizedName()).FullName;

            ///
            /// Return the master class
            /// 

            yield return masterClass;
        }
예제 #17
0
        /// <summary>
        /// Generate a proxy for the tree. This involves making the proxy and then putting in the proper
        /// text substitutions for later processing by our framework. Some ugly text hacking!
        /// </summary>
        /// <param name="tree"></param>
        /// <returns></returns>
        private FileInfo MakeProxy(ROOTNET.Interface.NTTree tree)
        {
            ///
            /// First create the proxy. We have to create a darn temp macro name for that.
            /// 

            var oldDir = Environment.CurrentDirectory;
            var createItDir = new DirectoryInfo(Environment.CurrentDirectory);
            if (ProxyGenerationLocation != null)
                createItDir = ProxyGenerationLocation;
            FileInfo macroFile = new FileInfo(createItDir + @"\junk_macro_parsettree_" + tree.SanitizedName() + ".C");
            FileInfo result = null;
            try
            {
                ///
                /// We can only use local directories
                /// 

                if (ProxyGenerationLocation != null)
                    Environment.CurrentDirectory = ProxyGenerationLocation.FullName;

                using (var writer = macroFile.CreateText())
                {
                    writer.WriteLine("void {0} () {{}}", Path.GetFileNameWithoutExtension(macroFile.Name));
                    writer.Close();
                }

                result = new FileInfo("ntuple_" + tree.SanitizedName() + ".h");
                tree.MakeProxy(Path.GetFileNameWithoutExtension(result.Name), macroFile.Name, null, "nohist");
            }
            finally
            {

                ///
                /// Go back to where we were
                /// 

                Environment.CurrentDirectory = oldDir;
            }

            ///
            /// Next, add the proper things and remove some stuff
            /// 

            ///
            /// Return the location of the cpp file
            /// 

            return result;
        }
예제 #18
0
        /// <summary>
        /// Do the accumulation for a root object.
        /// </summary>
        /// <param name="nTObject"></param>
        private void InternalAccumulateHash(ROOTNET.Interface.NTObject nTObject)
        {
            if (nTObject == null)
                throw new ArgumentNullException("The argument to InternalAccumulateHash was null - not allowed.");

            // Write it to a ROOT buffer
            var buffer = new ROOTNET.NTBufferFile(ROOTNET.Interface.NTBuffer.EMode.kWrite);
            buffer.WriteObject(nTObject);
            //var result = buffer.Buffer().as_array(buffer.Length());
            var result = BufferAsBytes(buffer);

            // And update the hash value we are holding onto.
            ComputeHash(result);
        }