Align volumes containing daughters

Hello,
I’ve just resumed working on a small ROOT project (using v4.03.02) using the geometry facilities of ROOT.
My problem is to shift around a volume via TGeoPhysicalNode::Align() which contains two daughters. I do not know how this is supposed to be coded, as just creating one physical node for the mother and aligning it doesn’t work.
Like this:

//geometry creation
top = gGeoManager->MakeBox("TOP",Vac,2 * meter, 2 * meter, 2 * meter);
sct = gGeoManager->MakeBox("SCT",Vac,10 * cm,10 * cm,1 * cm);
sct_wafer = gGeoManager->MakeTrap("SCT_Wafer", Si, ModuleHalfLenghtZ, ...

combi1 = new TGeoCombiTrans(0, 0,  482.5 * micron, r_phi);
combi2 = new TGeoCombiTrans(0, 0, -482.5 * micron,stereo);

sct->AddNode(sct_wafer,1,combi1);
sct->AddNode(sct_wafer,2,combi2); //sct contains two daughters
top->AddNode(sct,1);

gGeoManager->SetTopVolume(top);
gGeoManager->CloseGeometry();

node = gGeoManager->MakePhysicalNode("/TOP_1/SCT_1");


//aligning - to be called often
if (node->IsAligned())
  {
		ph = (TGeoCombiTrans*)node->GetNode()->GetMatrix();
  }	else {
		ph = new TGeoCombiTrans();
  }

ph->SetTranslation(SCT_Pos_x,SCT_Pos_y,SCT_Pos_z);
node-> Align(ph);

I’ve also tried to create PhysicalNodes for the daughters as well with no noticeable effect. Maybe I don’t really understand the hint in the documentation of TGeoPhysicalNode::Align()

The simplest solution would be to align just the two daughters instead of the mother volume… Is there a more elegant way, as this gets rather complicated for more than just two daughter volumes?

Thanks very much
Tobias

Hi Tobias,

Your implementation should work. Here is a macro based on yours, where I just put in some numbers in order to run:

void testal()
{
TGeoManager *geom = new TGeoManager("geom","test");
//geometry creation
TGeoVolume *top,*sct,*sct_wafer;
TGeoCombiTrans *combi1,*combi2,*ph;
Double_t cm = 1.0;
Double_t meter = 100.0*cm;
Double_t micron = 1.E-6 * meter;
TGeoRotation *r_phi = new TGeoRotation();
r_phi->RotateZ(15);
TGeoRotation *stereo = new TGeoRotation();
TGeoMaterial *mvac = new TGeoMaterial("vac",0,0,0);
TGeoMedium *Vac = new TGeoMedium("Vac",1,mvac);
top = gGeoManager->MakeBox("TOP",Vac,2 * meter, 2 * meter, 2 * meter);
sct = gGeoManager->MakeBox("SCT",Vac,10 * cm,10 * cm,1 * cm);
sct_wafer = gGeoManager->MakeTrd1("SCT_Wafer", Vac, 5,3,5,50*micron);

combi1 = new TGeoCombiTrans(0, 0,  482.5 * micron, r_phi);
combi2 = new TGeoCombiTrans(0, 0, -482.5 * micron,stereo);

sct->AddNode(sct_wafer,1,combi1);
sct->AddNode(sct_wafer,2,combi2); //sct contains two daughters
top->AddNode(sct,1);

gGeoManager->SetTopVolume(top);
gGeoManager->CloseGeometry();
TGeoPhysicalNode *node = gGeoManager->MakePhysicalNode("/TOP_1/SCT_1");


//aligning - to be called often
if (node->IsAligned())
  {
      ph = (TGeoCombiTrans*)node->GetNode()->GetMatrix();
  }   else {
      ph = new TGeoCombiTrans();
  }

ph->SetTranslation(10,10,10);
node-> Align(ph);
top->Draw();
gPad->GetView()->ShowAxis();
}

You should get a picture where your 2 layers are positioned at (10,10,10). Now from the root prompt do the
following:

TGeoPhysicalNode *node = (TGeoPhysicalNode*)gGeoManager->GetListOfPhysicalNodes()->At(0);
TGeoCombiTrans *c = (TGeoCombiTrans*)node->GetNode()->GetMatrix();
c->SetTranslation(-10,0,0);
node->Align(c);
gPad->Modified();

The pads will move now at -10. At least with the latest release.
Which version of ROOT are you using ?

Regards,

yes, you’re right. I’m using 4.03.02 (but also have access to 5.06) and your example also works with me and v4. Maybe there’s some bug at another place in my program that I’m missing.
I’ll investigate that…

Thanks for your help
Tobias

Hello again,
I’ve investigated this a bit further.
My small program uses the tracking capabilities of ROOT to determine the local coordinates where straightline tracks hit the volumes. As it is not very clever, it relies on the correct ordering of the crossed voumes. I’ve found out that if one places the volume “sct” to, say, (0, 0, -500), the first point I reach after a step:

gGeoManager->InitTrack(0,0,0, ParticleDir_x, ParticleDir_y, ParticleDir_z);
TGeoNode *NextBoundary = gGeoManager->FindNextBoundary();
if (NextBoundary)
{
  NextBoundary->Print();
  TGeoNode *HitNode = gGeoManager->Step(kTRUE,kTRUE);
  HitPoint = gGeoManager->GetCurrentPoint();
  cout<<"Hitpoint global: "<<HitPoint[0]<<", "<<HitPoint[1]<<", "<<HitPoint[2]<<endl;
//...
}

is the “wafer” at some global position around (0, 0, -.34), which is the (z translation inside sct - Halfwidth in Z), just like it is for a “wafer” positioned around the origin. Also it crosses boundaries in diffferent orders and so doesn’t work.

Up to that moment, I didn’t draw geometry any more because I just needed the calculation. As I now just inserted a tiny top->Draw() only once after geometry creation and before the first node->Align() is called, everything worked fine and I reach with the first step points around (something, something, -500), which is expected. The program seems to work now. (in both ROOT versions, v4.03 and v5.06)

My questions:

  • does the Tracking only know about my positioned volumes after I’ve drawn them once?
  • Can I also get this effect without drawing a canvas (good for remote connections), e.g. by calling some update method for the geometry?

thanks very much again,
it’s really good to know that the experts are such active and helping in the forum…

Tobias

Hi Tobias,

The answers to your questions are: no, you do not need to draw anything (and it is even not at all recommended) when you do tracking. Tracking has nothing to do with drawing.

It is hard to help you if you do not send me a simple macro that I can run to reproduce your problem. Please try to do that…

Cheers,

Hi Andrei,
here you are, I’ve attached the file.
Now I’m completely going crazy… This macro works only if I run it a second time…
But if you comment away line 70, it does not give the right numbers at all. Hope you see the problem.

(all with v5.06 @CERN)

Cheers,
Tobias
aligntestmacro.cpp (5.64 KB)

Hi Tobias,

It was rather hard to find the problem… Here it is:

When you do : top->Draw() the geometry tree is parsed in order to draw all elements and the last state of the modeler will be /TOP_1/SCT_1/SCT_Wafer_2. The corresponding matrices for all elements in this branch are cached and used from cache for your first query InitTrack. The result is that the navigation will ignore the new matrix of SCT_1 that you have just changed by calling Align() method. If you comment out the Draw() call, the state of the modeller will be /TOP_1 which does not cache any matrix - so you get correct results. To force the modeler using the correct new matrix, you just have to do:

gGeoManager->CdTop();

just after line 141: node->Align(ph);
Doing this will make your code work no matter if you do drawing or not. I will provide a patch in CVS to protect cases when people are mixing alignment with tracking (use case that was not really foreseen…). Meanwhile just use the CdTop().

Cheers,

wow, everything seems to work fine now. Great!
Thanks
Tobias