Does TClonesArray::ConstructedAt exist?

Hi,

I am trying to speed up my analysis code and I ran into
root.cern.ch/root/html/TClonesAr … structedAt
which might address my issues. However, I cannot find this method neither in ROOT 5.28/00e (the one coming with Athena) or ROOT 5.30/03 (sourced from AFS).

How can I use it?

Hi,

ConstrutedAt is not available in v5.28 not v5.30 (you can double check by browsing the reference guide) as it was implemented after the release of v5.30. To use it, you need to either use the svn trunk or to ue the upcoming v5.32.

Cheers,
Philippe.

Dear Philippe,
thank you for the information! Would it be safe to manually define a function in 5.28 in my code, such as

TObject *TClonesArrayConstructedAt(TClonesArray *array, Int_t idx) { TObject *obj = (*array)[idx]; if (obj && obj->TestBit(TObject::kNotDeleted)) { // obj->Clear("C"); return obj; } return (array->GetClass()) ? static_cast<TObject*>(array->GetClass()->New(obj)) : 0; }

?

I tried to do this but it seems not to work if I uncomment obj->Clear(“C”).
I am dealing with a class which inherits from a class containing std::vectors (and I defined the Clear methor for that mother class), am I doing it in the TClonesArray philosophy?

Hi Rene,

Unfortunately, not really, as the result of ‘obj->TestBit(TObject::kNotDeleted)’ is random in v5.28/v5.30 before the first initialization of the object. In the trunk we need to add:[code] fKeep->fCont[idx] = (TObject*) TStorage::ObjectAlloc(fClass->Size());

  •  // Reset the bit so that:
    
  •  //    obj = myClonesArray[i];
    
  •  //    obj->TestBit(TObject::kNotDeleted)
    
  •  // will behave correctly.
    
  •  memset(fKeep->fCont[idx], 0, sizeof(TObject));  // TClonesArray requires the class to start with the TObject part.
    
  • }[/code]in the code called be operator [].

Cheers,
Philippe.

uhm, so if I understand correctly with 5.28/5.30 there is no workaround to speed up dealing with TClonesArrays?
what I am doing (if it might help) is: I read from my ntuple some TClonesArray branches (containing, let’s say, a class TElectron) but I want to apply energy smearing on them, so I hold in memory a TClonesArray of a class TSmearedElectron inheriting from TElectron; for each event I read the electrons and fill properly the smearedelectrons, but of course this is a slow job… any suggestions?

Hi,

The only way in v5.28/v5.30 where you can save time in the construction of the object is to avoid using Clear and instead manipulated the end of the TClonesArray (with RemoveAt) to remove only the last elements (when needed) and to have to reconstructed only the missing elements.

Cheers,
Philippe.

so it is correct to use something like

[code] // loop on electrons within the event
for (Int_t i = 0; i < n_electrons; i++) {
// create a new element only if i is out of TClonesArray’s bounds
Bool_t isNew = kFALSE;
if (i >= fSmearedElectron->GetLast()) {
new((*fSmearedElectron)[i]) SmearedElectron();
isNew = kTRUE;
} // otherwise we already created an object in that position
// and since we never run Clear over the array, we can be sure an
// object is allocated at position i, so we don’t need to call again
// SmearedElectron::SmearedElectron constructor

  // retrieve a pointer to this new object
  SmearedElectron *obj = (SmearedElectron*)((*fSmearedElectron)[i]);

  // if the object was already there, clear the dynamic arrays it contains, to
  // avoid memory leak
  if (!isNew) {
    obj->Clear(); // this method empties std::vector members of SmearedElectron
  }

  // now do what must be done
  obj->CopyFrom(Electron(i)); // copies the ordinary electron in the smeared one
  ApplySmearing(obj); // applies energy smearing

}

// truncate TClonesArray to the maximum number of entries specified (40)
for (Int_t i = 40; i < fSmearedElectron->GetLast(); i++) {
fSmearedElectron->RemoveAt(i);
}[/code]

?

Yes, that should work.

Cheers,
Philippe.

do you confirm RemoveAt updates the TClonesArray in such a way that GetLast() is properly updated?
I mean, if I have GetLast() = 65, and I loop over i from 40 to 64 calling RemoveAt(i), after the loop I still have GetLast() = 65…

actually looping from 65 to 40 does work…