Newer
Older
// $Id: VolumeManager.cpp 513 2013-04-05 14:31:53Z gaede $
//====================================================================
// AIDA Detector description implementation for LCD
//--------------------------------------------------------------------
//
// Author : M.Frank
//
//====================================================================
// Framework include files
#include "DD4hep/VolumeManager.h"
#include "DD4hep/Printout.h"
Markus Frank
committed
#include "DD4hep/LCDD.h"
Markus Frank
committed
#include <cmath>
Markus Frank
committed
#include <iomanip>
using namespace DD4hep;
using namespace DD4hep::Geometry;
#define VOLUME_IDENTIFIER(id,mask) id
//#define VOLUME_IDENTIFIER(id,mask) id,mask
namespace {
Markus Frank
committed
struct Populator {
typedef VolumeManager::VolumeID VolumeID;
typedef vector<const TGeoNode*> Chain;
Markus Frank
committed
/// Reference to the LCDD instance
LCDD& m_lcdd;
/// Reference to the volume manager to be populated
VolumeManager m_volManager;
/// Set of already added entries
set<VolumeID> m_entries;
Populator(LCDD& lcdd, VolumeManager vm) : m_lcdd(lcdd), m_volManager(vm) {}
/// Populate the Volume manager
const DetElement::Children& c = e.children();
for(DetElement::Children::const_iterator i=c.begin(); i!=c.end(); ++i) {
DetElement de = (*i).second;
PlacedVolume pv = de.placement();
if ( pv.isValid() ) {
Markus Frank
committed
Chain chain;
PlacedVolume::VolIDs ids;
m_entries.clear();
scanPhysicalVolume(de, de, pv, ids, sd, chain);
printout(WARNING,"VolumeManager","++ Detector element %s of type %s has no placement.",
de.name(),de.type().c_str());
}
}
/// Find a detector element below with the corresponding placement
DetElement findElt(DetElement e, PlacedVolume pv) {
const DetElement::Children& c = e.children();
if ( e.placement().ptr() == pv.ptr() ) return e;
for(DetElement::Children::const_iterator i=c.begin(); i!=c.end(); ++i) {
DetElement de = (*i).second;
if ( de.placement().ptr() == pv.ptr() ) return de;
}
for(DetElement::Children::const_iterator i=c.begin(); i!=c.end(); ++i) {
DetElement de = findElt((*i).second,pv);
if ( de.isValid() ) return de;
}
return DetElement();
}
/// Scan a single physical volume and look for sensitive elements below
Markus Frank
committed
size_t scanPhysicalVolume(DetElement parent, DetElement e, PlacedVolume pv,
PlacedVolume::VolIDs ids, SensitiveDetector& sd, Chain& chain)
{
const TGeoNode* node = pv.ptr();
Markus Frank
committed
size_t count = 0;
Markus Frank
committed
Volume vol = pv.volume();
Markus Frank
committed
chain.push_back(node);
PlacedVolume::VolIDs pv_ids = pv.volIDs();
ids.PlacedVolume::VolIDs::Base::insert(ids.end(),pv_ids.begin(),pv_ids.end());
Markus Frank
committed
if ( vol.isSensitive() ) {
sd = vol.sensitiveDetector();
Readout ro = sd.readout();
Markus Frank
committed
if ( ro.isValid() ) {
add_entry(sd, parent, e, node, ids, chain);
++count;
Markus Frank
committed
}
Markus Frank
committed
else {
printout(WARNING,"VolumeManager",
Markus Frank
committed
"%s: Strange constellation volume %s is sensitive, but has no readout! sd:%p",
parent.name(), pv.volume().name(), sd.ptr());
Markus Frank
committed
}
}
for(Int_t idau=0, ndau=node->GetNdaughters(); idau<ndau; ++idau) {
TGeoNode* daughter = node->GetDaughter(idau);
if ( dynamic_cast<const PlacedVolume::Object*>(daughter) ) {
Markus Frank
committed
size_t cnt;
PlacedVolume pv_dau = Ref_t(daughter);
DetElement de_dau = findElt(e,daughter);
Markus Frank
committed
if ( de_dau.isValid() ) {
Chain dau_chain;
cnt = scanPhysicalVolume(parent, de_dau, pv_dau, ids, sd, dau_chain);
Markus Frank
committed
}
else {
cnt = scanPhysicalVolume(parent, e, pv_dau, ids, sd, chain);
}
if ( count == 0 && cnt>0 && !pv_ids.empty() ) {
add_entry(sd, parent, e, node, ids, chain);
Markus Frank
committed
}
count += cnt;
Markus Frank
committed
chain.pop_back();
Markus Frank
committed
return count;
Markus Frank
committed
pair<VolumeID,VolumeID> encoding(const IDDescriptor iddesc, const PlacedVolume::VolIDs& ids ) const {
Markus Frank
committed
//VolumeID volume_id = ~0x0ULL, mask = 0;
VolumeID volume_id = 0, mask = 0;
for(PlacedVolume::VolIDs::const_iterator i=ids.begin(); i!=ids.end(); ++i) {
const PlacedVolume::VolID& id = (*i);
IDDescriptor::Field f = iddesc.field(id.first);
Markus Frank
committed
VolumeID msk = f->mask();
int offset = f->offset();
// This pads the unused bits with '1' instead of '0':
// volume_id &= ~msk;
volume_id |= f->value(id.second<<offset)<<offset;
mask |= msk;
//volume_id &= f.encode(id.second);
//mask |= f.mask;
Markus Frank
committed
return make_pair(volume_id,mask);
}
void add_entry(DetElement parent, DetElement e,const TGeoNode* n,
const PlacedVolume::VolIDs& ids, const Chain& nodes)
Markus Frank
committed
{
Markus Frank
committed
Volume vol = PlacedVolume(n).volume();
SensitiveDetector sd = vol.sensitiveDetector();
add_entry(sd, parent,e,n,ids,nodes);
}
void add_entry(SensitiveDetector sd,
DetElement parent, DetElement e,const TGeoNode* n,
const PlacedVolume::VolIDs& ids, const Chain& nodes)
{
Readout ro = sd.readout();
IDDescriptor iddesc = ro.idSpec();
Markus Frank
committed
VolumeManager section = m_volManager.addSubdetector(parent,ro);
Markus Frank
committed
pair<VolumeID,VolumeID> code = encoding(iddesc, ids);
if ( m_entries.find(code.first) == m_entries.end() ) {
// This is the block, we effectively have to save for each physical volume with a VolID
VolumeManager::Context* context = new VolumeManager::Context;
DetElement::Object& o = parent._data();
context->identifier = code.first;
context->mask = code.second;
context->detector = parent;
context->element = e;
context->placement = Ref_t(n);
context->volID = ids;
context->path = nodes;
for(size_t i=nodes.size(); i>1; --i) { // Omit the placement of the parent DetElement
TGeoMatrix* m = nodes[i-1]->GetMatrix();
context->toWorld.MultiplyLeft(m);
}
context->toDetector = context->toWorld;
context->toDetector.MultiplyLeft(nodes[0]->GetMatrix());
context->toWorld.MultiplyLeft(o.worldTransformation());
//if ( parent.id() == 8 ) print_node(sd,parent,e,n,ids,nodes);
if ( !section.adoptPlacement(context) ) {
print_node(sd,parent,e,n,ids,nodes);
Markus Frank
committed
}
Markus Frank
committed
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
void find_entry(DetElement parent, DetElement e,const TGeoNode* n,
const PlacedVolume::VolIDs& ids, const Chain& nodes)
{
Volume vol = PlacedVolume(n).volume();
SensitiveDetector sd = vol.sensitiveDetector();
Readout ro = sd.readout();
IDDescriptor iddesc = ro.idSpec();
pair<VolumeID,VolumeID> code = encoding(iddesc, ids);
#if 0
VolumeID id = (VolumeID(rand())<<32) + VolumeID(rand());
id &= ~code.second;
id |= code.second;
VolumeID volID = id&code.first;
#else
VolumeID volID = code.first;
#endif
VolumeManager::Context* context = m_volManager.lookupContext(volID);
stringstream log;
if ( !context ) {
log << "CANNOT FIND volume:"
<< " Ptr:" << (void*)n
<< " [" << n->GetName() << "]"
<< " ID:" << (void*)volID
<< " Mask:" << (void*)code.second;
printout(ERROR,"VolumeManager",log.str().c_str());
return;
}
else if ( context->placement.ptr() != n ) {
log << "FOUND WRONG volume:"
<< " Ptr:" << (void*)context->placement.ptr()
<< " instead of " << (void*)n
<< " [" << context->placement.name()
<< " instead of " << n->GetName() << "]"
<< " ID:" << (void*)context->identifier
<< " instead of " << (void*)volID;
printout(ERROR,"VolumeManager",log.str().c_str());
return;
}
log << "Found volume:"
<< " Ptr:" << (void*)context->placement.ptr()
<< " [" << context->placement.name() << "]"
<< " ID:" << (void*)context->identifier
<< " Mask:" << (void*)context->mask;
printout(DEBUG,"VolumeManager",log.str().c_str());
}
Markus Frank
committed
void print_node(DetElement parent, DetElement e, const TGeoNode* n,
Markus Frank
committed
const PlacedVolume::VolIDs& ids, const Chain& nodes)
{
Volume vol = PlacedVolume(n).volume();
SensitiveDetector sd = vol.sensitiveDetector();
print_node(sd, parent, e, n, ids, nodes);
}
void print_node(SensitiveDetector sd, DetElement parent, DetElement e, const TGeoNode* n,
const PlacedVolume::VolIDs& ids, const Chain& nodes)
Markus Frank
committed
{
static int s_count = 0;
Markus Frank
committed
Readout ro = sd.readout();
Markus Frank
committed
const IDDescriptor& en = ro.idSpec();
Markus Frank
committed
PlacedVolume pv = Ref_t(n);
bool sensitive = pv.volume().isSensitive();
Markus Frank
committed
pair<VolumeID,VolumeID> code = encoding(en, ids);
IDDescriptor::VolumeID volume_id = code.first;
Markus Frank
committed
++s_count;
Markus Frank
committed
stringstream log;
log << s_count << ": " << e.name() << " de:" << e.ptr() << " ro:" << ro.ptr()
<< " pv:" << n->GetName() << " id:" << (void*)volume_id << " : ";
Markus Frank
committed
for(PlacedVolume::VolIDs::const_iterator i=ids.begin(); i!=ids.end(); ++i) {
const PlacedVolume::VolID& id = (*i);
IDDescriptor::Field f = ro.idSpec().field(id.first);
Markus Frank
committed
VolumeID value = f->value(volume_id);
log << id.first << "=" << id.second << "," << value
<< " [" << f->offset() << "," << f->width() << "] ";
Markus Frank
committed
}
Markus Frank
committed
log << " Sensitive:" << (sensitive ? "YES" : "NO");
printout(INFO,"VolumeManager",log.str().c_str());
Markus Frank
committed
#if 0
Markus Frank
committed
log.str("");
log << s_count << ": " << e.name() << " Detector GeoNodes:";
Markus Frank
committed
for(vector<const TGeoNode*>::const_iterator j=nodes.begin(); j!=nodes.end();++j)
Markus Frank
committed
log << (void*)(*j) << " ";
printout(INFO,"VolumeManager",log.str().c_str());
Markus Frank
committed
#endif
}
};
}
/// Default constructor
Markus Frank
committed
VolumeManager::Context::Context() : identifier(0), mask(~0x0ULL) {
}
/// Default destructor
VolumeManager::Context::~Context() {
}
/// Default constructor
Markus Frank
committed
VolumeManager::Object::Object(LCDD& l) : lcdd(l), top(0), sysID(0), flags(VolumeManager::NONE) {
}
/// Default destructor
VolumeManager::Object::~Object() {
Markus Frank
committed
Object* obj = dynamic_cast<Object*>(top);
bool isTop = obj == this;
bool hasTop = (flags&VolumeManager::ONE)==VolumeManager::ONE;
bool isSdet = (flags&VolumeManager::TREE)==VolumeManager::TREE && obj != this;
/// Cleanup volume tree
Markus Frank
committed
for_each(volumes.begin(),volumes.end(),DestroyObjects<VolIdentifier,Context*>());
Markus Frank
committed
volumes.clear();
/// Cleanup dependent managers
for_each(managers.begin(),managers.end(),DestroyHandles<VolumeID,VolumeManager>());
managers.clear();
subdetectors.clear();
}
/// Search the locally cached volumes for a matching ID
VolumeManager::Context* VolumeManager::Object::search(const VolIdentifier& id) const {
Context* context = 0;
Volumes::const_iterator i = volumes.find(id);
if ( i != volumes.end() )
context = (*i).second;
else if ( sysID == 8 ) {
//for(i=volumes.begin(); i!=volumes.end();++i)
// cout << (void*)(*i).first << " " << (*i).second->placement.name() << endl;
}
return context;
}
Markus Frank
committed
/// Search the locally cached volumes for a matching physical volume
VolumeManager::Context* VolumeManager::Object::search(const PlacedVolume pv) const {
PhysVolumes::const_iterator i = phys_volumes.find(pv.ptr());
if ( i != phys_volumes.end() )
return (*i).second;
return 0;
}
/// Initializing constructor to create a new object
Markus Frank
committed
VolumeManager::VolumeManager(LCDD& lcdd, const string& nam, DetElement elt, Readout ro, int flags)
Markus Frank
committed
Object* ptr = new Object(lcdd);
Markus Frank
committed
assign(ptr,nam,"VolumeManager");
Markus Frank
committed
Populator p(lcdd, *this);
Markus Frank
committed
Object& o = _data();
Markus Frank
committed
setDetector(elt, ro);
Markus Frank
committed
o.top = ptr;
o.flags = flags;
p.populate(elt);
}
}
/// Add a new Volume manager section according to a new subdetector
Markus Frank
committed
VolumeManager VolumeManager::addSubdetector(DetElement detector, Readout ro) {
if ( isValid() ) {
Object& o = _data();
Detectors::const_iterator i=o.subdetectors.find(detector);
if ( i == o.subdetectors.end() ) {
// First check all pre-conditions
if ( !ro.isValid() ) {
throw runtime_error("VolumeManager::addSubdetector: Only subdetectors with a "
"valid readout descriptor are allowed. [Invalid DetElement:"+det_name+"]");
}
PlacedVolume pv = detector.placement();
if ( !pv.isValid() ) {
throw runtime_error("VolumeManager::addSubdetector: Only subdetectors with a "
"valid placement are allowed. [Invalid DetElement:"+det_name+"]");
}
PlacedVolume::VolIDs::Base::const_iterator vit = pv.volIDs().find("system");
if ( vit == pv.volIDs().end() ) {
throw runtime_error("VolumeManager::addSubdetector: Only subdetectors with "
"valid placement VolIDs are allowed. [Invalid DetElement:"+det_name+"]");
Markus Frank
committed
i = o.subdetectors.insert(make_pair(detector,VolumeManager(o.lcdd,detector.name()))).first;
const PlacedVolume::VolID& id = (*vit);
VolumeManager m = (*i).second;
IDDescriptor::Field field = ro.idSpec().field(id.first);
Markus Frank
committed
if ( !field ) {
throw runtime_error("VolumeManager::addSubdetector: IdDescriptor of "+string(detector.name())+" has no field "+id.first);
}
Object& mo = m._data();
Markus Frank
committed
m.setDetector(detector,ro);
Markus Frank
committed
mo.top = o.top;
mo.flags = o.flags;
mo.system = field;
mo.sysID = id.second;
o.managers[mo.sysID] = m;
}
return (*i).second;
}
throw runtime_error("VolumeManager::addSubdetector: Failed to add subdetector section. [Invalid Manager Handle]");
}
/// Access the volume manager by cell id
VolumeManager VolumeManager::subdetector(VolumeID id) const {
if ( isValid() ) {
const Object& o = _data();
/// Need to perform a linear search, because the "system" tag width may vary between subdetectors
for(Detectors::const_iterator j=o.subdetectors.begin(); j != o.subdetectors.end(); ++j) {
const Object& mo = (*j).second._data();
Markus Frank
committed
//VolumeID sys_id = mo.system.decode(id);
VolumeID sys_id = mo.system->value(id<<mo.system->offset());
if ( sys_id == mo.sysID )
return (*j).second;
}
throw runtime_error("VolumeManager::subdetector(VolID): Attempt to access unknown subdetector section.");
}
throw runtime_error("VolumeManager::subdetector(VolID): Cannot assign ID descriptor [Invalid Manager Handle]");
}
/// Assign the top level detector element to this manager
Markus Frank
committed
void VolumeManager::setDetector(DetElement e, Readout ro) {
if ( isValid() ) {
if ( e.isValid() ) {
Object& o = _data();
o.id = ro.isValid() ? ro.idSpec() : IDDescriptor();
o.detector = e;
return;
}
throw runtime_error("VolumeManager::setDetector: Cannot assign invalid detector element [Invalid Handle]");
}
throw runtime_error("VolumeManager::setDetector: Cannot assign detector element [Invalid Manager Handle]");
}
/// Access the top level detector element
DetElement VolumeManager::detector() const {
if ( isValid() ) {
return _data().detector;
}
throw runtime_error("VolumeManager::detector: Cannot access DetElement [Invalid Handle]");
}
/// Assign IDDescription to VolumeManager structure
void VolumeManager::setIDDescriptor(IDDescriptor new_descriptor) const {
if ( isValid() ) {
if ( new_descriptor.isValid() ) { // Do NOT delete!
_data().id = new_descriptor;
return;
}
}
throw runtime_error("VolumeManager::setIDDescriptor: Cannot assign ID descriptor [Invalid Manager Handle]");
}
/// Access IDDescription structure
IDDescriptor VolumeManager::idSpec() const {
return _data().id;
}
Markus Frank
committed
/// Register physical volume with the manager (normally: section manager)
bool VolumeManager::adoptPlacement(VolumeID sys_id, Context* context) {
Markus Frank
committed
stringstream err;
Object& o = _data();
PlacedVolume pv = context->placement;
VolIdentifier vid(VOLUME_IDENTIFIER(context->identifier,context->mask));
Volumes::iterator i = o.volumes.find(vid);
Markus Frank
committed
#if 0
Markus Frank
committed
if ( (context->identifier&context->mask) != context->identifier ) {
err << "Bad context mask:" << (void*)context->mask << " id:" << (void*)context->identifier
<< " pv:" << pv.name() << " Sensitive:"
<< (pv.volume().isSensitive() ? "YES" : "NO") << endl;
Markus Frank
committed
goto Fail;
}
Markus Frank
committed
#endif
Markus Frank
committed
if ( i == o.volumes.end() ) {
o.volumes[vid] = context;
//o.phys_volumes[pv.ptr()] = context;
err << "Inserted new volume:" << setw(6) << left << o.volumes.size()
<< " Ptr:" << (void*)context->placement.ptr()
<< " [" << context->placement.name() << "]"
<< " ID:" << (void*)context->identifier
<< " Mask:" << (void*)context->mask;
printout(DEBUG,"VolumeManager",err.str().c_str());
Markus Frank
committed
}
err << "Attempt to register twice volume with identical volID "
<< (void*)context->identifier << " Mask:" << (void*)context->mask
<< " to detector " << o.detector.name()
<< " ptr:" << (void*)pv.ptr() << " -- " << (*i).second->placement.ptr()
Markus Frank
committed
<< " pv:" << pv.name() << " clashes with " << (*i).second->placement.name()
<< " Sensitive:" << (pv.volume().isSensitive() ? "YES" : "NO") << endl;
Markus Frank
committed
goto Fail;
Fail:
{
err << "++++ VolIDS:";
const PlacedVolume::VolIDs::Base& ids = context->volID;
for(PlacedVolume::VolIDs::Base::const_iterator vit = ids.begin(); vit != ids.end(); ++vit)
err << (*vit).first << "=" << (*vit).second << "; ";
}
Markus Frank
committed
printout(ERROR,"VolumeManager","++++[!!!] adoptPlacement: %s",err.str().c_str());
Markus Frank
committed
// throw runtime_error(err.str());
Markus Frank
committed
}
/// Register physical volume with the manager (normally: section manager)
bool VolumeManager::adoptPlacement(Context* context) {
stringstream err;
if ( isValid() ) {
Object& o = _data();
if ( context ) {
Markus Frank
committed
if ( (o.flags&ONE) == ONE ) {
VolumeManager top(Ref_t(o.top));
return top.adoptPlacement(context);
}
if ( (o.flags&TREE) == TREE ) {
Markus Frank
committed
bool isTop = ptr() == o.top;
Markus Frank
committed
if ( !isTop ) {
VolumeID sys_id = o.system->value(context->identifier);
if ( sys_id == o.sysID ) {
return adoptPlacement(sys_id,context);
}
Markus Frank
committed
VolumeManager top(Ref_t(o.top));
Markus Frank
committed
return top.adoptPlacement(context);
Markus Frank
committed
for(Managers::iterator j=o.managers.begin(); j != o.managers.end(); ++j) {
Object& m = (*j).second._data();
VolumeID sid = m.system->value(context->identifier);
if ( (*j).first == sid ) {
return (*j).second.adoptPlacement(sid,context);
}
Markus Frank
committed
return false;
Markus Frank
committed
err << "Failed to add new physical volume to detector:" << o.detector.name() << " [Invalid Context]";
err << "Failed to add new physical volume [Invalid Manager Handle]";
Markus Frank
committed
throw runtime_error(err.str());
/// Lookup the context, which belongs to a registered physical volume.
VolumeManager::Context* VolumeManager::lookupContext(VolumeID volume_id) const {
Markus Frank
committed
Context* c = 0;
const Object& o = _data();
Markus Frank
committed
bool is_top = o.top == ptr();
bool one_tree = (o.flags&ONE) == ONE;
if ( !is_top && one_tree ) {
Markus Frank
committed
return VolumeManager(Ref_t(o.top)).lookupContext(volume_id);
}
Markus Frank
committed
VolIdentifier id(VOLUME_IDENTIFIER(volume_id,~0x0ULL));
/// First look in our own volume cache if the entry is found.
Markus Frank
committed
c = o.search(id);
Markus Frank
committed
/// Second: look in the subdetector volume cache if the entry is found.
Markus Frank
committed
if ( !one_tree ) {
for(Detectors::const_iterator j=o.subdetectors.begin(); j != o.subdetectors.end(); ++j) {
if ( (c=(*j).second._data().search(id)) != 0 )
return c;
}
stringstream err;
err << "VolumeManager::lookupContext: Failed to search Volume context [Unknown identifier]"
<< (void*)volume_id;
throw runtime_error(err.str());
throw runtime_error("VolumeManager::lookupContext: Failed to search Volume context [Invalid Manager Handle]");
}
/// Lookup a physical (placed) volume identified by its 64 bit hit ID
PlacedVolume VolumeManager::lookupPlacement(VolumeID volume_id) const {
Context* c = lookupContext(volume_id);
return c->placement;
}
/// Lookup a top level subdetector detector element according to a contained 64 bit hit ID
DetElement VolumeManager::lookupDetector(VolumeID volume_id) const {
Context* c = lookupContext(volume_id);
return c->detector;
}
/// Lookup the closest subdetector detector element in the hierarchy according to a contained 64 bit hit ID
DetElement VolumeManager::lookupDetElement(VolumeID volume_id) const {
Context* c = lookupContext(volume_id);
return c->element;
}
/// Access the transformation of a physical volume to the world coordinate system
const TGeoMatrix& VolumeManager::worldTransformation(VolumeID volume_id) const {
Context* c = lookupContext(volume_id);
return c->toWorld;
}
Markus Frank
committed
/// Enable printouts for debugging
std::ostream& DD4hep::Geometry::operator<<(std::ostream& os, const VolumeManager& m) {
const VolumeManager::Object& o = *m.data<VolumeManager::Object>();
VolumeManager::Object* top = dynamic_cast<VolumeManager::Object*>(o.top);
bool isTop = top == &o;
bool hasTop = (o.flags&VolumeManager::ONE)==VolumeManager::ONE;
bool isSdet = (o.flags&VolumeManager::TREE)==VolumeManager::TREE && top != &o;
string prefix(isTop ? "" : "++ ");
Markus Frank
committed
os << prefix
<< (isTop ? "TOP Level " : "Secondary ")
<< "Volume manager:" << &o << " " << o.detector.name()
<< " IDD:" << o.id.toString()
<< " SysID:" << (void*)o.sysID << " "
<< o.managers.size() << " subsections "
<< o.volumes.size() << " placements ";
if ( !(o.managers.empty() && o.volumes.empty()) ) os << endl;
Markus Frank
committed
for(VolumeManager::Volumes::const_iterator i = o.volumes.begin(); i!=o.volumes.end(); ++i) {
const VolumeManager::Context* c = (*i).second;
PlacedVolume pv = c->placement;
Markus Frank
committed
os << prefix
<< "PV:" << setw(32) << left << pv.name()
<< " id:" << setw(18) << left << (void*)c->identifier
<< " mask:" << setw(18) << left << (void*) c->mask << endl;
Markus Frank
committed
}
for(VolumeManager::Managers::const_iterator i = o.managers.begin(); i!=o.managers.end(); ++i)
Markus Frank
committed
os << prefix << (*i).second << endl;
Markus Frank
committed
return os;
}
Markus Frank
committed
#if 0
It was wishful thinking, the implementation of the reverse lookups would be as simple.
Hence the folling calls are removed for the time being.
Markus Frank
/** This set of functions is required when reading/analyzing
* already created hits which have a VolumeID attached.
*/
/// Lookup the context, which belongs to a registered physical volume.
Context* lookupContext(PlacedVolume vol) const throw();
/// Access the physical volume identifier from the placed volume
VolumeID lookupID(PlacedVolume vol) const;
/// Lookup a top level subdetector detector element according to a contained 64 bit hit ID
DetElement lookupDetector(PlacedVolume vol) const;
/// Lookup the closest subdetector detector element in the hierarchy according to a contained 64 bit hit ID
DetElement lookupDetElement(PlacedVolume vol) const;
/// Access the transformation of a physical volume to the world coordinate system
const TGeoMatrix& worldTransformation(PlacedVolume vol) const;
Markus Frank
committed
/// Lookup the context, which belongs to a registered physical volume.
VolumeManager::Context* VolumeManager::lookupContext(PlacedVolume pv) const throw() {
if ( isValid() ) {
Context* c = 0;
const Object& o = _data();
if ( o.top != ptr() && (o.flags&ONE) == ONE ) {
return VolumeManager(Ref_t(o.top)).lookupContext(pv);
}
/// First look in our own volume cache if the entry is found.
c = o.search(pv);
if ( c ) return c;
/// Second: look in the subdetector volume cache if the entry is found.
for(Detectors::const_iterator j=o.subdetectors.begin(); j != o.subdetectors.end(); ++j) {
if ( (c=(*j).second._data().search(pv)) != 0 )
return c;
}
throw runtime_error("VolumeManager::lookupContext: Failed to search Volume context [Unknown identifier]");
}
throw runtime_error("VolumeManager::lookupContext: Failed to search Volume context [Invalid Manager Handle]");
Markus Frank
committed
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
}
/// Access the physical volume identifier from the placed volume
VolumeManager::VolumeID VolumeManager::lookupID(PlacedVolume vol) const {
Context* c = lookupContext(vol);
return c->identifier;
}
/// Lookup a top level subdetector detector element according to a contained 64 bit hit ID
DetElement VolumeManager::lookupDetector(PlacedVolume vol) const {
Context* c = lookupContext(vol);
return c->detector;
}
/// Lookup the closest subdetector detector element in the hierarchy according to a contained 64 bit hit ID
DetElement VolumeManager::lookupDetElement(PlacedVolume vol) const {
Context* c = lookupContext(vol);
return c->element;
}
/// Access the transformation of a physical volume to the world coordinate system
const TGeoMatrix& VolumeManager::worldTransformation(PlacedVolume vol) const {
Context* c = lookupContext(vol);
return c->toWorld;
}