ROOT - pyroot: Branch seen as leaf, can't access actual leaves - c++

I am trying to extract information from a root file using pyroot.
I tried using the usual GetBranch, GetLeaf, GetValue but it does not work as usual, so I tried alternatives.
I found an equivalent code in c++ which is extracting the values just fine from my ROOT file but when applying the same thing in pyroot, I get an empty object as my "mcinfo" (see below).
I also tried displaying the branches and leaves with GetListOfBranches() and GetListOfLeaves(). I get the proper list of branches with the first but when looking at the list of leaves (here MC but it's the same with all branches), I get out of MC.GetListOfLeaves() that the only leaf is MC too... I have several leaves (for instance energy) that I can access just fine with the c++ code and directly with data.Scan("energy") too...
Anyone has an idea of how to fix this? Sorry, I am not that familiar with ROOT yet. I assume it is a rather easy fix, but I don't see what is wrong with this...
C++ code:
TFile *file = new TFile(fname);
TTree *data = (TTree*)file->Get("data");
TBranch * McinfoBranch;
MCInfo* mcinfo = (MCInfo*)file->GetList()->FindObject("MC");
data->SetBranchAddress("MC", &mcinfo, &McinfoBranch);
pyroot version:
infile = ROOT.TFile(fname)
data = infile.Get("data")
mcinfo = infile.GetList().FindObject("MC")
which gives me this when printing mcinfo: <cppyy.gbl.TObject object at 0x(nil)>.

Related

Error with std::filesystem::copy copying a file to another pre-existing directory

See below for the following code, and below that, the error that follows.
std::string source = "C:\\Users\\cambarchian\\Documents\\tested";
std::string destination = "C:\\Users\\cambarchian\\Documents\\tester";
std::filesystem::path sourcepath = source;
std::filesystem::path destpath = destination;
std::filesystem::copy_options::update_existing;
std::filesystem::copy(sourcepath, destpath);
terminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error'
what(): filesystem error: cannot copy: File exists [C:\Users\cambarchian\Documents\tested] [C:\Users\cambarchian\Documents\tester]
Tried to use filesystem::copy, along with trying different paths. No luck with anything. Not too much I can write here as the problem is listed above, could be a simple formatting issue. That being said, it worked on my home computer using visual studio 2022, however using VS Code with gcc 11.2 gives me this issue.
Using:
filesystem::copy_file(oldPath, newPath, filesystem::copy_options::overwrite_existing);
The overloads of std::filesystem::copy are documented. You're using the first overload, but want the second:
void copy(from, to) which is equivalent to [overload 2, below] using copy_options::none
void copy(from, to, options)
Writing the statement std::filesystem::copy_options::update_existing; before calling copy doesn't achieve anything at all, whereas passing the option to the correct overload like
std::filesystem::copy(sourcepath, destpath,
std::filesystem::copy_options::update_existing);
should do what you want.
... it worked on my home computer using visual studio 2022 ...
you don't say whether the destination file existed in that case, which is the first thing you should check.
I put the copy_options within the copy function but it didn't work so I started moving it around, I probably should have mentioned that.
Randomly permuting your code isn't a good way of generating clean examples for others to help with.
In the rare event that hacking away at something does fix it, I strongly recommend pausing to figure out why. When you've hacked away at something and it still doesn't work, by all means leave comments to remind yourself what you tried, but the code itself should still be in a good state.
Still doesn't work when I write std::filesystem::copy(sourcepath, destpath, std::filesystem::copy_options::recursive)
Well, that's a different option, isn't it? Were you randomly permuting which copy_options you selected as well?
Trying recursive and update_existing yields the same issue.
The documentation says
The behavior is undefined if there is more than one option in any of the copy_options option group present in options (even in the copy_file group).
so you shouldn't be setting both anyway. There's no benefit to recursively copying a single file, but there may be a benefit to updating or overwriting one. If the destination already exists. Which, according to your error, it does.
Since you do have an error explicitly saying "File exists", you should certainly look at the "options controlling copy_file() when the file already exists" section of the table here.
Visual Studio 2022 fixed the problem

Getting `illegal pointer` error when using AddFriend from ROOT(cern)

Aim;
I wish to compare the contents of two ROOT TTree objects that have identical structure (but not identical contents obviously). The best way to do this seems to be using AddFriend.
Problem;
I am getting this error message;
Error: illegal pointer to class object t3 0x0 1681 makeFriends.C:6:
*** Interpreter error recovered ***
What I've tried so far;
After running the example at the bottom of this page successfully I decided to reduce it down to just the reading and friend adding section, as I had already created tree3.root and tree3f.root in the first run. So I had a file called tree3.C containing;
// Function to read the two files and add the friend
void tree3r() {
TFile *f = new TFile("tree3.root");
TTree *t3 = (TTree*)f->Get("t3");
// Add the second tree to the first tree as a friend
t3->AddFriend("t3f","tree3f.root");
// Draw pz which is in the first tree and use pt
// in the condition. pt is in the friend tree.
//t3->Draw("pz","pt>5");
}
This worked as expected, when loaded (root[] .L tree3.C) and run (root[] tree3r()) from the root prompt.
So I put a copy in a folder containing both of my root files, plainMaskOutput.root and DNMaskOutput.root, and changed strings in the copy to match the names of my files. So I have;
// Function to read the two files and add the friend
void tree3r() {
TFile *f = new TFile("plainMaskOutput.root");
TTree *t3 = (TTree*)f->Get("t3");
// Add the second tree to the first tree as a friend
t3->AddFriend("t3f","DNMaskOutput.root");
// Draw pz which is in the first tree and use pt
// in the condition. pt is in the friend tree.
//t3->Draw("pz","pt>5");
}
Which gives the error above. I dont understand why these things are behaving diffrently? Why can't they just be friends?
It turned out that TFiles method Get might return null, indicating the failure. You were not taking that into account. Why does it return null in your case?
According to the link I provided in the comments (https://root.cern.ch/phpBB3/viewtopic.php?t=12407) it is because your file doesn't contain a tree having a name you provided.
It will be better to add an explicit check of the returned value from Get. if the file gets changed later, your program will start to crash again.
The problem is that plainMaskOutput.root is a file name and the string inside the Get() parenthesis is the tree name. The file called plainMaskOutput.root did not contain a tree by the name t3 it contained one by the name HitsTree. So the line should have been;
TTree *foo = (TTree*)f->Get("HitsTree");
Similarly, the add friend command needed to have the name of the tree stored in DNMaskOutput.root, but as they have the same name it should be aliased;
foo->AddFriend("DNHitsTree = HitsTree","DNMaskOutput.root");
This is just the problem I was having this time, it may not always be the problem associated with this error. I am not knowledgeable enough in this area to say what other problems are possible.

python win32com shell.SHFileOperation - any way to get the files that were actually deleted?

In the code I maintain I run across:
from win32com.shell import shell, shellcon
# ...
result,nAborted,mapping = shell.SHFileOperation(
(parent,operation,source,target,flags,None,None))
In Python27\Lib\site-packages\win32comext\shell\ (note win32comext) I just have a shell.pyd binary.
What is the return value of shell.SHFileOperation for a deletion (operation=FO_DELETE in the call above) ? Where is the code for the shell.pyd ?
Can I get the list of files actually deleted from this return value or do I have to manually check afterwards ?
EDIT: accepted answer answers Q1 - having a look at the source of pywin32-219\com\win32comext\shell\src\shell.cpp I see that static PyObject *PySHFileOperation() delegates to SHFileOperation which does not seem to return any info on which files failed to be deleted - so I guess answer to Q2 is "no".
ActiveState Python help contains SHFileOperation description:
shell.SHFileOperation
int, int = SHFileOperation(operation)
Copies, moves, renames, or deletes a file system object.
Parameters
operation : SHFILEOPSTRUCT
Defines the operation to perform.
Return Value
The result is a tuple containing int result of the
function itself, and the result of the fAnyOperationsAborted member
after the operation. If Flags contains FOF_WANTMAPPINGHANDLE, returned
tuple will have a 3rd member containing a sequence of 2-tuples with
the old and new file names of renamed files. This will only have any
content if FOF_RENAMEONCOLLISION was specified, and some filename
conflicts actually occurred.
Source code can be downloaded here: http://sourceforge.net/projects/pywin32/files/pywin32/Build%20219/ (pywin32-219.zip)
Just unpack and go to .\pywin32-219\com\win32comext\shell\src\

Efficient and stable YAML parser for cocos2d-x

I am developing a game using cocos2d-x and C++, and I need to load a bunch of YAML files for this application. I tried using the yaml-cpp library with quite good results.
The problem is that this library seems to be very unstable (at least under cocos2d-x on iOS), since almost 20% of the time it fails loading the same YAML file throwing "end of map not found", "invalid map element", or errors like these ones.
I followed the HowToParseADocument guide, so I think I got it correct. But, since it's not 100% reliable, I am looking for something more stable. Eg:
long size = 0;
unsigned char *yaml = FileUtils::getInstance()->getFileData("file.yml", "r", &size);
std::stringstream is;
is << yaml;
YAML::Parser parser(is);
YAML::Node doc;
while(parser.GetNextDocument(doc)) {
instance->settings = doc.Clone();
}
The parser usally breaks at the parser.GetNextDocument(doc) call. The document I am trying to read is plain YAML with key: value lists in this simple form:
# Comment
section1:
param1: value1
param2: value2
# Comment
section2:
param1: value1
param2: value2
Edit
I am not allowed to disclose the content of the original YAML file, but I can give you some information:
It only contains maps, and not arrays, aliases or other particular constructs
Those values are integers, float or strings
It has been linted with this free tool, with success.
The code I used to read it, posted up there, it's always in that form, and I do not modify it to make the app run correctly. It's just that the app starts and works or starts and does not work. Since I am changing nothing in the middle, I really do not understand what's happening.
It's a bit hard to guess at the solution because you won't provide an actual example, but:
Who owns the data at the unsigned char* returned by getFileData? If that function itself owns the data, then it is no longer valid after the function returns, and so all sorts of crazy stuff might happen.
To validate what's happening here (beyond looking at the implementation of getFileData), you could print out is.string() before calling YAML::Parser parser(is); and see if that prints the expected YAML.

binary tree doesn't rebuild from file

I'm new on data structures and we were assigned to make a guessing game using binary tree implementation. I have accomplished the program flow without file implementation. I have saved the binary tree preorderly on an external file now I have problem in rebuilding tree from file
in my file I have:
Is it Angel Locsin?:#Neneng B?Is it Sam Pinto? ##White Beauty?Is it
Marian Rivera? ##HotandSexy?Is it Cristine Reyes? ###
The "#" is for a NULL node.
I have also my code. I follow the algorithm of what my professor gave me. I searched on the internet and gave me same algorithm as of what my prof said. My problem is on every third non-null data the program crashes. I think the main reason of crashing is a node that was not set to null after the third non-null data is inserted. If so, how could I set it to NULL so that my program will not crash.I assigned the data from file into array of strings and set a "\0" at the last index of array.
void read(node *temp)
{
while(array[j]=="#")
j++;
if(array[j]=="\0")
return;
node *nNode;
nNode = new node;
nNode->yes=NULL;
nNode->no=NULL;
nNode->data=array[j];
j++;
temp=nNode;
read(temp->yes);
read(temp->no);
}
Your problem is in the definition of your read function. I guess the idea is that "temp" is an output parameter of type "node*". But this is not what you have written.
You need to have a pointer or a reference to the "node*" parameter like e.g. so:
void read(node** temp)
Then adjust the rest of the code such that is compiles by proper (de)referencing. This should solve your crash.