| 1 | <!-- ******************************************************** -->
|
|---|
| 2 | <!-- -->
|
|---|
| 3 | <!-- [History] -->
|
|---|
| 4 | <!-- Changed by: Gabriele Cosmo, 18-Apr-2005 -->
|
|---|
| 5 | <!-- Converted to DocBook: Katsuya Amako, Aug-2006 -->
|
|---|
| 6 | <!-- -->
|
|---|
| 7 | <!-- ******************************************************** -->
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 | <!-- ******************* Section (Level#2) ****************** -->
|
|---|
| 11 | <sect2 id="sect.Geom.Navig">
|
|---|
| 12 | <title>
|
|---|
| 13 | The Geometry Navigator
|
|---|
| 14 | </title>
|
|---|
| 15 |
|
|---|
| 16 | <para>
|
|---|
| 17 | Navigation through the geometry at tracking time is implemented
|
|---|
| 18 | by the class <literal>G4Navigator</literal>. The navigator is used to locate
|
|---|
| 19 | points in the geometry and compute distances to geometry
|
|---|
| 20 | boundaries. At tracking time, the navigator is intended to be the
|
|---|
| 21 | only point of interaction with tracking.
|
|---|
| 22 | </para>
|
|---|
| 23 |
|
|---|
| 24 | <para>
|
|---|
| 25 | Internally, the G4Navigator has several private helper/utility
|
|---|
| 26 | classes:
|
|---|
| 27 |
|
|---|
| 28 | <itemizedlist spacing="compact">
|
|---|
| 29 | <listitem><para>
|
|---|
| 30 | <emphasis role="bold">G4NavigationHistory</emphasis> - stores the compounded
|
|---|
| 31 | transformations, replication/parameterisation information, and
|
|---|
| 32 | volume pointers at each level of the hierarchy to the current
|
|---|
| 33 | location. The volume types at each level are also stored - whether
|
|---|
| 34 | normal (placement), replicated or parameterised.
|
|---|
| 35 | </para></listitem>
|
|---|
| 36 | <listitem><para>
|
|---|
| 37 | <emphasis role="bold">G4NormalNavigation</emphasis> - provides location &
|
|---|
| 38 | distance computation functions for geometries containing 'placement'
|
|---|
| 39 | volumes, with no voxels.
|
|---|
| 40 | </para></listitem>
|
|---|
| 41 | <listitem><para>
|
|---|
| 42 | <emphasis role="bold">G4VoxelNavigation</emphasis> - provides location and distance
|
|---|
| 43 | computation functions for geometries containing 'placement'
|
|---|
| 44 | physical volumes with voxels. Internally a stack of voxel
|
|---|
| 45 | information is maintained. Private functions allow for isotropic
|
|---|
| 46 | distance computation to voxel boundaries and for computation of the
|
|---|
| 47 | 'next voxel' in a specified direction.
|
|---|
| 48 | </para></listitem>
|
|---|
| 49 | <listitem><para>
|
|---|
| 50 | <emphasis role="bold">G4ParameterisedNavigation</emphasis> - provides location and
|
|---|
| 51 | distance computation functions for geometries containing
|
|---|
| 52 | parameterised volumes with voxels. Voxel information is maintained
|
|---|
| 53 | similarly to <literal>G4VoxelNavigation</literal>, but computation can also
|
|---|
| 54 | be simpler by adopting voxels to be one level deep only
|
|---|
| 55 | (<emphasis>unrefined</emphasis>, or 1D optimisation)
|
|---|
| 56 | </para></listitem>
|
|---|
| 57 | <listitem><para>
|
|---|
| 58 | <emphasis role="bold">G4ReplicaNavigation</emphasis> - provides location and distance
|
|---|
| 59 | computation functions for replicated volumes.
|
|---|
| 60 | </para></listitem>
|
|---|
| 61 | </itemizedlist>
|
|---|
| 62 | </para>
|
|---|
| 63 |
|
|---|
| 64 | <para>
|
|---|
| 65 | In addition, the navigator maintains a set of flags for
|
|---|
| 66 | exiting/entry optimisation. A navigator is not a singleton class;
|
|---|
| 67 | this is mainly to allow a design extension in future (e.g
|
|---|
| 68 | geometrical event biasing).
|
|---|
| 69 | </para>
|
|---|
| 70 |
|
|---|
| 71 |
|
|---|
| 72 | <!-- ******************* Section (Level#3) ****************** -->
|
|---|
| 73 | <sect3 id="sect.Geom.Navig.NavigTrack">
|
|---|
| 74 | <title>
|
|---|
| 75 | Navigation and Tracking
|
|---|
| 76 | </title>
|
|---|
| 77 |
|
|---|
| 78 | <para>
|
|---|
| 79 | The main functions required for tracking in the geometry are
|
|---|
| 80 | described below. Additional functions are provided to return the
|
|---|
| 81 | net transformation of volumes and for the creation of touchables.
|
|---|
| 82 | None of the functions implicitly requires that the geometry be
|
|---|
| 83 | described hierarchically.
|
|---|
| 84 |
|
|---|
| 85 | <itemizedlist spacing="compact">
|
|---|
| 86 | <listitem><para>
|
|---|
| 87 | <emphasis role="bold">SetWorldVolume()</emphasis>
|
|---|
| 88 | <para>
|
|---|
| 89 | Sets the first volume in the hierarchy. It must be unrotated and
|
|---|
| 90 | untranslated from the origin.
|
|---|
| 91 | </para>
|
|---|
| 92 | </para></listitem>
|
|---|
| 93 | <listitem><para>
|
|---|
| 94 | <emphasis role="bold">LocateGlobalPointAndSetup()</emphasis>
|
|---|
| 95 | <para>
|
|---|
| 96 | Locates the volume containing the specified global point. This
|
|---|
| 97 | involves a traverse of the hierarchy, requiring the computation of
|
|---|
| 98 | compound transformations, testing replicated and parameterised
|
|---|
| 99 | volumes (etc). To improve efficiency this search may be performed
|
|---|
| 100 | relative to the last, and this is the recommended way of calling
|
|---|
| 101 | the function. A 'relative' search may be used for the first call of
|
|---|
| 102 | the function which will result in the search defaulting to a search
|
|---|
| 103 | from the root node of the hierarchy. Searches may also be performed
|
|---|
| 104 | using a <literal>G4TouchableHistory</literal>.
|
|---|
| 105 | </para>
|
|---|
| 106 | </para></listitem>
|
|---|
| 107 | <listitem><para>
|
|---|
| 108 | <emphasis role="bold">LocateGlobalPointAndUpdateTouchableHandle()</emphasis>
|
|---|
| 109 | <para>
|
|---|
| 110 | First, search the geometrical hierarchy like the above method
|
|---|
| 111 | <literal>LocateGlobalPointAndSetup()</literal>. Then use the volume found and
|
|---|
| 112 | its navigation history to update the touchable.
|
|---|
| 113 | </para>
|
|---|
| 114 | </para></listitem>
|
|---|
| 115 | <listitem><para>
|
|---|
| 116 | <emphasis role="bold">ComputeStep()</emphasis>
|
|---|
| 117 | <para>
|
|---|
| 118 | Computes the distance to the next boundary intersected along the
|
|---|
| 119 | specified unit direction from a specified point. The point must be
|
|---|
| 120 | have been located prior to calling <literal>ComputeStep()</literal>.
|
|---|
| 121 | </para>
|
|---|
| 122 | <para>
|
|---|
| 123 | When calling <literal>ComputeStep()</literal>, a proposed physics step is
|
|---|
| 124 | passed. If it can be determined that the first intersection lies at
|
|---|
| 125 | or beyond that distance then <literal>kInfinity</literal> is returned. In any
|
|---|
| 126 | case, if the returned step is greater than the physics step, the
|
|---|
| 127 | physics step must be taken.
|
|---|
| 128 | </para>
|
|---|
| 129 | </para></listitem>
|
|---|
| 130 | <listitem><para>
|
|---|
| 131 | <emphasis role="bold">SetGeometricallyLimitedStep()</emphasis>
|
|---|
| 132 | <para>
|
|---|
| 133 | Informs the navigator that the last computed step was taken in its
|
|---|
| 134 | entirety. This enables entering/exiting optimisation, and should be
|
|---|
| 135 | called prior to calling <literal>LocateGlobalPointAndSetup()</literal>.
|
|---|
| 136 | </para>
|
|---|
| 137 | </para></listitem>
|
|---|
| 138 | <listitem><para>
|
|---|
| 139 | <emphasis role="bold">CreateTouchableHistory()</emphasis>
|
|---|
| 140 | <para>
|
|---|
| 141 | Creates a <literal>G4TouchableHistory</literal> object, for which the caller
|
|---|
| 142 | has deletion responsibility. The 'touchable' volume is the volume
|
|---|
| 143 | returned by the last Locate operation. The object includes a copy
|
|---|
| 144 | of the current NavigationHistory, enabling the efficient relocation
|
|---|
| 145 | of points in/close to the current volume in the hierarchy.
|
|---|
| 146 | </para>
|
|---|
| 147 | </para></listitem>
|
|---|
| 148 | </itemizedlist>
|
|---|
| 149 | </para>
|
|---|
| 150 |
|
|---|
| 151 | <para>
|
|---|
| 152 | As stated previously, the navigator makes use of utility classes to
|
|---|
| 153 | perform location and step computation functions. The different
|
|---|
| 154 | navigation utilities manipulate the <literal>G4NavigationHistory</literal>
|
|---|
| 155 | object.
|
|---|
| 156 | </para>
|
|---|
| 157 |
|
|---|
| 158 | <para>
|
|---|
| 159 | In <literal>LocateGlobalPointAndSetup()</literal> the process of locating a
|
|---|
| 160 | point breaks down into three main stages - optimisation,
|
|---|
| 161 | determination that the point is contained with a subtree (mother
|
|---|
| 162 | and daughters), and determination of the actual containing
|
|---|
| 163 | daughter. The latter two can be thought of as scanning first 'up'
|
|---|
| 164 | the hierarchy until a volume that is guaranteed to contain the
|
|---|
| 165 | point is found, and then scanning 'down' until the actual volume
|
|---|
| 166 | that contains the point is found.
|
|---|
| 167 | </para>
|
|---|
| 168 |
|
|---|
| 169 | <para>
|
|---|
| 170 | In <literal>ComputeStep()</literal> three types of computation are treated
|
|---|
| 171 | depending on the current containing volume:
|
|---|
| 172 |
|
|---|
| 173 | <itemizedlist spacing="compact">
|
|---|
| 174 | <listitem><para>
|
|---|
| 175 | The volume contains normal (placement) daughters (or none)
|
|---|
| 176 | </para></listitem>
|
|---|
| 177 | <listitem><para>
|
|---|
| 178 | The volume contains a single parameterised volume object,
|
|---|
| 179 | representing many volumes
|
|---|
| 180 | </para></listitem>
|
|---|
| 181 | <listitem><para>
|
|---|
| 182 | The volume is a replica and contains normal (placement) daughters
|
|---|
| 183 | </para></listitem>
|
|---|
| 184 | </itemizedlist>
|
|---|
| 185 | </para>
|
|---|
| 186 |
|
|---|
| 187 | </sect3>
|
|---|
| 188 |
|
|---|
| 189 | <!-- ******************* Section (Level#3) ****************** -->
|
|---|
| 190 | <sect3 id="sect.Geom.Navig.LocPnt">
|
|---|
| 191 | <title>
|
|---|
| 192 | Using the navigator to locate points
|
|---|
| 193 | </title>
|
|---|
| 194 |
|
|---|
| 195 | <para>
|
|---|
| 196 | More than one navigator objects can be created inside an application; these
|
|---|
| 197 | navigators can act independently for different purposes. The main navigator
|
|---|
| 198 | which is "<emphasis>activated</emphasis> automatically at the startup of a
|
|---|
| 199 | simulation program is the navigator used for the
|
|---|
| 200 | <emphasis>tracking</emphasis> and attached the world volume
|
|---|
| 201 | of the main tracking (or <emphasis>mass</emphasis>) geometry.
|
|---|
| 202 | </para>
|
|---|
| 203 |
|
|---|
| 204 | <para>
|
|---|
| 205 | The navigator for tracking can be retrieved at any state of the application
|
|---|
| 206 | by messagging the <literal>G4TransportationManager</literal>:
|
|---|
| 207 |
|
|---|
| 208 | <informalexample>
|
|---|
| 209 | <programlisting>
|
|---|
| 210 | G4Navigator* tracking_navigator =
|
|---|
| 211 | G4TransportationManager::GetInstance()->GetNavigatorForTracking();
|
|---|
| 212 | </programlisting>
|
|---|
| 213 | </informalexample>
|
|---|
| 214 |
|
|---|
| 215 | This also allows to retrieve at any time a pointer to the world volume
|
|---|
| 216 | assigned for tracking:
|
|---|
| 217 |
|
|---|
| 218 | <informalexample>
|
|---|
| 219 | <programlisting>
|
|---|
| 220 | G4VPhysicalVolume* tracking_world = tracking_navigator->GetWorldVolume();
|
|---|
| 221 | </programlisting>
|
|---|
| 222 | </informalexample>
|
|---|
| 223 |
|
|---|
| 224 | The navigator for tracking also retains all the information of the current
|
|---|
| 225 | history of volumes transversed at a precise moment of the tracking during a
|
|---|
| 226 | run. Therefore, if the navigator for tracking is used during tracking for
|
|---|
| 227 | locating a generic point in the tree of volumes, the actual particle gets
|
|---|
| 228 | also -relocated- in the specified position and tracking will be of course
|
|---|
| 229 | affected !
|
|---|
| 230 | </para>
|
|---|
| 231 |
|
|---|
| 232 | <para>
|
|---|
| 233 | In order to avoid the problem above and provide information about location
|
|---|
| 234 | of a point without affecting the tracking, it is suggested to either use an
|
|---|
| 235 | alternative <literal>G4Navigator</literal> object (which can then be assigned
|
|---|
| 236 | to the world-volume), or access the information through the step.
|
|---|
| 237 | </para>
|
|---|
| 238 |
|
|---|
| 239 | <!-- ******* Bridgehead ******* -->
|
|---|
| 240 | <bridgehead renderas='sect4'>
|
|---|
| 241 | Using the 'step' to retrieve geometrical information
|
|---|
| 242 | </bridgehead>
|
|---|
| 243 |
|
|---|
| 244 | <para>
|
|---|
| 245 | During the tracking run, geometrical information can be retrieved through
|
|---|
| 246 | the touchable handle associated to the current step. For example, to identify
|
|---|
| 247 | the exact copy-number of a specific physical volume in the mass geometry,
|
|---|
| 248 | one should do the following:
|
|---|
| 249 |
|
|---|
| 250 | <informalexample>
|
|---|
| 251 | <programlisting>
|
|---|
| 252 | // Given the pointer to the step object ...
|
|---|
| 253 | //
|
|---|
| 254 | G4Step* aStep = ..;
|
|---|
| 255 |
|
|---|
| 256 | // ... retrieve the 'pre-step' point
|
|---|
| 257 | //
|
|---|
| 258 | G4StepPoint* preStepPoint = aStep->GetPreStepPoint();
|
|---|
| 259 |
|
|---|
| 260 | // ... retrieve a touchable handle and access to the information
|
|---|
| 261 | //
|
|---|
| 262 | G4TouchableHandle theTouchable = preStepPoint->GetTouchableHandle();
|
|---|
| 263 | G4int copyNo = theTouchable->GetCopyNumber();
|
|---|
| 264 | G4int motherCopyNo = theTouchable->GetCopyNumber(1);
|
|---|
| 265 | </programlisting>
|
|---|
| 266 | </informalexample>
|
|---|
| 267 | </para>
|
|---|
| 268 |
|
|---|
| 269 | <para>
|
|---|
| 270 | To determine the exact position in global coordinates in the mass geometry
|
|---|
| 271 | and convert to local coordinates (local to the current volume):
|
|---|
| 272 |
|
|---|
| 273 | <informalexample>
|
|---|
| 274 | <programlisting>
|
|---|
| 275 | G4ThreeVector worldPosition = preStepPoint->GetPosition();
|
|---|
| 276 | G4ThreeVector localPosition = theTouchable->GetHistory()->
|
|---|
| 277 | GetTopTransform().TransformPoint(worldPosition);
|
|---|
| 278 | </programlisting>
|
|---|
| 279 | </informalexample>
|
|---|
| 280 | </para>
|
|---|
| 281 |
|
|---|
| 282 | <!-- ******* Bridgehead ******* -->
|
|---|
| 283 | <bridgehead renderas='sect4'>
|
|---|
| 284 | Using an alternative navigator to locate points
|
|---|
| 285 | </bridgehead>
|
|---|
| 286 |
|
|---|
| 287 | <para>
|
|---|
| 288 | In order to know (when in the <literal>idle</literal> state of the
|
|---|
| 289 | application) in which physical volume a given point is located
|
|---|
| 290 | in the detector geometry, it is necessary to create an alternative
|
|---|
| 291 | navigator object first and assign it to the world volume:
|
|---|
| 292 |
|
|---|
| 293 | <informalexample>
|
|---|
| 294 | <programlisting>
|
|---|
| 295 | G4Navigator* aNavigator = new G4Navigator();
|
|---|
| 296 | aNavigator->SetWorldVolume(worldVolumePointer);
|
|---|
| 297 | </programlisting>
|
|---|
| 298 | </informalexample>
|
|---|
| 299 | </para>
|
|---|
| 300 |
|
|---|
| 301 | <para>
|
|---|
| 302 | Then, locate the point <literal>myPoint</literal> (defined in global coordinates),
|
|---|
| 303 | retrieve a <emphasis>touchable handle</emphasis> and do whatever you need with it:
|
|---|
| 304 |
|
|---|
| 305 | <informalexample>
|
|---|
| 306 | <programlisting>
|
|---|
| 307 | aNavigator->LocateGlobalPointAndSetup(myPoint);
|
|---|
| 308 | G4TouchableHistoryHandle aTouchable =
|
|---|
| 309 | aNavigator->CreateTouchableHistoryHandle();
|
|---|
| 310 |
|
|---|
| 311 | // Do whatever you need with it ...
|
|---|
| 312 | // ... convert point in local coordinates (local to the current volume)
|
|---|
| 313 | //
|
|---|
| 314 | G4ThreeVector localPosition = aTouchable->GetHistory()->
|
|---|
| 315 | GetTopTransform().TransformPoint(myPoint);
|
|---|
| 316 |
|
|---|
| 317 | // ... convert back to global coordinates system
|
|---|
| 318 | G4ThreeVector globalPosition = aTouchable->GetHistory()->
|
|---|
| 319 | GetTopTransform().Inverse().TransformPoint(localPosition);
|
|---|
| 320 | </programlisting>
|
|---|
| 321 | </informalexample>
|
|---|
| 322 | </para>
|
|---|
| 323 |
|
|---|
| 324 | <para>
|
|---|
| 325 | If outside of the tracking run and given a generic local position (local to a
|
|---|
| 326 | given volume in the geometry tree), it is -not- possible to determine a priori
|
|---|
| 327 | its global position and convert it to the global coordinates system.
|
|---|
| 328 | The reason for this is rather simple, nobody can guarantee that the given
|
|---|
| 329 | (local) point is located in the right -copy- of the physical volume !
|
|---|
| 330 | In order to retrieve this information, some extra knowledge related to the
|
|---|
| 331 | absolute position of the physical volume is required first, i.e. one should
|
|---|
| 332 | first determine a global point belonging to that volume, eventually making
|
|---|
| 333 | a dedicated scan of the geometry tree through a dedicated
|
|---|
| 334 | <literal>G4Navigator</literal> object and then apply the method above after
|
|---|
| 335 | having created the touchable for it.
|
|---|
| 336 | </para>
|
|---|
| 337 |
|
|---|
| 338 | </sect3>
|
|---|
| 339 |
|
|---|
| 340 | <!-- ******************* Section (Level#3) ****************** -->
|
|---|
| 341 | <sect3 id="sect.Geom.Navig.ParaGeom">
|
|---|
| 342 | <title>
|
|---|
| 343 | Navigation in parallel geometries
|
|---|
| 344 | </title>
|
|---|
| 345 |
|
|---|
| 346 | <para>
|
|---|
| 347 | Since release 8.2 of Geant4, it is possible to define geometry trees which
|
|---|
| 348 | are <literal>parallel</literal> to the tracking geometry and having them
|
|---|
| 349 | assigned to navigator objects that transparently communicate in sync with
|
|---|
| 350 | the normal tracking geometry.
|
|---|
| 351 | </para>
|
|---|
| 352 |
|
|---|
| 353 | <para>
|
|---|
| 354 | Parallel geometries can be defined for several uses (fast shower
|
|---|
| 355 | parameterisation, geometrical biasing, particle scoring, readout
|
|---|
| 356 | geometries, etc ...) and can <emphasis>overlap</emphasis> with the mass
|
|---|
| 357 | geometry defined for the tracking. The <literal>parallel</literal>
|
|---|
| 358 | transportation will be activated only after the registration of the
|
|---|
| 359 | parallel geometry in the detector description
|
|---|
| 360 | setup; see Section <xref linkend="sect.ParaGeom" /> for how to define a parallel
|
|---|
| 361 | geometry and register it to the run-manager.
|
|---|
| 362 | </para>
|
|---|
| 363 |
|
|---|
| 364 | <para>
|
|---|
| 365 | The <literal>G4TransportationManager</literal> provides all the utilities to verify,
|
|---|
| 366 | retrieve and activate the navigators associated to the various parallel
|
|---|
| 367 | geometries defined.
|
|---|
| 368 | </para>
|
|---|
| 369 |
|
|---|
| 370 | </sect3>
|
|---|
| 371 |
|
|---|
| 372 | <!-- ******************* Section (Level#3) ****************** -->
|
|---|
| 373 | <sect3 id="sect.Geom.Navig.PhantomGeom">
|
|---|
| 374 | <title>
|
|---|
| 375 | Fast navigation in regular patterned geometries and phantoms
|
|---|
| 376 | </title>
|
|---|
| 377 |
|
|---|
| 378 | <para>
|
|---|
| 379 | Since release 9.1 of Geant4, a specialised navigation algorithm has
|
|---|
| 380 | been introduced to allow for optimal memory use and extremely efficient
|
|---|
| 381 | navigation in geometries represented by a regular pattern of volumes
|
|---|
| 382 | and particularly three-dimensional grids of boxes. A typical application
|
|---|
| 383 | of this kind is the case of DICOM phantoms for medical physics studies.
|
|---|
| 384 | </para>
|
|---|
| 385 |
|
|---|
| 386 | <para>
|
|---|
| 387 | The class <literal>G4RegularNavigation</literal> is used and automatically
|
|---|
| 388 | activated when such geometries are defined. It is required to the user to
|
|---|
| 389 | implement a parameterisation of the kind <literal>G4PhantomParameterisation</literal>
|
|---|
| 390 | and place the parameterised volume containing it in a container volume, so that
|
|---|
| 391 | all cells in the three-dimensional grid (<emphasis>voxels</emphasis>) completely
|
|---|
| 392 | fill the container volume.
|
|---|
| 393 | This way the location of a point inside a voxel can be done in a fast way,
|
|---|
| 394 | transforming the position to the coordinate system of the container volume
|
|---|
| 395 | and doing a simple calculation of the kind:
|
|---|
| 396 |
|
|---|
| 397 | <informalexample>
|
|---|
| 398 | <programlisting>
|
|---|
| 399 | copyNo_x = (localPoint.x()+fVoxelHalfX*fNoVoxelX)/(fVoxelHalfX*2.)
|
|---|
| 400 | </programlisting>
|
|---|
| 401 | </informalexample>
|
|---|
| 402 |
|
|---|
| 403 | where <literal>fVoxelHalfX</literal> is the half dimension of the voxel along
|
|---|
| 404 | <literal>X</literal> and <literal>fNoVoxelX</literal> is the number of voxels
|
|---|
| 405 | in the <literal>X</literal> dimension.
|
|---|
| 406 | Voxel <literal>0</literal> will be the one closest to the corner
|
|---|
| 407 | <literal>(fVoxelHalfX*fNoVoxelX, fVoxelHalfY*fNoVoxelY, fVoxelHalfZ*fNoVoxelZ)</literal>.
|
|---|
| 408 | </para>
|
|---|
| 409 |
|
|---|
| 410 | <para>
|
|---|
| 411 | Having the voxels filling completely the container volume allows to avoid
|
|---|
| 412 | the lengthy computation of <literal>ComputeStep()</literal> and
|
|---|
| 413 | <literal>ComputeSafety</literal> methods required in the traditional
|
|---|
| 414 | navigation algorithm.
|
|---|
| 415 | In this case, when a track is inside the parent volume, it has always to
|
|---|
| 416 | be inside one of the voxels and it will be only necessary to calculate
|
|---|
| 417 | the distance to the walls of the current voxel.
|
|---|
| 418 | </para>
|
|---|
| 419 |
|
|---|
| 420 | <!-- ******* Bridgehead ******* -->
|
|---|
| 421 | <bridgehead renderas='sect4'>
|
|---|
| 422 | Skipping borders of voxels with same material
|
|---|
| 423 | </bridgehead>
|
|---|
| 424 |
|
|---|
| 425 | <para>
|
|---|
| 426 | Another speed optimisation can be provided by skipping the frontiers
|
|---|
| 427 | of two voxels which the same material assigned, so that bigger steps
|
|---|
| 428 | can be done. This optimisation may be not very useful when the number of
|
|---|
| 429 | materials is very big (in which case the probability of having contiguous
|
|---|
| 430 | voxels with same material is reduced), or when the physical step is small
|
|---|
| 431 | compared to the voxel dimensions (very often the case of electrons).
|
|---|
| 432 | The optimisation can be switched off in such cases, by invoking the
|
|---|
| 433 | following method with argument <literal>skip = 0</literal>:
|
|---|
| 434 |
|
|---|
| 435 | <!-- ******* Bridgehead ******* -->
|
|---|
| 436 | <bridgehead renderas='sect4'>
|
|---|
| 437 | Phantoms with only one material
|
|---|
| 438 | </bridgehead>
|
|---|
| 439 |
|
|---|
| 440 | <para>
|
|---|
| 441 | If you want to describe a phantom of a unique material, you may spare some memory by not filling the set of indices of materials of each voxel. If the method <literal>SetMaterialIndices()</literal> is not invoked, the index for all voxels will be 0, that is the first (and unique) material in your list.
|
|---|
| 442 | </para>
|
|---|
| 443 |
|
|---|
| 444 | <informalexample>
|
|---|
| 445 | <programlisting>
|
|---|
| 446 | G4RegularParameterisation::SetSkipEqualMaterials( G4bool skip );
|
|---|
| 447 | </programlisting>
|
|---|
| 448 | </informalexample>
|
|---|
| 449 | </para>
|
|---|
| 450 |
|
|---|
| 451 | <!-- ******* Bridgehead ******* -->
|
|---|
| 452 | <bridgehead renderas='sect4'>
|
|---|
| 453 | Example
|
|---|
| 454 | </bridgehead>
|
|---|
| 455 |
|
|---|
| 456 | <para>
|
|---|
| 457 | To use the specialised navigation, it is required to first create an object
|
|---|
| 458 | of type <literal>G4PhantomParameterisation</literal>:
|
|---|
| 459 |
|
|---|
| 460 | <informalexample>
|
|---|
| 461 | <programlisting>
|
|---|
| 462 | G4PhantomParameterisation* param = new G4PhantomParameterisation();
|
|---|
| 463 | </programlisting>
|
|---|
| 464 | </informalexample>
|
|---|
| 465 |
|
|---|
| 466 | Then, fill it with the all the necessary data:
|
|---|
| 467 |
|
|---|
| 468 | <informalexample>
|
|---|
| 469 | <programlisting>
|
|---|
| 470 | // Voxel dimensions in the three dimensions
|
|---|
| 471 | //
|
|---|
| 472 | G4double halfX = ...;
|
|---|
| 473 | G4double halfY = ...;
|
|---|
| 474 | G4double halfZ = ...;
|
|---|
| 475 | param->SetVoxelDimensions( halfX, halfY, halfZ );
|
|---|
| 476 |
|
|---|
| 477 | // Number of voxels in the three dimensions
|
|---|
| 478 | //
|
|---|
| 479 | G4int nVoxelX = ...;
|
|---|
| 480 | G4int nVoxelY = ...;
|
|---|
| 481 | G4int nVoxelZ = ...;
|
|---|
| 482 | param->SetNoVoxel( nVoxelX, nVoxelY, nVoxelZ );
|
|---|
| 483 |
|
|---|
| 484 | // Vector of materials of the voxels
|
|---|
| 485 | //
|
|---|
| 486 | std::vector < G4Material* > theMaterials;
|
|---|
| 487 | theMaterials.push_back( new G4Material( ...
|
|---|
| 488 | theMaterials.push_back( new G4Material( ...
|
|---|
| 489 | param->SetMaterials( theMaterials );
|
|---|
| 490 |
|
|---|
| 491 | // List of material indices
|
|---|
| 492 | // For each voxel it is a number that correspond to the index of its
|
|---|
| 493 | // material in the vector of materials defined above;
|
|---|
| 494 | //
|
|---|
| 495 | size_t* mateIDs = new size_t[nVoxelX*nVoxelY*nVoxelZ];
|
|---|
| 496 | mateIDs[0] = n0;
|
|---|
| 497 | mateIDs[1] = n1;
|
|---|
| 498 | ...
|
|---|
| 499 | param->SetMaterialIndices( mateIDs );
|
|---|
| 500 | </programlisting>
|
|---|
| 501 | </informalexample>
|
|---|
| 502 |
|
|---|
| 503 | Then, define the volume that contains all the voxels:
|
|---|
| 504 |
|
|---|
| 505 | <informalexample>
|
|---|
| 506 | <programlisting>
|
|---|
| 507 | G4Box* cont_solid = new G4Box("PhantomContainer",nVoxelX*halfX.,nVoxelY*halfY.,nVoxelZ*halfZ);
|
|---|
| 508 | G4LogicalVolume* cont_logic =
|
|---|
| 509 | new G4LogicalVolume( cont_solid,
|
|---|
| 510 | matePatient, // material is not relevant here...
|
|---|
| 511 | "PhantomContainer",
|
|---|
| 512 | 0, 0, 0 );
|
|---|
| 513 | G4VPhysicalVolume * cont_phys =
|
|---|
| 514 | new G4PVPlacement(rotm, // rotation
|
|---|
| 515 | pos, // translation
|
|---|
| 516 | cont_logic, // logical volume
|
|---|
| 517 | "PhantomContainer", // name
|
|---|
| 518 | world_logic, // mother volume
|
|---|
| 519 | false, // No op. bool.
|
|---|
| 520 | 1); // Copy number
|
|---|
| 521 |
|
|---|
| 522 | </programlisting>
|
|---|
| 523 | </informalexample>
|
|---|
| 524 |
|
|---|
| 525 | The physical volume should be assigned as the container volume of the
|
|---|
| 526 | parameterisation:
|
|---|
| 527 |
|
|---|
| 528 | <informalexample>
|
|---|
| 529 | <programlisting>
|
|---|
| 530 | param->BuildContainerSolid(cont_phys);
|
|---|
| 531 |
|
|---|
| 532 | // Assure that the voxels are completely filling the container volume
|
|---|
| 533 | //
|
|---|
| 534 | param->CheckVoxelsFillContainer( cont_solid->GetXHalfLength(),
|
|---|
| 535 | cont_solid->GetyHalfLength(),
|
|---|
| 536 | cont_solid->GetzHalfLength() );
|
|---|
| 537 |
|
|---|
| 538 | // The parameterised volume which uses this parameterisation is placed
|
|---|
| 539 | // in the container logical volume
|
|---|
| 540 | //
|
|---|
| 541 | G4PVParameterised * patient_phys =
|
|---|
| 542 | new G4PVParameterised("Patient", // name
|
|---|
| 543 | patient_logic, // logical volume
|
|---|
| 544 | cont_logic, // mother volume
|
|---|
| 545 | kXAxis, // optimisation hint
|
|---|
| 546 | nVoxelX*nVoxelY*nVoxelZ, // number of voxels
|
|---|
| 547 | param); // parameterisation
|
|---|
| 548 |
|
|---|
| 549 | // Indicate that this physical volume is having a regular structure
|
|---|
| 550 | //
|
|---|
| 551 | patient_phys->SetRegularStructureId(1);
|
|---|
| 552 | </programlisting>
|
|---|
| 553 | </informalexample>
|
|---|
| 554 | </para>
|
|---|
| 555 |
|
|---|
| 556 | An example showing the application of the optimised navigation algorithm
|
|---|
| 557 | for phantoms geometries is available in
|
|---|
| 558 | <literal>examples/extended/medical/DICOM</literal>. It implements a real
|
|---|
| 559 | application for reading <literal>DICOM</literal> images and convert them to
|
|---|
| 560 | Geant4 geometries with defined materials and densities, allowing for
|
|---|
| 561 | different implementation solutions to be chosen (non optimised, classical
|
|---|
| 562 | 3D optimisation, nested parameterisations and use of
|
|---|
| 563 | <literal>G4PhantomParameterisation</literal>).
|
|---|
| 564 |
|
|---|
| 565 | </sect3>
|
|---|
| 566 |
|
|---|
| 567 | <!-- ******************* Section (Level#3) ****************** -->
|
|---|
| 568 | <sect3 id="sect.Geom.Navig.RunTime">
|
|---|
| 569 | <title>
|
|---|
| 570 | Run-time commands
|
|---|
| 571 | </title>
|
|---|
| 572 |
|
|---|
| 573 | <para>
|
|---|
| 574 | When running in <emphasis>verbose</emphasis> mode (i.e. the default,
|
|---|
| 575 | <literal>G4VERBOSE</literal> set while installing the Geant4 kernel
|
|---|
| 576 | libraries), the navigator provides a few commands to control its
|
|---|
| 577 | behavior. It is possible to select different verbosity levels (up
|
|---|
| 578 | to 5), with the command:
|
|---|
| 579 |
|
|---|
| 580 | <informalexample>
|
|---|
| 581 | <programlisting>
|
|---|
| 582 | geometry/navigator/verbose [verbose_level]
|
|---|
| 583 | </programlisting>
|
|---|
| 584 | </informalexample>
|
|---|
| 585 |
|
|---|
| 586 | or to force the navigator to run in <emphasis>check</emphasis> mode:
|
|---|
| 587 |
|
|---|
| 588 | <informalexample>
|
|---|
| 589 | <programlisting>
|
|---|
| 590 | geometry/navigator/check_mode [true/false]
|
|---|
| 591 | </programlisting>
|
|---|
| 592 | </informalexample>
|
|---|
| 593 | </para>
|
|---|
| 594 |
|
|---|
| 595 | <para>
|
|---|
| 596 | The latter will force more strict and less tolerant checks in
|
|---|
| 597 | step/safety computation to verify the correctness of the solids'
|
|---|
| 598 | response in the geometry.
|
|---|
| 599 | </para>
|
|---|
| 600 |
|
|---|
| 601 | <para>
|
|---|
| 602 | By combining <emphasis>check_mode</emphasis> with verbosity level-1, additional
|
|---|
| 603 | verbosity checks on the response from the solids can be activated.
|
|---|
| 604 | </para>
|
|---|
| 605 |
|
|---|
| 606 | </sect3>
|
|---|
| 607 |
|
|---|
| 608 | <!-- ******************* Section (Level#3) ****************** -->
|
|---|
| 609 | <sect3 id="sect.Geom.Tolerance">
|
|---|
| 610 | <title>
|
|---|
| 611 | Setting Geometry Tolerance to be relative
|
|---|
| 612 | </title>
|
|---|
| 613 |
|
|---|
| 614 | <para>
|
|---|
| 615 | The tolerance value defining the accuracy of tracking on the surfaces
|
|---|
| 616 | is by default set to a reasonably small value of <emphasis>10E-9 mm</emphasis>.
|
|---|
| 617 | Such accuracy may be however redundant for use on simulation of detectors
|
|---|
| 618 | of big size or macroscopic dimensions. Since release 9.0, it is possible to
|
|---|
| 619 | specify the surface tolerance to be relative to the extent of the world volume
|
|---|
| 620 | defined for containing the geometry setup.
|
|---|
| 621 | </para>
|
|---|
| 622 |
|
|---|
| 623 | <para>
|
|---|
| 624 | The class <literal>G4GeometryManager</literal> can be used to activate
|
|---|
| 625 | the computation of the surface tolerance to be relative to the geometry
|
|---|
| 626 | setup which has been defined. It can be done this way:
|
|---|
| 627 |
|
|---|
| 628 | <informalexample>
|
|---|
| 629 | <programlisting>
|
|---|
| 630 | G4GeometryManager::GetInstance()->SetWorldMaximumExtent(WorldExtent);
|
|---|
| 631 | </programlisting>
|
|---|
| 632 | </informalexample>
|
|---|
| 633 |
|
|---|
| 634 | where, <literal>WorldExtent</literal> is the actual maximum extent of the
|
|---|
| 635 | world volume used for placing the whole geometry setup.
|
|---|
| 636 | </para>
|
|---|
| 637 |
|
|---|
| 638 | <para>
|
|---|
| 639 | Such call to <literal>G4GeometryManager</literal> must be done
|
|---|
| 640 | <emphasis role="bold">before</emphasis> defining any geometrical component of
|
|---|
| 641 | the setup (solid shape or volume), and can be done only
|
|---|
| 642 | <emphasis role="bold">once</emphasis> !
|
|---|
| 643 | </para>
|
|---|
| 644 |
|
|---|
| 645 | <para>
|
|---|
| 646 | The class <literal>G4GeometryTolerance</literal> is to be used for retrieving the
|
|---|
| 647 | actual values defined for tolerances, surface (Cartesian), angular or radial
|
|---|
| 648 | respectively:
|
|---|
| 649 |
|
|---|
| 650 | <informalexample>
|
|---|
| 651 | <programlisting>
|
|---|
| 652 | G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
|
|---|
| 653 | G4GeometryTolerance::GetInstance()->GetAngularTolerance();
|
|---|
| 654 | G4GeometryTolerance::GetInstance()->GetRadialTolerance();
|
|---|
| 655 | </programlisting>
|
|---|
| 656 | </informalexample>
|
|---|
| 657 |
|
|---|
| 658 | </para>
|
|---|
| 659 |
|
|---|
| 660 | </sect3>
|
|---|
| 661 |
|
|---|
| 662 | </sect2>
|
|---|