AliPhysics  8d00e07 (8d00e07)
AliEmcalContainerIndexMap.h
Go to the documentation of this file.
1 #if !(defined(__CINT__) || defined(__MAKECINT__))
2 #ifndef ALIEMCALCONTAINERINDEXMAP_H
3 #define ALIEMCALCONTAINERINDEXMAP_H
4 
5 #include <map>
6 #include <typeinfo>
7 
8 #include <TObject.h>
9 #include <TClonesArray.h>
10 #include <TObjArray.h>
11 #include <TClass.h>
12 #include <AliLog.h>
13 
14 #include "AliEmcalContainer.h"
15 
73 template <class U, class V>
75  public:
77  // Implemented using copy-and-swap mechanism
80  // Change the template variables to avoid shadowing U and V.
81  // See: https://stackoverflow.com/a/4039892
82  template<class X, class Y>
85 
86  // Don't delete fClass, as it was returned by TClass and deleting it will cause segfaults in ROOT
88 
89  // Setup index map for AliEmcalContainer or TClonesArray
90  int RegisterArray(U * inputObject);
91 
92  // Copy the mapping from the source "map"; the mapping is between the global index found in "map" for object "cont" and the object "cont" itself
93  template<class U2>
94  void CopyMappingFrom(const AliEmcalContainerIndexMap<U2, V>& map, U* cont);
95 
96  // Copy the mapping from the source "map"; the mapping is between the global index found in "map" for each object in "containers" and the objects in "containers"
97  template<class U2>
98  void CopyMappingFrom(const AliEmcalContainerIndexMap<U2, V>& map, TCollection & containers);
99 
100  // Index operations
101  // Returns the offset of an input object
102  template<class U2>
103  int GetOffset(const U2 * inputObject) const;
104  // Returns the global index of an input object and the local index of the object of interest
105  int GlobalIndexFromLocalIndex(const U * inputObject, const int localIndex) const;
106  // Returns a pair with the local index and the array for a given global index
107  std::pair<int, U *> LocalIndexFromGlobalIndex(const int globalIndex) const;
108  // Get object directly
109  V * GetObjectFromGlobalIndex(const int globalIndex) const;
110 
111  protected:
112  //template<class Z = U>
113  const TClonesArray * GetObject(const AliEmcalContainer * inputObject) const;
114  const TClonesArray * GetObject(const TClonesArray * inputObject) const;
115  bool IsUnderlyingInputObjectTypeCompatible(const U * inputObject) const;
116 
117  std::map <int, U *> fGlobalIndexMap;
118 
119  int fOffset;
120  TClass* fClass;
121 };
122 
126 template<class U, class V>
128  fGlobalIndexMap(),
129  fOffset(100000),
130  fClass(TClass::GetClass(typeid(V)))
131 {
132 }
133 
137 template<class U, class V>
140  fOffset(map.fOffset),
141  fClass(map.fClass) // Should be okay to be the same pointer, as it just points to the class type
142 {
143 }
144 
148 template<class U, class V>
151 {
152  swap(*this, other);
153 }
154 
159 template<class U, class V>
161 {
162  swap(*this, map);
163 
164  return *this;
165 }
166 
170 template<class X, class Y>
172 {
173  using std::swap;
174 
175  swap(first.offset, second.offset);
176  swap(first.fGlobalIndexMap, second.fGlobalIndexMap);
177  swap(first.fClass, second.fClass);
178 }
179 
189 template<class U, class V>
190 inline const TClonesArray * AliEmcalContainerIndexMap<U, V>::GetObject(const AliEmcalContainer * inputObject) const
191 {
192  return inputObject->GetArray();
193 }
194 
203 template<class U, class V>
204 inline const TClonesArray * AliEmcalContainerIndexMap<U, V>::GetObject(const TClonesArray * inputObject) const
205 {
206  return inputObject;
207 }
208 
220 template<class U, class V>
222 {
223  if (!(inputObject->GetClass()->InheritsFrom(fClass))) {
224  AliErrorGeneral("AliEmcalContainerIndexMap", Form("Cannot register array %s. This map can only accept arrays of type %s.", inputObject->GetName(), fClass->GetName()));
225  return false;
226  }
227 
228  return true;
229 }
230 
241 template<class U, class V>
243 {
244  if (IsUnderlyingInputObjectTypeCompatible(inputObject) == false) {
245  return -1;
246  }
247 
248  int index = 0;
249  bool addToMap = true;
250  for (auto val : fGlobalIndexMap)
251  {
252  // Check if the array is already added
253  // We want to compare the address of the TClonesArrays to simplify the comparison
254  if (GetObject(val.second) == GetObject(inputObject)) {
255  addToMap = false;
256  index = val.first;
257  break;
258  }
259 
260  // Find the max index so that we can add at the proper place
261  if (val.first >= index) {
262  index = val.first + fOffset;
263  }
264  }
265 
266  // Add to map
267  if (addToMap) {
268  // We want to compare the address of the TClonesArrays to simplify the comparison
269  fGlobalIndexMap[index] = inputObject;
270  }
271 
272  return index;
273 }
274 
284 template<class U, class V>
285 int AliEmcalContainerIndexMap<U, V>::GlobalIndexFromLocalIndex(const U * inputObject, const int localIndex) const
286 {
287  int globalIndex = GetOffset(inputObject);
288 
289  // Only add the local index if we found a match!
290  if (globalIndex >= 0) {
291  globalIndex += localIndex;
292  }
293  else {
294  AliWarningGeneral("AliEmcalContainerIndexMap", TString::Format("Unable to retrieve global index for input object %s. Was the input object registered?", inputObject->GetName()));
295  }
296 
297  return globalIndex;
298 }
299 
307 template<class U, class V>
308 template<class U2>
309 int AliEmcalContainerIndexMap<U, V>::GetOffset(const U2 * inputObject) const
310 {
311  int globalIndex = -1;
312  for (auto val : fGlobalIndexMap)
313  {
314  // We want to compare the address of the TClonesArrays to simplify the comparison
315  if (GetObject(val.second) == GetObject(inputObject)) {
316  globalIndex = val.first;
317  break;
318  }
319  }
320 
321  return globalIndex;
322 }
323 
331 template<class U, class V>
332 std::pair<int, U *> AliEmcalContainerIndexMap<U, V>::LocalIndexFromGlobalIndex(const int globalIndex) const
333 {
334  // Round to nearest offset
335  int index = (globalIndex + fOffset/2)/fOffset * fOffset;
336 
337  // Used at() to allow the function to be const (operator[] is not const for std::map)
338  U * array = fGlobalIndexMap.at(index);
339 
340  return std::pair<int, U*> (globalIndex - index, array);
341 }
342 
351 template<class U, class V>
353 {
354  auto res = LocalIndexFromGlobalIndex(globalIndex);
355 
356  // We don't need to call GetObject() if we access using operator[]!
357  return static_cast<V *>((*res.second)[res.first]);
358 }
359 
370 template<class U, class V>
371 template<class U2>
373 {
374  TIter next(&containers);
375  TObject* obj = 0;
376  while((obj = next())) {
377  U* cont = dynamic_cast<U*>(obj);
378  if (!cont) continue;
379  if (IsUnderlyingInputObjectTypeCompatible(cont) == false) {
380  continue;
381  }
382 
383  int gindex = map.GetOffset(cont);
384  if (gindex >= 0) fGlobalIndexMap[gindex] = cont;
385  }
386 }
387 
398 template<class U, class V>
399 template<class U2>
401 {
402  if (IsUnderlyingInputObjectTypeCompatible(cont) == false) {
403  return;
404  }
405 
406  int gindex = map.GetOffset(cont);
407  if (gindex >= 0) fGlobalIndexMap[gindex] = cont;
408 }
409 
410 #endif /* AliEmcalContainerIndexMap.h */
411 #endif /* Hiding from CINT */
std::map< int, U * > fGlobalIndexMap
! Map between index and input object
std::pair< int, U * > LocalIndexFromGlobalIndex(const int globalIndex) const
Container or array to index mapping for AliEmcalContainer derived classes.
const TClonesArray * GetObject(const AliEmcalContainer *inputObject) const
int GetOffset(const U2 *inputObject) const
int GlobalIndexFromLocalIndex(const U *inputObject, const int localIndex) const
AliEmcalContainerIndexMap & operator=(AliEmcalContainerIndexMap map)
V * GetObjectFromGlobalIndex(const int globalIndex) const
TClass * fClass
Used to compare the type of V against the underlying input object type.
friend void swap(AliEmcalContainerIndexMap< X, Y > &first, AliEmcalContainerIndexMap< X, Y > &second)
void CopyMappingFrom(const AliEmcalContainerIndexMap< U2, V > &map, U *cont)
void swap(AliEmcalContainerIndexMap< X, Y > &first, AliEmcalContainerIndexMap< X, Y > &second)
int fOffset
Offset between each TClonesArray.
bool IsUnderlyingInputObjectTypeCompatible(const U *inputObject) const