G4VisAttributes::GetInvisible()

Hi,

I just want to report two tricky things which could help others to debug.

  1. I use G4VNestedParameterisation class to build the geometry, and in my own virtual method for ComputeMaterial(), I will call
    GetLogicalVolume()->SetVisAttributes( G4VisAttributes::GetInvisible() )

The tricky part is that SetVisAttributes() is overridden; there are two versions, one takes in reference one takes in pointer as the inputs. In the reference version, it will call new operator, while the pointer version does not. And I didn’t know G4VisAttributes::GetInvisible() return an object, not a pointer.

so my application breaks due to out of memory.
The solution is
GetLogicalVolume()->SetVisAttributes( & G4VisAttributes::GetInvisible() )
Just add “&”

  1. in the G4VNestedParameterisation.cc file line 64 to 70
G4Material* 
G4VNestedParameterisation::ComputeMaterial(const G4int repNo, 
                                                 G4VPhysicalVolume* currentVol,
                                           const G4VTouchable* parentTouch)
{
  return ComputeMaterial( currentVol, repNo, parentTouch );
  // the order should be repNO, currentVol, parentTouch 
}

while in G4VPVParameterisation.cc file line 85 to 87

virtual G4Material* ComputeMaterial(const G4int repNo, 
                                        G4VPhysicalVolume *currentVol,
                                        const G4VTouchable *parentTouch=0);

It seems the return has the wrong order.
the order should be repNO, currentVol, parentTouch
But it is a virtual function and so …

Thank you very much

  1. I use G4VNestedParameterisation class to build the geometry, and in my own virtual method for ComputeMaterial(), I will call
    GetLogicalVolume()->SetVisAttributes( G4VisAttributes::GetInvisible() )

You do NOT need to call SetVisAttributes() inside your parameterisation function. Simply call it -once- for the logical-volume(s) used in your parameterisation

  1. in the G4VNestedParameterisation.cc file line 64 to 70

    It seems the return has the wrong order.
    the order should be repNO, currentVol, parentTouch

WRONG. The implementation is correct.
The ComputeMaterial() method you refer to is the implementation of the virtual method from the base class G4VPVParameterisation, which should be expressed in terms of the ComputeMaterial() method in G4VNestedParameterisation (pure virtual and with inverted signature).

Dear gcosmo,

Thank you very much for your reply.

Actually, I am aware that I should pull SetVisAttributes() function out of ComputeMaterial() for just invoking it once in my parameterization class inherited from G4VNestedParameterisation.

I think to put this piece of code in the constructor.
But I am struggling to figure out how to loop through my 3D voxels in the constructor.
I need the index of each voxel to get material info, and then use material info to get color setting.

the above part can be done via G4VTouchable* parentTouch
e.g.

ComputeMaterial(
              G4VPhysicalVolume*  physVol, 
              const G4int         copyNo,
              const G4VTouchable* parentTouch ) {
....

G4int ix = parentTouch->GetReplicaNumber(0); // depth = 0
G4int iy = parentTouch->GetReplicaNumber(1); // depth = 1
G4int iz = copyNo;

unsigned long ivoxel = ix  + fNVoxelX*iy + fNVoxelX*fNVoxelY*iz;
int iMat = fMateIDs[ ivoxel ];  

But how can I do the similar thing in the constructor when G4Touchable is not available?
I will very appreciated if you could give me some suggestions.
Thank you~

Well, tracking and drawing are two different things. You can set vis attributes in the logical volume and they will, of course, be used in drawing, but in this case, if I have understood, there is only one logical volume for all the volumes represented by the parameterisation.
So if you want to colour the parameterised volumes by material (is this what you want?) I suggest you write a user vis action, which will be used only when drawing. Then, you can switch off the normal drawing:
/vis/geometry/set/visibility <logical-vol-name> ! false
and use the special drawing
/vis/scene/add/userAction <name>
Note: If you make the volumes transparent (which is a good way to see inside a 3D array of volumes) you will find a big performance penalty with Qt due to a bug we are fixing for the next release) but OGLSX should be OK.

Header file:
class MyVisAction: public G4VUserVisAction {
virtual void Draw();
};

Implementation file:
void MyVisAction::Draw()
{
G4VVisManager* pVisManager = G4VVisManager::GetConcreteInstance();
if (pVisManager) {
Then, in a loop over volumes, get solid, position and colour, then
G4VisAttributes visAtts(colour);
visAtts.SetForceSolid(true);
pVisManager->Draw(solid,visAtts,G4Translate3D(x,y,z));

Hope that helps.

John

Ooops. Forgot to say you have to register the user vis action. In the main program:
G4VisManager* visManager = new G4VisExecutive;
visManager->RegisterEndOfRunUserVisAction("MyName",new MyVisAction);