Here we will show you how to modify or create new xAOD containers/objects, and then how to write these to another xAOD using EventLoop.
 Note that if
 you do it this way you will not be able to read the output xAOD back
 with POOL in Athena. We will make use of some methods in the
 xAODRootAccess package to create our new xAOD.
 Note that if
 you do it this way you will not be able to read the output xAOD back
 with POOL in Athena. We will make use of some methods in the
 xAODRootAccess package to create our new xAOD.
 These
 instructions are only meant for EventLoop/AnalysisBase. With
 Athena/AthAnalysis you have to use the native Athena I/O system for
 writing mini-xAOD files.
 These
 instructions are only meant for EventLoop/AnalysisBase. With
 Athena/AthAnalysis you have to use the native Athena I/O system for
 writing mini-xAOD files.
IMPORTANT NOTE: If you are creating a new smaller xAOD file that is used by your analysis group, consider setting up a derivation in the Derivation Reduction Framework, which will automatically generate this smaller xAOD in the production system for you. See the Derivation Framework for more information.
 Before you do this part
 of the tutorial, make sure that you worked through the section on
 modifying xAOD objects in its entirety.  While it
 can be meaningful simply to copy input objects, you will almost always
 want to modify them in some way.
 Before you do this part
 of the tutorial, make sure that you worked through the section on
 modifying xAOD objects in its entirety.  While it
 can be meaningful simply to copy input objects, you will almost always
 want to modify them in some way.
First of all we need to set up a new “output stream” for writing the xAOD file. This happens in two separate steps.
xAOD::TEvent.In your submission script you need to use
EL::Job::outputAdd
to define a new output stream. Assuming that your EL::Job object is
called job (as it was shown in the
EventLoop configuration section), you can declare
the new output stream like the following in Python:
# Add an output stream called 'ANALYSIS'.
job.outputAdd( ROOT.EL.OutputStream( 'ANALYSIS' ) )
To make your algorithm the most robust, it’s a very good idea to set up a string property on it that allows setting the output stream name from the submission script. See the Using Properties section for more details on setting up such a property.
Assuming that you called the output stream’s name
m_outputStreamName, you can connect the job’s xAOD::TEvent object
to the output stream/file by putting the following into the
initialize() function of your algorithm:
TFile* ofile = wk()->getOutputFile( m_outputStreamName );
if( ! ofile ) {
   // Handle the error...
}
ANA_CHECK( evtStore()->event()->writeTo( ofile ) );
 If you have not done
 that yet, you may need to include
 If you have not done
 that yet, you may need to include "EventLoop/Worker.h" at this
 point to make this code compile successfully.  That may also require
 adding EventLoop as a dependency in your CMakeLists.txt file.
Finally, in finalize() let’s tell the job to close up the output
xAOD by adding:
// Finalize and close our output xAOD file.
TFile* ofile = wk()->getOutputFile( m_outputStreamName );
ANA_CHECK( evtStore()->event()->finishWritingTo( ofile ) );
With all of these set up, you are ready to start adding content to your output xAOD.
Here we will show you how to copy the contents of a full container, unmodified, for every event. We assume you have followed the instructions above to define a new output xAOD in EventLoop.
We will create this copy in the event loop, so in
MyAnalysis/Root/MyxAODAnalysis.cxx in the execute() method add the
following line to copy the full container for "AntiKt4EMTopoJets":
// copy full container(s) to new xAOD
// without modifying the contents of it: 
ANA_CHECK( evtStore()->event()->copy("AntiKt4EMTopoJets") );
At the end of execute() add this line to fill the xAOD with the
content we have specified in the event loop:
// Save the event:
evtStore()->event()->fill();
Compile like usual and test your code as explained in the EventLoop configuration section.
If you have followed the instructions above you will find your output
xAOD in submitDir/data-ANALYSIS/. (Assuming that you set
"ANALYSIS" as the name of your output stream.)
Note that you can only copy xAOD objects and/or containers. You can
determine if the container is of xAOD type by running checkxAOD.py
on the xAOD and seeing which objects are of type xAOD::x (where x
is the container of interest).
There are two options here, dictated by how you set the flag setShallowIO:
Save a real shallow copy only writing to the xAOD container the
 variables you have overwritten while still pointing to the original
 for all other variables. In this case you must also write the
 original container (setShallowIO is true) as
 previously
 described.
Save an actually deep copy; in this case you do not need to also
write the original container to the xAOD (setShallowIO is false).
For either option add these lines below our iterator over the shallow copied jets:
const xAOD::JetContainer *jets = nullptr;
ANA_CHECK (evtStore()->retrieve (jets, "AntiKt4EMTopoJets"));
std::pair< xAOD::JetContainer*, xAOD::ShallowAuxContainer* > jets_shallowCopy = xAOD::shallowCopyContainer( *jets );
xAOD::TEvent* event = wk()->xaodEvent();
  
// true = shallow copy, false = deep copy
// if true should have something like this line somewhere:
// event->copy("AntiKt4EMTopoJets");
jets_shallowCopy.second->setShallowIO( false );
ANA_CHECK (event->record (jets_shallowCopy.first, "ShallowCopiedJets"));
ANA_CHECK (event->record (jets_shallowCopy.second, "ShallowCopiedJetsAux."));
You can record the shallow copy to TStore, in a very similar way we
did above by storing it to TEvent. First in the source code in
execute() you will need to define an instance of a TStore object
(making use of the EventLoop worker object):
xAOD::TStore* store = wk()->xaodStore();
Then simply record your shallowed jet container (and aux container) to the store:
ANA_CHECK (store->record (jets_shallowCopy.first, "ShallowCopiedJets"));
ANA_CHECK (store->record (jets_shallowCopy.second, "ShallowCopiedJetsAux."));
EventLoop takes care of clearing the memory for you.
 At any point you can see
 what is stored to your
 At any point you can see
 what is stored to your xAOD::TStore object by doing
 store->print().
Compile like usual and test your code. Depending on how you set
setShallowIO you will have more or less variables in your new xAOD
associated to the "ShallowCopiedJets" container. You can try
changing the flag, recompiling and checking the alternative content of
the xAOD.
As a final ingredient to writing out modified objects, you can select which of their properties should be written to the output file. The xAOD design was based around the idea that objects/containers may be slimmed during the analysis easily.
As you should know, all the data payload of xAOD objects/containers is
in their auxiliary store objects. Because of this the way to specify
which variables should be written out, is to set a property for the
auxiliary store in question. This is done using the
xAOD::TEvent::setAuxItemList
function. By putting something like this into your algorithm’s
initialize() function:
// Set which variables not to write out:
evtStore()->event()->setAuxItemList ("AntiKt4EMTopoJetsAux.",
                                     "-NumTrkPt1000.-NumTrkPt500");
// Set which variable to do write out:
evtStore()->event()->setAuxItemList ("GoodJetsAux.",
                                     "JetGhostArea.TrackCount");
Unfortunately at the time of writing this still has some issues when using multiple input files (code crashing on a few files into the job), but the formalism is going to be this once the code works as intended…