ATLAS Offline Software
Loading...
Searching...
No Matches
ViewHelper.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5#ifndef ATHVIEWS_VIEWHELPER_HH
6#define ATHVIEWS_VIEWHELPER_HH
7
8#include "GaudiKernel/SmartIF.h"
9#include "GaudiKernel/IScheduler.h"
10#include "GaudiKernel/EventContext.h"
11#include "GaudiKernel/StatusCode.h"
16#include "AthViews/View.h"
19
20
21namespace ViewHelper
22{
23 //Function to create a vector of views, each populated with one data object
24 template< typename T >
25 inline StatusCode makeAndPopulate( std::string const& viewNameRoot, ViewContainer* viewVector,
26 SG::WriteHandleKey< T > const& populateKey, EventContext const& sourceContext,
27 std::vector< T > const& inputData, bool const allowFallThrough = true )
28 {
29 //Check for spaces in the name
30 if ( viewNameRoot.find( ' ' ) != std::string::npos )
31 {
32 return StatusCode::FAILURE;
33 }
34
35 //Make a WriteHandle to use
36 SG::WriteHandle<T> populateHandle( populateKey, sourceContext );
37
38 //Loop over all input data
39 unsigned int const viewNumber = inputData.size();
40 for ( unsigned int viewIndex = 0; viewIndex < viewNumber; ++viewIndex )
41 {
42 //Create view
43 SG::View * outputView = new SG::View( viewNameRoot, viewIndex, allowFallThrough );
44 viewVector->push_back( outputView );
45
46 //Attach a handle to the view
47 StatusCode sc = populateHandle.setProxyDict( outputView );
48 if ( !sc.isSuccess() )
49 {
50 viewVector->clear();
51 return sc;
52 }
53
54 //Populate the view
55 sc = populateHandle.record( std::make_unique< T >( inputData[ viewIndex ] ) );
56 if ( !sc.isSuccess() )
57 {
58 viewVector->clear();
59 return sc;
60 }
61 }
62
63 return StatusCode::SUCCESS;
64 }
65
66 //Function to pass a single view to the scheduler
67 inline StatusCode scheduleSingleView( SG::View* view, std::string const& nodeName, EventContext const& sourceContext,
68 EventIDBase::number_type conditionsRun, SmartIF<IScheduler> scheduler )
69 {
70 //Make a new context with the view attached
71 auto viewContext = std::make_unique< EventContext >( sourceContext );
72 if ( view->getROI().isValid() ) {
74 Atlas::ExtendedEventContext( view, conditionsRun, *view->getROI() ) );
75 } else {
77 Atlas::ExtendedEventContext( view, conditionsRun ) );
78 }
79
80 //Attach the view to the named node
81 return scheduler->scheduleEventView( &sourceContext, nodeName, std::move( viewContext ) );
82 }
83
84 //Function to attach a set of views to a graph node
85 inline StatusCode scheduleViews( ViewContainer * viewVector, std::string const& nodeName,
86 EventContext const& sourceContext, SmartIF<IScheduler> scheduler, bool reverseOrder = false )
87 {
88 //Require the information of the extended context (should always be there, but check anyway)
89 if ( !Atlas::hasExtendedEventContext( sourceContext ) ) {
90 return StatusCode::FAILURE;
91 }
92 Atlas::ExtendedEventContext const extendedContext = Atlas::getExtendedEventContext( sourceContext );
93
94 //Prevent view nesting - test if source context has view attached
95 if ( dynamic_cast< SG::View* >( extendedContext.proxy() ) ) {
96 return StatusCode::FAILURE;
97 }
98
99 //Retrieve the scheduler
100 if ( !scheduler ) {
101 return StatusCode::FAILURE;
102 }
103
104 if ( viewVector->empty() ) {
105
106 //Disable the node if no views
107 return scheduler->scheduleEventView( &sourceContext, nodeName, 0 );
108 }
109 else {
110 if ( reverseOrder ) {
111 for ( auto iter = viewVector->rbegin(); iter != viewVector->rend(); ++iter ) {
112
113 //Schedule each view in reverse (should make no difference, just a debugging tool)
114 if ( scheduleSingleView( *iter, nodeName, sourceContext,
115 extendedContext.conditionsRun(), scheduler ).isFailure() ) {
116 return StatusCode::FAILURE;
117 }
118 }
119 }
120 else {
121 for ( SG::View* view : *viewVector ) {
122
123 //Schedule each view
124 if ( scheduleSingleView( view, nodeName, sourceContext,
125 extendedContext.conditionsRun(), scheduler ).isFailure() ) {
126 return StatusCode::FAILURE;
127 }
128 }
129 }
130 }
131
132 return StatusCode::SUCCESS;
133 }
134
136 private:
138 MsgStream& m_msg;
139 public:
140 ViewMerger(StoreGateSvc* sg, MsgStream& msg ) : m_sg( sg ), m_msg( msg ) {}
141
142 //Function merging view data into a single collection
143 template< typename T >
144 inline StatusCode mergeViewCollection( ViewContainer const& viewVector, SG::ReadHandleKey< T > const& queryKey, EventContext const& sourceContext, T & outputData )
145 {
146 //Make a ReadHandle to use
147 SG::ReadHandle<T> queryHandle( queryKey, sourceContext );
148
149 //Loop over all views
150 for ( const SG::View* inputView : viewVector )
151 {
152 // setProxyDict only supports non-const stores
153 SG::View* nc_inputView ATLAS_THREAD_SAFE = const_cast< SG::View* >( inputView );
154 //Attach the handle to the view
155 StatusCode sc = queryHandle.setProxyDict( nc_inputView );
156 if ( !sc.isSuccess() )
157 {
158 m_msg << MSG::ERROR <<"Failed to use view " << inputView->name() << " to read " << queryHandle.key() << " resetting output" << endmsg;
159 outputData.clear();
160 return sc;
161 }
162
163 //Merge the data
164 T inputData = *queryHandle;
165 outputData.insert( outputData.end(), inputData.begin(), inputData.end() );
166 }
167
168 return StatusCode::SUCCESS;
169 }
170
171 //Function merging view data into a single collection - overload for datavectors to do all the bookkeeping
172 //Adds aux data element "viewIndex" to indicate which element of the merged collection came from where
173 //Calls remap for ElementLinks so that they point to the merged collection
174 template< typename T >
175 inline StatusCode mergeViewCollection( ViewContainer const& viewVector, SG::ReadHandleKey< DataVector< T > > const& queryKey, EventContext const& sourceContext, DataVector< T > & outputData )
176 {
177 //Check that there's a non-const aux store for output bookkeeping
178 if ( !outputData.getStore() )
179 {
180 m_msg << MSG::ERROR << "output data does not have the store" << endmsg;
181 return StatusCode::FAILURE;
182 }
183
184 //Make ReadHandle to access views
185 SG::ReadHandle< DataVector< T > > queryHandle( queryKey, sourceContext );
186
187 //Make accessor for bookkeeping
189
190 //Loop over all views
191 unsigned int offset = outputData.size(); //allow for existing objects in the container
192 for ( const SG::View* inputView : viewVector )
193 {
194 // setProxyDict only supports non-const stores
195 SG::View* nc_inputView ATLAS_THREAD_SAFE = const_cast< SG::View* >( inputView );
196 //Attach the handle to the view
197 StatusCode sc = queryHandle.setProxyDict( nc_inputView );
198 if ( !sc.isSuccess() )
199 {
200 m_msg << MSG::ERROR << "Failed to use view " << inputView->name() << " to read " << queryHandle.key() << endmsg;
201 return sc;
202 }
203
204 //Nothing to do for empty collections
205 if ( queryHandle->empty() )
206 {
207 if (m_msg.level() <= MSG::DEBUG) {
208 m_msg << MSG::DEBUG << "Empty collection " << queryHandle.key() <<" in a view " << inputView->name() <<endmsg;
209 continue;
210 }
211 }
212
213 // Warn about unlocked decorations that won't get copied.
214 for ( SG::auxid_t decor : queryHandle->getDecorIDs() ) {
216 m_msg << MSG::WARNING << "mergeViewCollection: skipped unlocked decoration " << queryHandle.key() << "." << r.getName( decor ) << endmsg;
217 }
218
219 //Merge the data
220 for ( const auto inputObject : *queryHandle.cptr() )
221 {
222 //Element-wise copy data (looks a bit weird, but necessary for xAOD objects)
223 T * outputObject = new T();
224 outputData.push_back( outputObject );
225 *outputObject = *inputObject;
226
227 //Add aux data for bookkeeping
228 viewBookkeeper( *outputObject ) = inputView->getROI();
229 }
230
231 if (m_msg.level() <= MSG::DEBUG) {
232 m_msg << MSG::DEBUG << "Copied " << queryHandle->size() << " objects from collection in view " << inputView->name() << endmsg;
233 }
234
235 //Declare remapping
236 auto proxy = inputView->proxy( queryHandle.clid(), queryHandle.key() ); //shouldn't need to test validity since queryHandle already used
238 proxy->name(),
239 queryHandle.name(),
240 offset );
241 offset += queryHandle->size();
242 }
243
244 return StatusCode::SUCCESS;
245 }
246 };
247
248
252 inline SG::View* makeView( const std::string& common_name, int const unique_index = -1, bool const allowFallThrough = true )
253 {
254 //Check for spaces in the name
255 if ( common_name.find( ' ' ) != std::string::npos )
256 {
257 return nullptr;
258 }
259
260 return new SG::View( common_name, unique_index, allowFallThrough );
261 }
262
263
272 template<typename KEY>
273 auto makeHandle( const SG::View* view, const KEY& key, const EventContext& ctx )
274 {
275 // setProxyDict only supports non-const stores
276 SG::View* nview ATLAS_THREAD_SAFE = const_cast< SG::View* >( view );
277 auto handle = SG::makeHandle( key, ctx );
278 handle.setProxyDict( nview ).ignore(); // can never fail
279 return handle;
280 }
281
282
292 template<typename T, typename CONT>
294 const EventContext& context )
295 {
296 // setProxyDict only supports non-const stores
297 SG::View* nview ATLAS_THREAD_SAFE = const_cast< SG::View* >( view );
298 auto handle = SG::makeHandle<T>(dKey, context );
299 handle.setProxyDict( nview ).ignore(); // can never fail
300 return handle;
301 }
302
303
308 template<typename T>
309 ElementLink<T> makeLink( const SG::View* view, const SG::ReadHandle<T>& handle, size_t index )
310 {
311 auto proxy = view->proxy( handle.clid(), handle.key() );
312 if ( proxy == nullptr ) throw std::runtime_error( "Attempting to make element link with invalid key " + handle.key() );
313 return ElementLink<T>( proxy->name(), index );
314 }
315
316} // EOF namspace ViewHelper
317
318#endif
#define endmsg
Base class for elements of a container that can have aux data.
std::vector< Identifier > ID
An STL vector of pointers that by default owns its pointed-to elements.
static Double_t sc
Handle class for reading from StoreGate.
Handle class for adding a decoration to an object.
Handle class for recording to StoreGate.
DataVector< SG::View > ViewContainer
View container for recording in StoreGate.
Definition View.h:290
#define ATLAS_THREAD_SAFE
EventIDBase::number_type conditionsRun() const
Derived DataVector<T>.
Definition DataVector.h:795
const_reverse_iterator rend() const noexcept
Return a const_reverse_iterator pointing at the beginning of the collection.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
const_reverse_iterator rbegin() const noexcept
Return a const_reverse_iterator pointing past the end of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
void clear()
Erase all the elements in the collection.
bool empty() const noexcept
Returns true if the collection is empty.
SG::Accessor< T, ALLOC > Accessor
Definition AuxElement.h:572
Handle mappings between names and auxid_t.
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Property holding a SG store/key/clid from which a ReadHandle is made.
const_pointer_type cptr()
Dereference the pointer.
virtual const std::string & key() const override final
Return the StoreGate ID for the referenced object.
virtual StatusCode setProxyDict(IProxyDict *store)
Explicitly set the event store.
CLID clid() const
Return the class ID for the referenced object.
const std::string & name() const
Return the StoreGate ID for the referenced object.
A "view" of the event store (IProxyDict).
Definition View.h:46
Property holding a SG store/key/clid/attr name from which a WriteDecorHandle is made.
Handle class for adding a decoration to an object.
Property holding a SG store/key/clid from which a WriteHandle is made.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
The Athena Transient Store API.
StatusCode mergeViewCollection(ViewContainer const &viewVector, SG::ReadHandleKey< T > const &queryKey, EventContext const &sourceContext, T &outputData)
Definition ViewHelper.h:144
StatusCode mergeViewCollection(ViewContainer const &viewVector, SG::ReadHandleKey< DataVector< T > > const &queryKey, EventContext const &sourceContext, DataVector< T > &outputData)
Definition ViewHelper.h:175
ViewMerger(StoreGateSvc *sg, MsgStream &msg)
Definition ViewHelper.h:140
StoreGateSvc * m_sg
Definition ViewHelper.h:137
int r
Definition globals.cxx:22
void setExtendedEventContext(EventContext &ctx, ExtendedEventContext &&ectx)
Move an extended context into a context object.
const ExtendedEventContext & getExtendedEventContext(const EventContext &ctx)
Retrieve an extended context from a context object.
bool hasExtendedEventContext(const EventContext &ctx)
Test whether a context object has an extended context installed.
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
size_t auxid_t
Identifier for a particular aux data item.
Definition AuxTypes.h:27
StatusCode scheduleViews(ViewContainer *viewVector, std::string const &nodeName, EventContext const &sourceContext, SmartIF< IScheduler > scheduler, bool reverseOrder=false)
Definition ViewHelper.h:85
ElementLink< T > makeLink(const SG::View *view, const SG::ReadHandle< T > &handle, size_t index)
Create EL to a collection in view.
Definition ViewHelper.h:309
SG::View * makeView(const std::string &common_name, int const unique_index=-1, bool const allowFallThrough=true)
Definition ViewHelper.h:252
StatusCode scheduleSingleView(SG::View *view, std::string const &nodeName, EventContext const &sourceContext, EventIDBase::number_type conditionsRun, SmartIF< IScheduler > scheduler)
Definition ViewHelper.h:67
StatusCode makeAndPopulate(std::string const &viewNameRoot, ViewContainer *viewVector, SG::WriteHandleKey< T > const &populateKey, EventContext const &sourceContext, std::vector< T > const &inputData, bool const allowFallThrough=true)
Definition ViewHelper.h:25
auto makeHandle(const SG::View *view, const KEY &key, const EventContext &ctx)
Create a view handle from a handle key.
Definition ViewHelper.h:273
Definition index.py:1
Default, invalid implementation of ClassID_traits.
MsgStream & msg
Definition testRead.cxx:32