Skip to content
Snippets Groups Projects
Commit e58bfc3c authored by Vakhtang Tsulaia's avatar Vakhtang Tsulaia
Browse files

Merge branch 'GMXDoc' into 'main'

initial updates to GeoModelXML docs

See merge request !309
parents 5a21a4b9 ff63e551
No related branches found
No related tags found
1 merge request!309initial updates to GeoModelXML docs
Pipeline #7188655 passed with warnings
Showing
with 1059 additions and 433 deletions
Since geometries described with `GeoModel` typically aim to represent a detector which will (or might be) physically constructed in future, it is important to be able to model issues which commonly face detectors once constructed. A significant issue for many detectors is that contruction tolerances and/or effects due to changing temperature, magnetic fields, etc, can result in measurable differences between the real and expected positions of detector elements.
While these effects can be explicitly modeled in the geometry *if known*, it is more typical to include such effects by allowing for *misalignments* to be applied to the geometry, which represent external corrections to be applied to the positions of volumes, having been determined by an *alignment procedure* (typically a minimization of certain parameters with high sensitivity to the positions of sensor elements).
## Making volumes alignable
In `GeoModelXML`, elements are made alignable through using the `alignable` property. This has several functions.
- When creating a `logvol` or `assembly`, this property indicates that a `GeoFullPhysVol`[^abbr1] should be created rather than a `GeoPhysVol`[^abbr2] [(see GeoModelKernel for more details)](../../kernel/overview/#physical-volumes-and-the-geometry-graph).
```
<logvol name="SingleBox" shape="BoxShape" material="Air" alignable="true"/>
```
- When creating a `transformation`, this property indicates that a [`GeoAlignableTransform` should be created rather than a `GeoTransform`](../../kernel/overview/#physical-volumes-and-the-geometry-graph).
```
<transformation name="RotateABox" alignable="true">
<rotation zcos="1.0" angle="-PI/4"/>
</transformation>
```
Since often it is known when creating a volume that is *should* be aligned, but not necessarily the full picture of how it may later be positioned via `transformations`, it is also possible to define an empty `transformation` to which alignments can be applied (since the final position will be the product of all `transformations` applied):
```
<logvol name="SingleBox" shape="BoxShape" material="Air" alignable="true"/>
<assembly name="AlignableBox">
<transform>
<transformation name="DummyTransform" alignable="true">
<translation/>
</transformation>
<logvolref ref="SingleBox"/>
</transform>
</assembly>
```
- The final use of `alignable` is a little different; when defining a `transform`, `multicopy`, or `ReplicaArray`, the `alignable` property expects an `int` rather than a `bool`. This is because this use of `alignable` propagates the objects which are to be made alignable to [`GmxInterface`](../components/gmxinterface/), in order that they can be accessed and used externally to `GeoModel`, e.g. within an experiment's simulation or reconstruction framework. The value passed as an `int` represents the alignment "level"; different levels may be treated differently as they can be defined to distinguish e.g. large, medium, and small structures which should be processed one after the other in the alignment procedures of the experiment.
Putting this all together, you should have something that looks like the following:
```
<logvol name="SingleBox" shape="BoxShape" material="Air" alignable="true"/>
<assembly name="AlignableBox">
<transform alignable="1">
<transformation name="RotateABox" alignable="true">
<rotation zcos="1.0" angle="-PI/4"/>
</transformation>
<logvolref ref="SingleBox"/>
</transform>
</assembly>
```
If all three of the points discussed above have been successfully applied, you should see be able to see a `DEBUG` message from `GmxInterface` (if the output verbosity is high enough):
```
GmxInterface::addAlignable called for a physvol. Logvol name [...]
```
## Known issues
Currently alignment with `GeoModelXML` is in a development and testing phase, and so issues are in the process of being discovered and solved. The current known issues are:
- when using `splitLevel` to [split up volumes into multiple readout elements](../readout/#splitting-volumes-into-multiple-readout-elements), only the first of these currently gets a `GeoAlignableTransform` passed on. Since these split volumes should always be physically bound, they should not need alignment relative to each other and so can all use a single `GeoAlignableTransform`. This propagation of a common `GeoAlignableTransform` for split volumes is not yet implemented.
- when defining a `multicopy` without a `loopvar`, `GeoAlignableTransforms` are not being properly created. Until this is fixed, it is suggested that a `loopvar` is used in all cases (can be a ["dummy" which simply implements the *implicit* behaviour](../buildinggeometry/#repeated-positionings))
- using the same name for the `bool` and `int` `alignable` properties can be confusing; a new `alignmentLevel` (or similar) property should be defined that can optionally be used in place of the `int` version, and eventually replace it as the standard.
[^abbr1]:Class definition states: *"This class represent a physical volume whose absolute default and aligned positions are known and held in cache."*
[^abbr2]:Class definition states: *"A GeoPhysVol is a physical volume for normal recursive access only. This means, normally, that it represents a piece of detector that nobody cares about except for tracing engines like GEANT"*
\ No newline at end of file
# Building a Geometry
## Creating a volume
When building a geometry, we are generally considering a set of `volumes` positioned in a 3D space. We define these by creating a `logvol`:
```
<logvol name="MyLogVol" shape="MyShape" material="MyMaterial"/>
```
a `logvol` should have a `name` (names are generally needed for identifying elements and referring to them elsewhere in the code), a `shape` defining its extent in space, and a `material` which specificies its composition and density.
A `shape` to be used in this `logvol` can be defined as follows:
```
<shapes>
<!-other shapes can be defined here too-->
<box name=“MyShape” xhalflength=“100.” yhalflength=“100.” zhalflength=“500.” />
<\shapes>
```
This will create a `shape` of type `box`, which is defined by 3 parameters: its half-length in `x`,`y`, and `z`, set to 100, 100, and 500 mm, respecively. A full list of supported shapes can be found [here](../components/processors/#supported-shapes).
A `material` to be used in the `logvol` can be defined as follows, building up chemical molecules from elements, to make materials which can themselves be mixed in different fractions to create new materials:
```
<materials>
<!- a more complicated definition to show some possibilities ->
<element name="Carbon" shortname="C" Z="6" A=“12.011"/>
<element name="Argon" shortname="N" Z="18" A="39.72"/>
<element name="Oxygen" shortname="O" Z="8" A=“15.9994"/>
<chemical name="CO2">
<elemcontent ref="Carbon" quantity="1"/>
<elemcontent ref="Oxygen" quantity="2"/>
</chemical>
<material name="CO2Gas" density="1.98e-3">
<chemicalref fraction="1" ref="CO2"/>
</material>
<material name="ArgonGas" density="1.789e-3" >
<elementref fraction="1.00000" ref="Argon"/>
</material>
<material name="MyMaterial" density="1.79e-3" >
<materialref ref="ArgonGas" fraction="0.93" />
<materialref ref="CO2Gas" fraction="0.07" />
</material>
</materials>
```
## Placing a volume
By default, volumes are created at the origin of the reference frame. To place a volume within 3D space, it should be placed within a `transform` element and have a `transformation` applied. For example, to place the centre of the box we created at a position 250 mm along the z-axis:
```
<transform>
<transformation name="MyTransformation">
<translation z="250">
</transformation>
<logvolref ref="MyLogVol">
</transform>
```
Here we use a `logvolref` to refer to a previously defined `logvol`. This can also be done with a `transformation` that has been previously defined (for example to allow re-use), e.g.
```
<transformation name="MyTransformation">
<translation z="250">
</transformation>
<transform>
<transformationref ref="MyTransformation">
<logvolref ref="MyLogVol">
</transform>
```
Multiple operations can be combined in a single `transformation`, e.g. to combine a translation and a rotation:
```
<transformation name="MyTranslateRotate" >
<translation x=“600." y="600." z="600." />
<rotation xcos="1/sqrt(3.)" ycos="1/sqrt(3.)" zcos="1/sqrt(3.)" angle="PI/4." />
</transformation>
```
When defining rotations, the parameters are the cosines defining the axis around which the rotation should be performed, and the angle through which to be rotated. The cosines are `0` unless set, and so a rotation about the z-axis can be performed like `<rotation zcos="1.0" angle="PI/4." />`.
## Combining volumes
Since a full detetor will typically consist of very many volumes, some nested within others, it is necessary to be able to combine them. It is possible to simply place one `logvol` inside another (NB they must be full contained and not protruding otherwise this will cause a `clash`):
```
<!- assuming you've defined "MyBigBox", "MySmallBox", "MySmallVolume", ","MyMaterial" already->
<logvol name="MyBigVolume" shape="MyBigBox" material="MyMaterial">
<logvolref ref="MySmallVolume"/>
</logvol>
```
This can be done for mutliple `logvols`, and can also include a `transformation`, e.g:
```
<!- assuming you've defined "MyBigBox", "MySmallBox", "MySmallVolume", ","MyMaterial" already->
<logvol name="MyBigVolume" shape="MyBigBox" material="MyMaterial">
<transform>
<transformation name"MyZShift">
<translation z="5"/>
</transformation>
<logvolref ref="MySmallVolume"/>
</transform>
<transform>
<transformation name"MyNegativeZShift">
<translation z="-5"/>
</transformation>
<logvolref ref="MySmallVolume"/>
</transform>
</logvol>
```
This generally works very well, but note that the containing `logvol` by definition requires a `shape`. Sometimes this can be inconvenient; e.g. one may need to define a very complicated shape to encompass all the volumes contained, without generating clashes with other volumes. A good solution can be to create an `assembly` which simply binds a set of volumes together, without requiring an "outer" `logvol` and `shape`:
```
<!- assuming you've defined "MyBigBox", "MySmallBox", "MySmallVolume", ","MyMaterial" already->
<assembly name="MyBigVolume">
<transform>
<transformation name"MyZShift">
<translation z="5"/>
</transformation>
<logvolref ref="MySmallVolume"/>
</transform>
<transform>
<transformation name"MyNegativeZShift">
<translation z="-5"/>
</transformation>
<logvolref ref="MySmallVolume"/>
</transform>
</assembly>
```
An `assembly` can consist of a single positioned `logvol` as a convenient way to bind a `transformation` to a volume, and an `assembly` can also contain mutliple other `assemblies` or `assemblyrefs`:
```
<!- assuming you've defined "MyBigBox", "MySmallBox", "MySmallVolume", ","MyMaterial" already->
<assembly name="MySmallVolumePos">
<transform>
<transformation name="MyZShift">
<translation z="5"/>
</transformation>
<logvolref ref="MySmallVolume">
</transform>
</assembly>
<assembly name="MySmallVolumeNeg">
<transform>
<transformation name="MyNegativeZShift">
<translation z="-5"/>
</transformation>
<logvolref ref="MySmallVolume">
</transform>
</assembly>
<assembly name="MyBigVolume">
<assemblyref ref="MySmallVolumePos"/>
<assemblyref ref="MySmallVolumeNeg"/>
</assembly>
```
## Defining variables
You may notice that in the previous examples, we have used explicit numerical values for e.g. the magnitude of translations. In general, as stated in the [Good practise guidelines](../#good-practise-guidelines), it is better to always use defined variables where possible. This can be done as follows:
```
<defines>
<var name=“PI” value=“3.14159265359” />
<vector name=“digits” value=“0 1 2 3 4 5 6 7 8 9” />
<matrix name=“ints” coldim=“3” value=“ 1 2 3 4 5 6 7 8 9” />
</defines>
```
These can also use mathematical operations, and other already-defined variables in their definition:
```
<defines>
<var name="position1" value="1">
<var name="position2" value="3.5">
<var name="position3" value="pos1+pos2">
<var name="position4" value="(pos1+pos2)/(pos2 - pos1)">
</defines>
```
Addressing specific components of vectors (matrices) can be done via an `_N` (`_N_M`) notation:
```
<defines>
<var name=“PI” value=“3.14159265359” />
<vector name=“digits” value=“0 1 2 3 4 5 6 7 8 9” />
<matrix name=“ints” coldim=“3” value=“ 1 2 3 4 5 6 7 8 9” />
</defines>
<defines>
<var name=“PIby2” value=“PI/digits_2” />
<var name=“AlsoPIby2” value=“PI/ints_0_1”/>
</defines>
```
## Repeated positionings
Detector geometries are in general built of repeated structures, and so it is of great convenience (nigh-on essential) to be able to place identical volumes in a series different positions, reflecting e.g. detector modules placed at regular z-intervals. This can be achieved through the use of a `multicopy`. The `multicopy` will place `n` instances of the `logvol`/`assembly` it is applied to, applying the same `transformation` each time. For instance, placing a volume 5 times with a regular z-interval of 5mm:
```
<multicopy name="MyVolsAlongZ" n="5">
<transformation name="MyZShift">
<translation z="5"/>
</transformation>
<logvolref ref="MyLogVol">
</multicopy>
```
It is also possible to use `multicopy` to place volumes with more complex sets of positions via the use of a `loopvar`. The `loopvar` is a vector of values, for which the `multicopy` will use element `_N` for the n$^{th}$ copy:
```
<defines>
<vector name=“MyZPositions” value=“-11 -10 -5 1 4” />
</defines>
<multicopy name="MyVolsAlongZ" n="5" loopvar="MyZPositions">
<transformation name="MyZShift">
<translation z="MyZPositions"/> <!--This will evaluate to MyZPositions_N-->
</transformation>
<logvolref ref="MyLogVol">
</multicopy>
```
The `loopvar` variable can also be used in formulae:
```
<defines>
<vector name=“MyScaleFactors” value=“1 2 3 4 5” />
</defines>
<multicopy name="MyVolsAlongZ" n="5" loopvar="MyScaleFactors">
<transformation name="MyZShift">
<translation z="10*MyScaleFactors"/>
</transformation>
<logvolref ref="MyLogVol">
</multicopy>
```
**NB** that when using a `multicopy` without a `loopvar`, there is an *implicit* multiplication by 0 ... n in the iterations. When a `loopvar` is defined the periodicity is fully *explicit* and so the following:
```
<defines>
<vector name=“MyZPositions” value=“0 1 2 3 4” />
</defines>
<multicopy name="MyVolsAlongZ" n="5" loopvar="MyZPositions">
<transformation name="MyZShift">
<translation z="5"/>
</transformation>
<logvolref ref="MyLogVol">
</multicopy>
```
would result in 5 copies placed at the same position (hence clashing), while the following would produce the same result as using no `loopvar`:
```
<defines>
<vector name=“MyZPositions” value=“0 1 2 3 4” />
</defines
<multicopy name="MyVolsAlongZ" n="5" loopvar="MyZPositions">
<transformation name="MyZShift">
<translation z="5*MyZPositions"/>
</transformation>
<logvolref ref="MyLogVol">
</multicopy>
```
*[NS: Should also document the `ReplicaXYArray` etc here, but I've not used these so might be better that someone else does it ;-)]*
## Working with shapes
While the [built-in shapes](../components/processors/#supported-shapes) give considerable options for the type of volumes that can be constructed, some shapes cannot be directly described by the built-in options. In this case `boolean` solids can be useful. In the following, the three types of boolean operations are shown - `union`, `subtraction`, and `intersection`:
```
<shapes>
<tube name="Cylinder” rmin="100" rmax="200" zhalflength=“1000"/>
<box name="Box" xhalflength="300" yhalflength="300" zhalflength=“500"/>
<union name="BoxAndCylinder" >
<shaperef ref="Box" />
<transformation name="trivialShift">
<translation z="0."/>
</transformation>
<shaperef ref="Cylinder" />
</union>
<subtraction name="BoxMinusCylinder" >
<shaperef ref="Box" />
<transformation name="trivialShift" >
<translation z="0."/>
</transformation>
<shaperef ref="Cylinder" />
</subtraction>
<intersection name="BoxIntersectCylinder" >
<shaperef ref="Box" />
<transformation name="rotations" >
<rotation xcos="1" angle="PI/4."/>
<rotation ycos="1" angle="PI/4."/>
<rotation zcos="1" angle="PI/4."/>
</transformation>
<shaperef ref="Cylinder" />
</intersection>
</shapes>
```
Note that extensive use of `boolean` operations can lead to high computational overheads, and so their use should be carefully considered (e.g. best avoided for volumes for which very many copies will created).
# Gmx2Geo
`Gmx2Geo` is the main top-level class of `GeoModelXML`, and as the name suggests, it is the interface through which `GeoModel` objects are created from the `GeoModelXML` processing of the input XML files. It takes as inputs:
- The XML files to be processed
- A "world" volume into which the geometry tree to be built will be inserted
- a `gmxInterface` to be used for communication with downstream code (or simply debugging)
- flags to steer behvaiour (e.g. whether to read from a file or a string from a database)
- a list of additional `processors` to be run on top of the "standard list" in `GmxUtil` (the main "driver" class)
The primary uses of `Gmx2Geo` are therefore in intergrating `GeoModelXML` in a more general software framework as the method of building `GeoModel` detector description, or in writing plugins which can be used by the other `GeoModel` tools such as `gmcat`, `gmex`, etc.
# GmxInterface
`GmxInterface`, as the name suggests, is an *interface* class, intended to allow client code to access information from `GeoModelXML` and build on top of it within the relevant software stack. `GmxInterface` therefore implements a selection of methods to allow access to information which is expected to be needed elsewhere downstream within the client software. These methods in this base classs from `GeoModelXML` are expected to be overridden in a *derived* class by the client, so that they can provide the necessary context-specific handling of the information. The following methods are implemented in the base class:
- *sensorId/splitSensorId*: To format the indices defined in the [`positionindex`](../../readout/#identifying-sensitive-volumes) into the necessary format for the client code to use. Called whenever a sensitive `logvol` has been encountered, and the result of this method should be written to a `GeoIdentifierTag` for the volume.
- *addSensorType*: Called whenever a new [`sensortype`](../../readout/#making-volumes-sensitive) is encountered. It allows client code to create and store as appropriate its catalog of possible sensor representations.
- *addSensor/addSplitSensor*: Called whenever a [`sensitive` `logvol`](../../readout/#making-volumes-sensitive) is encountered, allowing a representation of a specific sensor to be created and stored by the client code.
- *addAlignable/addSplitAlignable:* called whenever an [`alignable` volume](../../alignment/#making-volumes-alignable) is encountered, it allows the `GeoFullPhysVol` and `GeoAlignableTransform` pointers to be passed to the client code for use, as well as any additional information such as the alignment `level` of the volume.
- setPublisher: allows a *publisher* to be set, such that the `readout` information will be written to `SQLite` tables by that publisher.
- publish: write the provided information via the above *publisher*
It also provides helpers for accessing the `readout` information, `getParameter` and `getParameters` for retrieving single and vectors of parameters respectively (plus `checkParameter` for testing the existence of a given parameter in the `readout` definition).
`GeoModelXML` uses `processors` to append specific information that should be associated with an XML element into a vector that gets passed the various steps. The standard list of `processors` applied (in `GmxUtil`) is:
## Standard processors
- *addbranch*: define a volume hierarchy to actually be built
- *logvol/logvolref*: create a `logvol` (or use one that previously been defined)
- *assembly/assemblyref*: create an `assembly` (or use one that has already been defined)
- *transform*: create a geometrical transformation (rotation, translation, etc)
- *multicopy*: create multiple instances of a given `logvol` or `assembly` according to a given transformation rule to be apllied for each instance
- *replicaX/replicaY/replicaZ/replicaRPhi/replicaXYarrays*: similar to `multicopy` - create multuple instances of a given `logvol` or `assembly` with a defined periodic structure
- *index*: create a set of indices for addressing a volume
More information on the meanings can be found in the sections on [building a geometry](../../buildinggeometry/) and [defining readout](../../readout/).
## Supported shapes
The following shapes are supported by `GeoModeXML`. The names reflect the `Geant4` shapes on which they are based (and may eventually create).
- simplepolygonbrep
- twistedtrap
- ellipticaltube
- torus
- box
- cons
- generictrap
- para
- pcon
- pgon
- trap
- trd
- tube
- tubs
In addition, the following boolean operations are defined, and can be applied to any of the above shapes, to create new solid volume possibilities.
- intersection
- union
- subtraction
Note that boolean operations can be very CPU intensive to navigate.
To-do: add the arguments for each type?
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
## Quick Start
To define a geometry using `GeoModelXML`, a top-level file should be provided which gives an entry point to the geometry description, and contains several things which allow it to be interpreted by `GeoModelXML`:
- The `DOCTYPE` should be set to `geomodel`, providing the path to a valid `.dtd` file (for example the latest version of `geomodel.dtd` found in `GeoModelXML\GeoModelXml\data`) defining the expected and allowed properties of the various elements.
- While it is perfectly valid to write the full geometry within a single file (and in fact _production_ geometries will be automatically combined into a single file before use) it can often be more readable to break up the geometry into multiple files. This can be done by defining a named `ENTITY` with a path to another `.gmx` file to be included
- A `geomodel` element should then be defined, which contains the actual geometry definition; this includes defining materials and shapes which can then be used to create logical volumes (`logvols`) which can then be built up into larger `logvols` or `assemblies`.
- The entities defined can be included in the geometry by adding them with `&` in front of their name. NB that entities should be included in an appropriate order to avoid issues (e.g. entities defining parameters should be included before the parameters are used).
- An `addbranch` element should then be defined which includes the [geometry elements to build](buildinggeometry.md). These should be of type `logvol` or `assembly` (or a reference thereto). Anything prior to the `addbranch` can be considered as defining _possible_ contents of the geometry, since only things pulled in by the elements included in `addbranch` will finally be built as part of the geometry.
You can see an example below:
```
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE geomodel SYSTEM "PATH/TO/FILE/geomodel.dtd" [
<!ENTITY materialFile SYSTEM "PATH/TO/FILE/materials.gmx">
]>
<geomodel name="Hello World" version="1.0"
xmlns="http://www.nikhef.nl/%7Er29/gmx">
&materialFile
<shapes>
<tube name="ShapeOneMeterCylinder" rmin="200" rmax="500" zhalflength="500"/>
</shapes>
<addbranch>
<logvol name="DiamondCylinder" shape="ShapeOneMeterCylinder" material="Diamond"/>
</addbranch>
</geomodel>
```
```
<!-This is the content of materials.gmx->
<materials>
<element name="Carbon" shortname="C" Z="6" A="12.011" />
<material name="Diamond" density="3.515">
<elementref fraction="1.0" ref="Carbon"/>
</material>
</materials>
```
The way in which these elements can be defined, have shapes, materials, and transformations (to position them) defined, as well as how they can be combined and replicated will be covered in [Building a geometry](buildinggeometry.md).
Once you have a valid geometry defined, you can use it as an input to the various `GeoModel` applications such as `gmcat`, `gmclash`, `gmex`, etc, via using the `GMXPlugin` to process the input. The input file to use in the `GMXPlugin` can be set one of two ways:
- By default, the plugin will looks for a file called `gmx.xml` so you can e.g. simply create a symbolic link to your desired input file with this name. This works well if you have just a single file, or you are working in the directory where all your geometry files reside. However, this can cause problems with relative paths to entities you wish to include. Therefore, a further more robust option is to simply concatenate your multiple files into a single file, e.g:
```
xmllint --noent --valid PATH/TO/FILE/MyTopFile.gmx > gmx.xml
```
- Alternatively, you can define an environment variable `GMX_FILES` which provides the path to the file (or multiple files, if you have several top-level files defined e.g. for dirrferent detector components) to be read in, e.g:
```
export GMX_FILES='PATH/TO/FILES/file1.gmx PATH/TO/FILES/file2.gmx'
```
(also note potential issues with relative paths to entities)
Once you have your inputs defined, you can launch the applications with a command like:
```
install/bin/gmcat install/lib64/libGMXPlugin.so -o mySQLiteFile.db
```
(details will depend on your installation paths, etc).
Note that the `GMXPlugin` is effectively a simple code wrapper around a call to [`gmx2geo`](components/gmx2geo/), within the general plugin framework defined by `GeoVGeometryPlugin`, and so new plugins which implment slighty different access patterns and behaviour are easily added.
## Good practise guidelines
As with any software framework, following sensible rules when developing in `GeoModelXML` can help greatly in ensuring readability and maintainability for future, so that other developers can pick up your files and easily understand how they work, and how they could be modified as necessary. Some important rules to think about are:
- Avoid magic numbers: use of named variables (if sensibly named) will be far clearer - for example defining `<var name="bulkhead_z_pos" value="300" />` rather than simply placing a structure at `z=300`
- Use descriptive names: E.g. `bulkhead_z_pos` is better than `BHZ`
- Use relative rather than absolute positions: This allows elements to be moved together rather by updating a single parameter, and thus avoiding either potential misplacements (and clashes) or needing to update multiple parameter coherently. E.g if we have:
```
<var name="bulkhead_z_pos" value="300" />
<var name="bulkhead_halflength_z" value="5" />
<var name="myStruct_halflength_z" value="5" />
```
Then it is preferable to place `myStruct` via
```
<var name="myStruct_z_pos" value="bulkhead_z_pos + bulkhead_halflength_z + myStruct_halflength_z" />
```
than simply by doing
```
<var name="myStruct_z_pos" value="310" />
```
since in the former case changing either the dimensions of `myStruct` or the position of `bulkhead` allow a consistent location of `myStruct` relative to `bulkhead`.
- Components should ideally be built up in a modular way, such that individual components can be visualized and debugged individually: e.g. thought should be given so that it is straightforward to build a geometry containing a single instance of each fundamental structure on its own.
When building geometries in `GeoModelXML` it is assumed that at least some parts will be instrumented for readout in order to be be able to function as a particle detector. While most of the modeling of the readout is handled outside of `GeoModel`, it is important that the relevant information about the sensitive elements of the detector is propagated correctly, and that the sensitive volumes are handled correctly in the geometry tree.
## Making volumes sensitive
In order to make a given volume sensitive, a `readout` scheme must first be applied. Since as mentioned the detector readout is handled externally, there are few constraints on what information the reaout scheme can contain; customed-named single parameters or parameter lists can be defined with either numerical or string data. This information will be made avaiable via [`GmxInterface`](../components/gmxinterface/)[^abbr] for external tools, and also propagated to dedicated tables in the SQLite files created by e.g. `gmcat`.
The sensitive detectors can be defined by creating a `readoutgeometry` element. Information can be split over classes and types, by defining one or more `sensorclass` elements with information that is common to all types, and which should contain one or more `sensortype` elements which add additional type-specific information. The desired informtion can be defined like in the example below:
```
<readoutgeometry>
<sensorclass name="MySensor">
<param name="ToTBits" value="4"/>
<param name="is3D" value="0"/>
<!-- main Quad type -->
<sensortype name="MySensor1">
<param name="rows" value="200"/>
<param name="columns" value="400"/>
<param name="pitchEta" value="0.050"/>
<param name="pitchPhi" value="0.050"/>
<param name="thickness" value="0.1"/>
</sensortype>
<sensortype name="MySensor2">
<param name="rows" value="400"/>
<param name="columns" value="600"/>
<param name="pitchEta" value="0.025"/>
<param name="pitchPhi" value="0.025"/>
<param name="thickness" value="0.15"/>
</sensortype>
</sensorclass>
</readoutgeometry>
```
The `sensitive` property is used to assign a specific readout scheme to a `logvol`:
```
<logvol name="MySensor" shape="MySensorShape" material="SiMetal" sensitive="MySensor1">
```
NB that the `sensitive` property is always applied to `logvols` and not to assemblies. Any `logvol` which has the `sensitive` property set will have an associated `GeoFullPhysVol` rather than `GeoPhysVol` assocated [(see GeoModelKernel for more details)](../../kernel/overview/#physical-volumes-and-the-geometry-graph).
## Identifying sensitive volumes
To identify specific instances of a sensitive volumes, it can be useful to define hierarchical indices to represent that a given sensor is e.g. the 3rd sensor in $\eta$ on the 2nd barrel layer, etc. This can be done by defining a `positionindex` element, and adding various indices which may want to be counted:
```
<positionindex>
<addindex name="layer"/>
<addindex name="eta_module"/>
</positionindex>
```
These can be set for a `logvol` or `assembly` via an `index` element directly, if the structure of the geometry allows:
```
<assembly name="Layer1" >
<index ref="layer" value="2"/>
[rest of assembly definition]
</assembly>
```
However, it is frequently the case that such volume's index will not be a priori easily known, due to the use of `multicopy` etc. In which case, automated internal couters of the form `CNL_X` can be used. These are dynamically assigned to the various levels in the geometry hierarchy which are iterated over, and so the number `X` is the `depth` in the hierarchy. They can be used either directly, or as part of a function, to define the index, and will dynamically evaluate to the current iteration when queried.
```
<assembly name="Layer1" >
<index ref="eta_module" value="CNL_3"/>
[multicopy over modules, that is 3rd in hierarchy]
</assembly>
```
Setting these indices correctly can be "fiddly" if there are strong external constraints on the ranges/values, and so one should be aware that quite some trial and error may be involved in getting them correct.
## Splitting volumes into multiple readout elements
Occasionally it may be beneficial to split a single `GeoModel` volume into multiple readout elements downstream. This can be achieved by setting the `splitLevel` property of the `logvol`, which can then produce multiple readout instances which share the same `GeoFullPhysVol`. Whenever the `splitlevel` property is encountered, it will call `addSplitSensor` (rather than `addSensor`) for each of the `n` elements into which the single volume should be split, and propagate additional information that can be used to set the indices correctly following the splitting.
*Currently the `splitLevel` assumes that the volumes should be split in the $\eta$ coordinate, and so the indices to be adjusted are assumed to the `eta_module`. Some small code developments would be required to allow this to be fully configurable.*
[^abbr]: these can be accessed via helper functions like `getParameter`/`getParameters` (for single values and vectors respectively)
\ No newline at end of file
# Troubleshooting
Some typical errors that can happen, and how to debug and/or solve them. This is an evolving list and may differ depending on the specific version of `GeoModelXML`, as bugs are solved and others revealed.
- `evaluate: invalid expression. Last good expression was ...`:
This error indicates an issue when XML is being parsed. Check for typos or invalid syntax in defining parameters, providing names to `logvolref`, etc.
\ No newline at end of file
......@@ -28,6 +28,17 @@ nav:
- 'Class Reference': 'components/kernel/reference/index.md'
- GeoModelTools:
- 'GDML2GeoModel': 'components/geomodeltools/gdml2gm/index.md'
- GeoModelXML:
- 'GeoModelXML Overview' : 'components/geomodelxml/index.md'
- 'Building a geometry' : 'components/geomodelxml/buildinggeometry.md'
- 'Defining detector readout' : 'components/geomodelxml/readout.md'
- 'Setting alignment properties' : 'components/geomodelxml/alignment.md'
- Components:
- 'Gmx2Geo': 'components/geomodelxml/components/gmx2geo.md'
- 'GmxInterface' : 'components/geomodelxml/components/gmxinterface.md'
- 'Processors' : 'components/geomodelxml/components/processors.md'
- 'Troubleshooting' : 'components/geomodelxml/troubleshooting.md'
- 'User Guide (old, ATLAS specific)' : 'components/geomodelxml/old.md'
- GeoModelVisualization:
- 'GeoModelExplorer': 'components/geomodelvisualization/gmex/index.md'
- FullSimLight tools:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment