Skip to content

geo

converter.converter.shieldhit.geo

DefaultMaterial

Bases: IntEnum

List of special material ids that are not referring to the mat and have a separate meaning. E.g. Assigning id=1000 to a zone in geo file would mean, that the zone is made out of vacuum, not that it refers to the 1000th item in mat file.

Source code in yaptide/converter/converter/shieldhit/geo.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class DefaultMaterial(IntEnum):
    """
    List of special material ids that are not referring to the `mat` and have a separate
    meaning. E.g. Assigning id=1000 to a zone in `geo` file would mean, that the zone is made out
    of vacuum, not that it refers to the 1000th item in `mat` file.
    """

    BLACK_HOLE = 0
    VACUUM = 1000

    @staticmethod
    def is_default_material(material_value: int) -> bool:
        """Check if the material is one of the predefined default materials."""
        return material_value in DefaultMaterial._value2member_map_

BLACK_HOLE class-attribute instance-attribute

BLACK_HOLE = 0

VACUUM class-attribute instance-attribute

VACUUM = 1000

is_default_material staticmethod

is_default_material(material_value)

Check if the material is one of the predefined default materials.

Source code in yaptide/converter/converter/shieldhit/geo.py
18
19
20
21
@staticmethod
def is_default_material(material_value: int) -> bool:
    """Check if the material is one of the predefined default materials."""
    return material_value in DefaultMaterial._value2member_map_

GeoMatConfig dataclass

Class mapping of the geo.dat config file.

Source code in yaptide/converter/converter/shieldhit/geo.py
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
@dataclass
class GeoMatConfig:
    """Class mapping of the geo.dat config file."""

    figures: list[SolidFigure] = field(default_factory=lambda: [
        CylinderFigure(position=(0., 0., 10.), radius_top=10., radius_bottom=10., height=20., rotation=(90., 0., 0.)),
        CylinderFigure(position=(0., 0., 7.5), radius_top=15., radius_bottom=15., height=25., rotation=(90., 0., 0.)),
        CylinderFigure(position=(0., 0., 5.), radius_top=20., radius_bottom=20., height=30., rotation=(90., 0., 0.)),
    ])
    zones: list[Zone] = field(default_factory=lambda: [
        Zone(
            uuid='',
            id=1,
            figures_operators=[{
                1,
            }],
            material=1,
        ),
        Zone(
            uuid='',
            id=2,
            figures_operators=[{-1, 2}],
            material=1000,
        ),
        Zone(
            uuid='',
            id=3,
            figures_operators=[{-2, 3}],
            material=0,
        ),
    ])
    materials: list[Material] = field(default_factory=lambda: [Material('', '', '', 276)])
    jdbg1: int = 0
    jdbg2: int = 0
    title: str = 'Unnamed geometry'
    available_custom_stopping_power_files: dict[int, StoppingPowerFile] = field(default_factory=lambda: {})

    geo_template: str = """
{jdbg1:>5}{jdbg1:>5}          {title}
{figures}
  END
{zones_geometries}
  END
{zones_materials}
"""

    @staticmethod
    def _split_zones_to_rows(zones: list[int], max_size=14) -> list[list[int]]:
        """Split list of Zones into rows of not more than 14 elements"""
        return [zones[i:min(i + max_size, len(zones))] for i in range(0, len(zones), max_size)]

    def _get_zone_material_string(self) -> str:
        """Generate material_id, zone_id pairs string (for geo.dat)."""
        # Cut lists into chunks of max size 14
        zone_ids = [
            ''.join([f'{id:>5}' for id in row])
            for row in GeoMatConfig._split_zones_to_rows([zone.id for zone in self.zones])
        ]
        material_ids = [
            ''.join([f'{mat:>5}' for mat in row])
            for row in GeoMatConfig._split_zones_to_rows([zone.material for zone in self.zones])
        ]
        return '\n'.join([*zone_ids, *material_ids])

    def get_geo_string(self) -> str:
        """Generate geo.dat config."""
        return self.geo_template.format(
            jdbg1=self.jdbg1,
            jdbg2=self.jdbg2,
            title=self.title,
            # we increment idx because shieldhit indexes from 1 while python indexes lists from 0
            figures=''.join([parse_figure(figure, idx + 1) for idx, figure in enumerate(self.figures)])[1:],
            zones_geometries=''.join([str(zone) for zone in self.zones])[1:],
            zones_materials=self._get_zone_material_string(),
        )

    def get_mat_string(self) -> str:
        """Generate mat.dat config."""
        # we increment idx because shieldhit indexes from 1 while python indexes lists from 0
        material_strings = []
        materials_filtered = filter(lambda x: not DefaultMaterial.is_default_material(x.icru), self.materials)
        for idx, material in enumerate(materials_filtered):
            material.idx = idx + 1
            material_strings.append(str(material))

        return ''.join(material_strings)

available_custom_stopping_power_files class-attribute instance-attribute

available_custom_stopping_power_files = field(
    default_factory=lambda: {}
)

figures class-attribute instance-attribute

figures = field(
    default_factory=lambda: [
        CylinderFigure(
            position=(0.0, 0.0, 10.0),
            radius_top=10.0,
            radius_bottom=10.0,
            height=20.0,
            rotation=(90.0, 0.0, 0.0),
        ),
        CylinderFigure(
            position=(0.0, 0.0, 7.5),
            radius_top=15.0,
            radius_bottom=15.0,
            height=25.0,
            rotation=(90.0, 0.0, 0.0),
        ),
        CylinderFigure(
            position=(0.0, 0.0, 5.0),
            radius_top=20.0,
            radius_bottom=20.0,
            height=30.0,
            rotation=(90.0, 0.0, 0.0),
        ),
    ]
)

geo_template class-attribute instance-attribute

geo_template = "\n{jdbg1:>5}{jdbg1:>5}          {title}\n{figures}\n  END\n{zones_geometries}\n  END\n{zones_materials}\n"

jdbg1 class-attribute instance-attribute

jdbg1 = 0

jdbg2 class-attribute instance-attribute

jdbg2 = 0

materials class-attribute instance-attribute

materials = field(
    default_factory=lambda: [Material("", "", "", 276)]
)

title class-attribute instance-attribute

title = 'Unnamed geometry'

zones class-attribute instance-attribute

zones = field(
    default_factory=lambda: [
        Zone(
            uuid="",
            id=1,
            figures_operators=[{1}],
            material=1,
        ),
        Zone(
            uuid="",
            id=2,
            figures_operators=[{-1, 2}],
            material=1000,
        ),
        Zone(
            uuid="",
            id=3,
            figures_operators=[{-2, 3}],
            material=0,
        ),
    ]
)

__init__

__init__(
    figures=lambda: [
        CylinderFigure(
            position=(0.0, 0.0, 10.0),
            radius_top=10.0,
            radius_bottom=10.0,
            height=20.0,
            rotation=(90.0, 0.0, 0.0),
        ),
        CylinderFigure(
            position=(0.0, 0.0, 7.5),
            radius_top=15.0,
            radius_bottom=15.0,
            height=25.0,
            rotation=(90.0, 0.0, 0.0),
        ),
        CylinderFigure(
            position=(0.0, 0.0, 5.0),
            radius_top=20.0,
            radius_bottom=20.0,
            height=30.0,
            rotation=(90.0, 0.0, 0.0),
        ),
    ](),
    zones=lambda: [
        Zone(
            uuid="",
            id=1,
            figures_operators=[{1}],
            material=1,
        ),
        Zone(
            uuid="",
            id=2,
            figures_operators=[{-1, 2}],
            material=1000,
        ),
        Zone(
            uuid="",
            id=3,
            figures_operators=[{-2, 3}],
            material=0,
        ),
    ](),
    materials=lambda: [Material("", "", "", 276)](),
    jdbg1=0,
    jdbg2=0,
    title="Unnamed geometry",
    available_custom_stopping_power_files=lambda: {}(),
    geo_template="\n{jdbg1:>5}{jdbg1:>5}          {title}\n{figures}\n  END\n{zones_geometries}\n  END\n{zones_materials}\n",
)

get_geo_string

get_geo_string()

Generate geo.dat config.

Source code in yaptide/converter/converter/shieldhit/geo.py
226
227
228
229
230
231
232
233
234
235
236
def get_geo_string(self) -> str:
    """Generate geo.dat config."""
    return self.geo_template.format(
        jdbg1=self.jdbg1,
        jdbg2=self.jdbg2,
        title=self.title,
        # we increment idx because shieldhit indexes from 1 while python indexes lists from 0
        figures=''.join([parse_figure(figure, idx + 1) for idx, figure in enumerate(self.figures)])[1:],
        zones_geometries=''.join([str(zone) for zone in self.zones])[1:],
        zones_materials=self._get_zone_material_string(),
    )

get_mat_string

get_mat_string()

Generate mat.dat config.

Source code in yaptide/converter/converter/shieldhit/geo.py
238
239
240
241
242
243
244
245
246
247
def get_mat_string(self) -> str:
    """Generate mat.dat config."""
    # we increment idx because shieldhit indexes from 1 while python indexes lists from 0
    material_strings = []
    materials_filtered = filter(lambda x: not DefaultMaterial.is_default_material(x.icru), self.materials)
    for idx, material in enumerate(materials_filtered):
        material.idx = idx + 1
        material_strings.append(str(material))

    return ''.join(material_strings)

Material dataclass

Dataclass mapping for SH12A materials.

Source code in yaptide/converter/converter/shieldhit/geo.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
@dataclass
class Material:
    """Dataclass mapping for SH12A materials."""

    name: str
    sanitized_name: str
    uuid: str
    icru: int
    density: Optional[float] = None
    custom_stopping_power: bool = False
    idx: int = 0

    property_template = """{name} {value}\n"""
    property_template_name = """{name}\n"""

    def __str__(self) -> str:
        result = self.property_template.format(name='MEDIUM', value=self.idx)
        result += self.property_template.format(name='ICRU', value=self.icru)
        if self.density is not None:
            result += self.property_template.format(name='RHO', value=format_float(self.density, 10))

        if self.custom_stopping_power:
            result += self.property_template_name.format(name='LOADDEDX')

        result += 'END\n'
        return result

custom_stopping_power class-attribute instance-attribute

custom_stopping_power = False

density class-attribute instance-attribute

density = None

icru instance-attribute

icru

idx class-attribute instance-attribute

idx = 0

name instance-attribute

name

property_template class-attribute instance-attribute

property_template = '{name} {value}\n'

property_template_name class-attribute instance-attribute

property_template_name = '{name}\n'

sanitized_name instance-attribute

sanitized_name

uuid instance-attribute

uuid

__init__

__init__(
    name,
    sanitized_name,
    uuid,
    icru,
    density=None,
    custom_stopping_power=False,
    idx=0,
    property_template="{name} {value}\n",
    property_template_name="{name}\n",
)

__str__

__str__()
Source code in yaptide/converter/converter/shieldhit/geo.py
118
119
120
121
122
123
124
125
126
127
128
def __str__(self) -> str:
    result = self.property_template.format(name='MEDIUM', value=self.idx)
    result += self.property_template.format(name='ICRU', value=self.icru)
    if self.density is not None:
        result += self.property_template.format(name='RHO', value=format_float(self.density, 10))

    if self.custom_stopping_power:
        result += self.property_template_name.format(name='LOADDEDX')

    result += 'END\n'
    return result

StoppingPowerFile dataclass

Dataclass mapping for SH12A stopping power files.

Source code in yaptide/converter/converter/shieldhit/geo.py
153
154
155
156
157
158
159
@dataclass
class StoppingPowerFile:
    """Dataclass mapping for SH12A stopping power files."""

    icru: int
    name: str
    content: str

content instance-attribute

content

icru instance-attribute

icru

name instance-attribute

name

__init__

__init__(icru, name, content)

Zone dataclass

Dataclass mapping for SH12A zones.

Source code in yaptide/converter/converter/shieldhit/geo.py
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
@dataclass
class Zone:
    """Dataclass mapping for SH12A zones."""

    uuid: str

    id: int = 1
    figures_operators: list[set[int]] = field(default_factory=lambda: [{1}])
    material: int = 0
    material_override: dict[str, str] = field(default_factory=dict)

    zone_template: str = """
  {id:03d}       {operators}"""

    def __str__(self) -> str:
        return self.zone_template.format(
            id=self.id,
            operators='OR'.join(['  '.join([f'{id:+5}' for id in figure_set])
                                 for figure_set in self.figures_operators]),
        )

figures_operators class-attribute instance-attribute

figures_operators = field(default_factory=lambda: [{1}])

id class-attribute instance-attribute

id = 1

material class-attribute instance-attribute

material = 0

material_override class-attribute instance-attribute

material_override = field(default_factory=dict)

uuid instance-attribute

uuid

zone_template class-attribute instance-attribute

zone_template = '\n  {id:03d}       {operators}'

__init__

__init__(
    uuid,
    id=1,
    figures_operators=lambda: [{1}](),
    material=0,
    material_override=dict(),
    zone_template="\n  {id:03d}       {operators}",
)

__str__

__str__()
Source code in yaptide/converter/converter/shieldhit/geo.py
145
146
147
148
149
150
def __str__(self) -> str:
    return self.zone_template.format(
        id=self.id,
        operators='OR'.join(['  '.join([f'{id:+5}' for id in figure_set])
                             for figure_set in self.figures_operators]),
    )

parse_figure

parse_figure(figure, number)

Parse a SolidFigure into a string representation of SH12A input file.

Source code in yaptide/converter/converter/shieldhit/geo.py
24
25
26
27
28
29
30
31
32
33
def parse_figure(figure: SolidFigure, number: int) -> str:
    """Parse a SolidFigure into a string representation of SH12A input file."""
    if type(figure) is BoxFigure:
        return _parse_box(figure, number)
    if type(figure) is CylinderFigure:
        return _parse_cylinder(figure, number)
    if type(figure) is SphereFigure:
        return _parse_sphere(figure, number)

    raise ValueError(f'Unexpected solid figure type: {figure}')