File indexing completed on 2026-11-09 10:47:17
0001 """
0002 Author : Andrii Tykhonov (andrii.tykhonov@cern.ch)
0003 Description : A light-weight tool to convert CAD drawings
0004 (.stl) into geant4 compatible format (.gdml)
0005
0006 MIT License
0007
0008 Copyright (c) 2018 Andrii Tykhonov
0009
0010 Permission is hereby granted, free of charge, to any person obtaining a copy
0011 of this software and associated documentation files (the "Software"), to deal
0012 in the Software without restriction, including without limitation the rights
0013 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0014 copies of the Software, and to permit persons to whom the Software is
0015 furnished to do so, subject to the following conditions:
0016
0017 The above copyright notice and this permission notice shall be included in all
0018 copies or substantial portions of the Software.
0019
0020 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0021 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0022 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0023 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0024 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
0025 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0026 SOFTWARE.
0027
0028
0029 """
0030
0031 import ast
0032 import argparse
0033 import sys
0034
0035 from bisect import bisect
0036 import __main__
0037
0038 if int(sys.version_info.major)>=3:
0039 xrange = range
0040
0041 EMAIL = "andrii.tykhonov@cernSPAMNOT.ch"
0042 ERROR_CONTACT = "\nPlease contact %s for more information"%EMAIL
0043
0044 HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n'
0045 SCHEMA = '<gdml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://service-spi.web.cern.ch/service-spi/app/releases/GDML/schema/gdml.xsd">\n'
0046 FOOTER = '</gdml>'
0047
0048
0049 AUNIT = 'deg'
0050 LUNIT = 'mm'
0051
0052 X_OFFSET = 0.0
0053 Y_OFFSET = 0.0
0054 Z_OFFSET = 0.0
0055
0056
0057 MATERIALS_INFO = '''
0058
0059 #@
0060 #@ So far, following complex materials are implemented:
0061 #@ - Vacuum
0062 #@ - Mechanic tructures
0063 #@ - Aluminum
0064 #@ - Honeycomb (Aluminum)
0065 #@ - CarbonFibre
0066 #@ - Adhesives
0067 #@ - DC3140 (Glue, Dow Corning)
0068 #@ - PCB
0069 #@ - FR4
0070 #@ - Copper
0071 #@ - Kapton
0072 #@ - Gold
0073 #@ - Nickel
0074 #@ - Titanium
0075 #@ - Silver
0076 #@ - Palladium
0077 #@ - Tin
0078 #@ - Platinum
0079 #@ - Detector materials:
0080 #@ - Silicon
0081 #@ - CdTe
0082 #@ - Tungsten
0083 #@ - PMT
0084 #@ - BGO
0085 #@ - BC254 (neutron detector)
0086 #@ - CdWO4 (cadmium tungstanate)
0087 #@ - Others:
0088 #@ - Glass
0089 #@ - Lead
0090 #@ - Q235 (Steel)
0091 #@ - AL5052-H32 (Aluminium alloy)
0092 #@ - Brass
0093 #@ - FibrousGlass
0094 #@ - PDMS: Polydimethylsiloxane (Silicon Rubber)
0095 #@ - EpoxyResin
0096 #@ - AlNO
0097 #@ - SAC305
0098 #@
0099 #@ Please contact the author to implement more materials,
0100 #@ or (and) feel free to implement them yourself
0101 #@
0102 '''
0103
0104 MATERIALS_LIST = [
0105 {"name" : "Vacuum", "group" : "Other"},
0106 {"name" : "Aluminum", "group" : "Mechanic tructures"},
0107 {"name" : "Honeycomb", "group" : "Mechanic tructures"},
0108 {"name" : "CarbonFibre", "group" : "Mechanic tructures"},
0109 {"name" : "DC3140", "group" : "Adhesives"},
0110 {"name" : "FR4", "group" : "PCB"},
0111 {"name" : "Copper", "group" : "PCB"},
0112 {"name" : "Gold", "group" : "PCB"},
0113 {"name" : "Nickel", "group" : "PCB"},
0114 {"name" : "Titanium", "group" : "PCB"},
0115 {"name" : "Silver", "group" : "PCB"},
0116 {"name" : "Palladium", "group" : "PCB"},
0117 {"name" : "Tin", "group" : "PCB"},
0118 {"name" : "Platinum", "group" : "PCB"},
0119 {"name" : "Silicon", "group" : "Detector Elements"},
0120 {"name" : "CdTe", "group" : "Detector Elements"},
0121 {"name" : "Tungsten", "group" : "Detector Elements"},
0122 {"name" : "PMT", "group" : "Detector Elements"},
0123 {"name" : "BGO", "group" : "Detector Elements"},
0124 {"name" : "BC254", "group" : "Detector Elements"},
0125 {"name" : "CdWO4", "group" : "Detector Elements"},
0126 {"name" : "Glass", "group" : "Other"},
0127 {"name" : "FibrousGlass", "group" : "Other"},
0128 {"name" : "PDMS", "group" : "Other"},
0129 {"name" : "EpoxyResin", "group" : "Other"},
0130 {"name" : "AlNO", "group" : "Other"},
0131 {"name" : "SAC305", "group" : "Other"},
0132 {"name" : "Lead", "group" : "Other"},
0133 {"name" : "Q235", "group" : "Other"},
0134 {"name" : "AL5052-H32", "group" : "Other"},
0135 {"name" : "Brass", "group" : "Other"},
0136 ]
0137
0138 MATERIALS = '''
0139 <materials>
0140 <!-- -->
0141 <!-- elements -->
0142 <!-- -->
0143 <!-- http://www-cdf.fnal.gov/~kirby/lbne_geo_tests/lbne_10kT_Materials.gdml -->
0144 <element name="videRef" formula="VACUUM" Z="1"> <atom value="1."/> </element>
0145 <element name="hydrogen" formula="H" Z="1"> <atom value="1.0079"/> </element>
0146 <element name="carbon" formula="C" Z="6"> <atom value="12.0107"/> </element>
0147 <element name="nitrogen" formula="N" Z="7"> <atom value="14.0067"/> </element>
0148 <element name="oxygen" formula="O" Z="8"> <atom value="15.999"/> </element>
0149 <element name="sodium" formula="Na" Z="11"> <atom value="22.99"/> </element>
0150 <element name="magnesium" formula="Mg" Z="12"> <atom value="24.305"/> </element>
0151 <element name="aluminum" formula="Al" Z="13"> <atom value="26.9815"/> </element>
0152 <element name="silicon" formula="Si" Z="14"> <atom value="28.0855"/> </element>
0153 <element name="phosphorus" formula="P" Z="15"> <atom value="30.973"/> </element>
0154 <element name="sulphur" formula="S" Z="16"> <atom value="32.065"/> </element>
0155 <element name="argon" formula="Ar" Z="18"> <atom value="39.9480"/> </element>
0156 <element name="potassium" formula="K" Z="19"> <atom value="39.0983"/> </element>
0157 <element name="calcium" formula="Ca" Z="20"> <atom value="40.078"/> </element>
0158 <element name="titanium" formula="Ti" Z="22"> <atom value="47.867"/> </element>
0159 <element name="chromium" formula="Cr" Z="24"> <atom value="51.9961"/> </element>
0160 <element name="manganese" formula="Mn" Z="25"> <atom value="54.9380"/> </element>
0161 <element name="iron" formula="Fe" Z="26"> <atom value="55.8450"/> </element>
0162 <element name="nickel" formula="Ni" Z="28"> <atom value="58.6934"/> </element>
0163 <element name="copper" formula="Cu" Z="29"> <atom value="63.55"/> </element>
0164 <element name="germanium" formula="Ge" Z="32"> <atom value="72.63"/> </element>
0165 <element name="bromine" formula="Br" Z="35"> <atom value="79.904"/> </element>
0166 <element name="palladium" formula="Pd" Z="46"> <atom value="106.42"/> </element>
0167 <element name="tin" formula="Sn" Z="50"> <atom value="118.71"/> </element>
0168 <element name="platinum" formula="Pt" Z="78"> <atom value="195.084"/> </element>
0169 <element name="gold" formula="Au" Z="79"> <atom value="196.97"/> </element>
0170 <element name="tungsten" formula="W" Z="74"> <atom value="183.84"/> </element>
0171 <element name="bismuth" formula="Bi" Z="83"> <atom value="208.980"/> </element>
0172
0173
0174 <!-- -->
0175 <!-- composite elements -->
0176 <!-- -->
0177
0178 <isotope name="B10" N="5" Z="5"> <atom unit="g/mole" value="10.0129369"/> </isotope>
0179 <isotope name="B11" N="6" Z="5"> <atom unit="g/mole" value="11.0093054"/> </isotope>
0180 <element name="B">
0181 <fraction n="0.199" ref="B10"/>
0182 <fraction n="0.801" ref="B11"/>
0183 </element>
0184
0185 <isotope name="Zn64" N="34" Z="30"> <atom unit="g/mole" value="63.9291422"/> </isotope>
0186 <isotope name="Zn66" N="36" Z="30"> <atom unit="g/mole" value="65.9260334"/> </isotope>
0187 <isotope name="Zn67" N="37" Z="30"> <atom unit="g/mole" value="66.9271273"/> </isotope>
0188 <isotope name="Zn68" N="38" Z="30"> <atom unit="g/mole" value="67.9248442"/> </isotope>
0189 <isotope name="Zn70" N="40" Z="30"> <atom unit="g/mole" value="69.9253193"/> </isotope>
0190 <element name="zink">
0191 <!-- see: https://en.wikipedia.org/wiki/Isotopes_of_zinc -->
0192 <fraction n="0.492" ref="Zn64"/>
0193 <fraction n="0.277" ref="Zn66"/>
0194 <fraction n="0.040" ref="Zn67"/>
0195 <fraction n="0.185" ref="Zn68"/>
0196 <fraction n="0.006" ref="Zn70"/>
0197 </element>
0198
0199 <isotope name="Ag107" N="60" Z="47"> <atom value="106.905092"/> </isotope>
0200 <isotope name="Ag109" N="62" Z="47"> <atom value="108.904756"/> </isotope>
0201 <element name="silver">
0202 <!-- https://www.webelements.com/silver/isotopes.html -->
0203 <fraction n="0.51839" ref="Ag107"/>
0204 <fraction n="0.48161" ref="Ag109"/>
0205 </element>
0206
0207 <isotope name="Sb121" N="70" Z="51"> <atom value="120.9038157"/> </isotope>
0208 <isotope name="Sb122" N="71" Z="51"> <atom value="121.9051737"/> </isotope>
0209 <element name="antimony">
0210 <!-- https://en.wikipedia.org/wiki/Isotopes_of_antimony -->
0211 <fraction n="0.572" ref="Sb121"/>
0212 <fraction n="0.428" ref="Sb122"/>
0213 </element>
0214
0215 <isotope name="Cd106Cd" N="58" Z="48"> <atom unit="g/mole" value="105.906461"/> </isotope>
0216 <isotope name="Cd108Cd" N="60" Z="48"> <atom unit="g/mole" value="107.904176"/> </isotope>
0217 <isotope name="Cd110Cd" N="62" Z="48"> <atom unit="g/mole" value="109.903005"/> </isotope>
0218 <isotope name="Cd111Cd" N="63" Z="48"> <atom unit="g/mole" value="110.904182"/> </isotope>
0219 <isotope name="Cd112Cd" N="64" Z="48"> <atom unit="g/mole" value="111.902757"/> </isotope>
0220 <isotope name="Cd113Cd" N="65" Z="48"> <atom unit="g/mole" value="112.904400"/> </isotope>
0221 <isotope name="Cd114Cd" N="66" Z="48"> <atom unit="g/mole" value="113.903357"/> </isotope>
0222 <isotope name="Cd116Cd" N="68" Z="48"> <atom unit="g/mole" value="115.904755"/> </isotope>
0223 <element name="cadmium">
0224 <!-- isotopes taken in the natural abundance -->
0225 <!-- taken from https://www.webelements.com/cadmium/isotopes.html -->
0226 <fraction ref="Cd106Cd" n="0.0125"/>
0227 <fraction ref="Cd108Cd" n="0.0089"/>
0228 <fraction ref="Cd110Cd" n="0.1249"/>
0229 <fraction ref="Cd111Cd" n="0.1280"/>
0230 <fraction ref="Cd112Cd" n="0.2413"/>
0231 <fraction ref="Cd113Cd" n="0.1222"/>
0232 <fraction ref="Cd114Cd" n="0.2873"/>
0233 <fraction ref="Cd116Cd" n="0.0749"/>
0234 </element>
0235
0236 <isotope name="Te120Te" N="68" Z="52"> <atom unit="g/mole" value="119.904048"/> </isotope>
0237 <isotope name="Te122Te" N="70" Z="52"> <atom unit="g/mole" value="121.903050"/> </isotope>
0238 <isotope name="Te123Te" N="71" Z="52"> <atom unit="g/mole" value="122.9042710"/> </isotope>
0239 <isotope name="Te124Te" N="72" Z="52"> <atom unit="g/mole" value="123.9028180"/> </isotope>
0240 <isotope name="Te125Te" N="73" Z="52"> <atom unit="g/mole" value="124.9044285"/> </isotope>
0241 <isotope name="Te126Te" N="74" Z="52"> <atom unit="g/mole" value="125.9033095"/> </isotope>
0242 <isotope name="Te128Te" N="76" Z="52"> <atom unit="g/mole" value="127.904463"/> </isotope>
0243 <isotope name="Te130Te" N="78" Z="52"> <atom unit="g/mole" value="129.906229"/> </isotope>
0244 <element name="tellurium">
0245 <!-- see https://www.webelements.com/tellurium/isotopes.html -->
0246 <fraction ref="Te120Te" n="0.0009"/>
0247 <fraction ref="Te122Te" n="0.0255"/>
0248 <fraction ref="Te123Te" n="0.0089"/>
0249 <fraction ref="Te124Te" n="0.0474"/>
0250 <fraction ref="Te125Te" n="0.0707"/>
0251 <fraction ref="Te126Te" n="0.1884"/>
0252 <fraction ref="Te128Te" n="0.3174"/>
0253 <fraction ref="Te130Te" n="0.3408"/>
0254 </element>
0255
0256 <isotope name="Pb208" N="126" Z="82"> <atom unit="g/mole" value="207.9766521"/> </isotope>
0257 <isotope name="Pb207" N="125" Z="82"> <atom unit="g/mole" value="206.9758969"/> </isotope>
0258 <isotope name="Pb206" N="124" Z="82"> <atom unit="g/mole" value="205.9744653"/> </isotope>
0259 <isotope name="Pb204" N="122" Z="82"> <atom unit="g/mole" value="203.9730430"/> </isotope>
0260 <element name="lead">
0261 <!-- see https://en.wikipedia.org/wiki/Isotopes_of_lead -->
0262 <fraction ref="Pb208" n="0.524"/>
0263 <fraction ref="Pb207" n="0.221"/>
0264 <fraction ref="Pb206" n="0.241"/>
0265 <fraction ref="Pb204" n="0.014"/>
0266 </element>
0267
0268
0269
0270 <!-- -->
0271 <!-- vacuum -->
0272 <!-- -->
0273 <material formula=" " name="Vacuum">
0274 <D value="1.e-25" unit="g/cm3" />
0275 <fraction n="1.0" ref="videRef" />
0276 </material>
0277
0278
0279
0280 <!-- -->
0281 <!-- materials -->
0282 <!-- -->
0283
0284 <!-- FR4 submaterials -->
0285
0286 <material name="EpoxyResin" formula="C38H40O6Br4">
0287 <D value="1.1250" unit="g/cm3"/>
0288 <composite n="38" ref="carbon"/>
0289 <composite n="40" ref="hydrogen"/>
0290 <composite n="6" ref="oxygen"/>
0291 <composite n="4" ref="bromine"/>
0292 </material>
0293
0294 <material name="SiO2" formula="SiO2">
0295 <D value="2.2" unit="g/cm3"/>
0296 <composite n="1" ref="silicon"/>
0297 <composite n="2" ref="oxygen"/>
0298 </material>
0299
0300 <material name="Al2O3" formula="Al2O3">
0301 <D value="3.97" unit="g/cm3"/>
0302 <composite n="2" ref="aluminum"/>
0303 <composite n="3" ref="oxygen"/>
0304 </material>
0305
0306 <material name="Fe2O3" formula="Fe2O3">
0307 <D value="5.24" unit="g/cm3"/>
0308 <composite n="2" ref="iron"/>
0309 <composite n="3" ref="oxygen"/>
0310 </material>
0311
0312 <material name="CaO" formula="CaO">
0313 <D value="3.35" unit="g/cm3"/>
0314 <composite n="1" ref="calcium"/>
0315 <composite n="1" ref="oxygen"/>
0316 </material>
0317
0318 <material name="MgO" formula="MgO">
0319 <D value="3.58" unit="g/cm3"/>
0320 <composite n="1" ref="magnesium"/>
0321 <composite n="1" ref="oxygen"/>
0322 </material>
0323
0324 <material name="Na2O" formula="Na2O">
0325 <D value="2.27" unit="g/cm3"/>
0326 <composite n="2" ref="sodium"/>
0327 <composite n="1" ref="oxygen"/>
0328 </material>
0329
0330 <material name="TiO2" formula="TiO2">
0331 <D value="4.23" unit="g/cm3"/>
0332 <composite n="1" ref="titanium"/>
0333 <composite n="2" ref="oxygen"/>
0334 </material>
0335
0336 <material name="FibrousGlass">
0337 <D value="2.74351" unit="g/cm3"/>
0338 <fraction n="0.600" ref="SiO2"/>
0339 <fraction n="0.118" ref="Al2O3"/>
0340 <fraction n="0.001" ref="Fe2O3"/>
0341 <fraction n="0.224" ref="CaO"/>
0342 <fraction n="0.034" ref="MgO"/>
0343 <fraction n="0.010" ref="Na2O"/>
0344 <fraction n="0.013" ref="TiO2"/>
0345 </material>
0346
0347 <material name="FR4">
0348 <D value="1.98281" unit="g/cm3"/>
0349 <fraction n="0.47" ref="EpoxyResin"/>
0350 <fraction n="0.53" ref="FibrousGlass"/>
0351 </material>
0352
0353
0354 <!-- Glue (DC3140, Dow Corning) sub materials -->
0355
0356 <material name="dimethylsiloxane_hydroxy_terminated" formula="HOSiCH3CH3OH">
0357 <D value="0.98" unit="g/cm3"/>
0358 <composite n="2" ref="oxygen"/>
0359 <composite n="8" ref="hydrogen"/>
0360 <composite n="2" ref="carbon"/>
0361 <composite n="1" ref="silicon"/>
0362 </material>
0363
0364 <material name="trimethylated_silica" formula="O2Si">
0365 <D value="2.6" unit="g/cm3"/>
0366 <composite n="2" ref="oxygen"/>
0367 <composite n="1" ref="silicon"/>
0368 </material>
0369
0370 <material name="methyltrimethoxysilane" formula="C4H12O3Si">
0371 <D value="0.955" unit="g/cm3"/>
0372 <composite n="3" ref="oxygen"/>
0373 <composite n="12" ref="hydrogen"/>
0374 <composite n="4" ref="carbon"/>
0375 <composite n="1" ref="silicon"/>
0376 </material>
0377
0378 <material name="DC3140">
0379 <D value="1.2" unit="g/cm3"/>
0380 <fraction n="0.60" ref="dimethylsiloxane_hydroxy_terminated"/>
0381 <fraction n="0.30" ref="trimethylated_silica"/>
0382 <fraction n="0.10" ref="methyltrimethoxysilane"/>
0383 </material>
0384
0385
0386 <!-- Conductive materials for PCB -->
0387
0388 <material name="Copper" state="solid">
0389 <D value="8.960" unit="g/cm3"/>
0390 <fraction n="1." ref="copper"/>
0391 </material>
0392
0393 <material name="Gold" state="solid">
0394 <D value="19.32" unit="g/cm3"/>
0395 <fraction n="1." ref="gold"/>
0396 </material>
0397
0398
0399 <material name="Nickel" state="solid">
0400 <D value="8.96" unit="g/cm3"/>
0401 <fraction n="1." ref="nickel"/>
0402 </material>
0403
0404 <material name="Titanium" state="solid">
0405 <!--http://www.rsc.org/periodic-table/element/22/titanium -->
0406 <D value="4.506" unit="g/cm3"/>
0407 <fraction n="1." ref="titanium"/>
0408 </material>
0409
0410
0411 <material name="Silver" state="solid">
0412 <!-- see https://en.wikipedia.org/wiki/Silver -->
0413 <D value="10.49" unit="g/cm3"/>
0414 <fraction n="1." ref="silver"/>
0415 </material>
0416
0417 <material name="Cadmium" state="solid">
0418 <!-- see https://www.lenntech.com/periodic/elements/cd.htm -->
0419 <D value="8.7" unit="g/cm3"/>
0420 <fraction n="1." ref="cadmium"/>
0421 </material>
0422
0423 <material name="Palladium" state="solid">
0424 <!-- see http://www.rsc.org/periodic-table/element/46/palladium -->
0425 <D value="12.0" unit="g/cm3"/>
0426 <fraction n="1." ref="palladium"/>
0427 </material>
0428
0429 <material name="Tin" state="solid">
0430 <!-- see http://www.rsc.org/periodic-table/element/50/tin -->
0431 <D value="7.287" unit="g/cm3"/>
0432 <fraction n="1." ref="tin"/>
0433 </material>
0434
0435 <material name="Tellurium" state="solid">
0436 <!-- see http://www.rsc.org/periodic-table/element/52/tellurium -->
0437 <D value="6.232" unit="g/cm3"/>
0438 <fraction n="1." ref="tellurium"/>
0439 </material>
0440
0441 <material name="Lead" state="solid">
0442 <!-- see https://en.wikipedia.org/wiki/Lead -->
0443 <D value="11.34" unit="g/cm3"/>
0444 <fraction n="1." ref="lead"/>
0445 </material>
0446
0447 <material name="Q235" state="solid"> <!-- STEEL -->
0448 <!-- density, see: https://www.chinesesteelgrades.com/q235-steel/ -->
0449 <D value="7.85" unit="g/cm3"/>
0450 <fraction n="0.980" ref="iron"/>
0451 <fraction n="0.014" ref="manganese"/>
0452 <fraction n="0.004" ref="silicon"/>
0453 <fraction n="0.002" ref="carbon"/>
0454 </material>
0455
0456 <material name="AL5052-H32" state="solid"> <!-- ALUMINUIM ALLOY -->
0457 <D value="2.68" unit="g/cm3"/>
0458 <fraction n="0.969" ref="aluminum"/>
0459 <fraction n="0.025" ref="magnesium"/>
0460 <fraction n="0.003" ref="iron"/>
0461 <fraction n="0.002" ref="chromium"/>
0462 <fraction n="0.001" ref="silicon"/>
0463 </material>
0464
0465 <material name="Brass" state="solid"> <!-- brass: http://www.aatongdiao.com/en/new/new-73-571.html -->
0466 <D value="8.73" unit="g/cm3"/>
0467 <fraction n="0.61" ref="copper"/>
0468 <fraction n="0.39" ref="zink"/>
0469 </material>
0470
0471 <material name="Platinum" state="solid">
0472 <!-- see http://www.rsc.org/periodic-table/element/78/platinum -->
0473 <D value="21.5" unit="g/cm3"/>
0474 <fraction n="1." ref="platinum"/>
0475 </material>
0476
0477
0478 <!-- Passivation -->
0479
0480 <material name="AlNO" state="solid" formula="AlNO">
0481 <!-- Aluminum oxynitride -->
0482 <!-- see https://en.wikipedia.org/wiki/Aluminium_oxynitride -->
0483 <!-- see https://webbook.nist.gov/cgi/formula?ID=B1000046&Mask=800 -->
0484 <D value="3.6935" unit="g/cm3"/>
0485 <composite n="1" ref="aluminum"/>
0486 <composite n="1" ref="nitrogen"/>
0487 <composite n="1" ref="oxygen"/>
0488 </material>
0489
0490 <!-- Bonding -->
0491
0492 <material name="SAC305" state="solid">
0493 <!-- see https://www.aimsolder.com/sites/default/files/alloy_sac305_tds.pdf -->
0494 <!-- see https://cdn.sos.sk/productdata/73/d6/578230e0/sac305-sn96-5ag3cu0-5-0-7mm-1kg.pdf -->
0495 <D value="7.37" unit="g/cm3"/>
0496 <fraction n="0.965" ref="Tin"/>
0497 <fraction n="0.030" ref="Silver"/>
0498 <fraction n="0.005" ref="Copper"/>
0499 </material>
0500
0501
0502
0503
0504 <!-- Kapton -->
0505
0506 <material name="Kapton" state="solid">
0507 <D value="1.42" unit="g/cm3"/>
0508 <fraction n="0.0273" ref="hydrogen"/>
0509 <fraction n="0.7213" ref="carbon"/>
0510 <fraction n="0.0765" ref="nitrogen"/>
0511 <fraction n="0.1749" ref="oxygen"/>
0512 </material>
0513
0514
0515
0516 <!-- Aluminum, Hineycomb, Carbon fibre, etc. (simple materials) -->
0517
0518 <material formula="Al" name="Aluminum" state="solid">
0519 <D value="2.700" unit="g/cm3"/>
0520 <fraction n="1." ref="aluminum"/>
0521 </material>
0522
0523 <material name="CarbonFibre" state="solid">
0524 <D unit="g/cm3" value="1.55"/>
0525 <fraction n="0.85" ref="carbon"/>
0526 <fraction n="0.03" ref="hydrogen"/>
0527 <fraction n="0.04" ref="nitrogen"/>
0528 <fraction n="0.08" ref="oxygen"/>
0529 </material>
0530
0531 <material name="Honeycomb" state="solid">
0532 <D value="0.030" unit="g/cm3"/>
0533 <fraction n="1." ref="aluminum"/>
0534 </material>
0535
0536 <!-- Silicon -->
0537 <material name="Silicon" state="solid">
0538 <D value="2.333" unit="g/cm3"/>
0539 <fraction n="1." ref="silicon"/>
0540 </material>
0541
0542 <!-- Tungsten -->
0543 <material name="Tungsten" state="solid">
0544 <D value="19.3" unit="g/cm3"/>
0545 <fraction n="1." ref="tungsten"/>
0546 </material>
0547
0548 <!-- Cadmium Telluride -->
0549 <material name="CdTe" state="solid">
0550 <!--https://www.azom.com/article.aspx?ArticleID=8408-->
0551 <D value="5.85" unit="g/cm3"/>
0552 <composite n="1" ref="cadmium"/>
0553 <composite n="1" ref="tellurium"/>
0554 </material>
0555
0556 <!-- PMT -->
0557 <!--sylgard 170, Silicon Rubber Polydimethylsiloxane(PDMS)-->
0558 <material name="PDMS" formula="SiOC2H6" >
0559 <D value="1.34" unit="g/cm3" />
0560 <composite n="1" ref="silicon" />
0561 <composite n="1" ref="oxygen" />
0562 <composite n="2" ref="carbon" />
0563 <composite n="6" ref="hydrogen" />
0564 </material>
0565
0566 <material name="Glass" formula="SiO2" >
0567 <D value="2.5" unit="g/cm3" />
0568 <composite n="1" ref="silicon" />
0569 <composite n="2" ref="oxygen" />
0570 </material>
0571
0572 <material name="PMT" state="solid">
0573 <D value="2.524" unit="g/cm3"/>
0574 <fraction n="0.7" ref="aluminum"/>
0575 <fraction n="0.2" ref="Glass"/>
0576 <fraction n="0.1" ref="PDMS"/>
0577 </material>
0578
0579 <!-- BGO -->
0580 <material name="BGO" formula="Bi4Ge3O12" >
0581 <D value="7.13" unit="g/cm3" />
0582 <composite n="4" ref="bismuth" />
0583 <composite n="3" ref="germanium" />
0584 <composite n="12" ref="oxygen" />
0585 </material>
0586
0587
0588 <!-- BC254 (neutron detector) -->
0589 <material name="BC254" state="solid">
0590 <MEE unit="eV" value="173"/>
0591 <D unit="g/cm3" value="1.026"/>
0592 <fraction n="0.2492" ref="carbon"/>
0593 <fraction n="0.7475" ref="hydrogen"/>
0594 <fraction n="0.0033" ref="B"/>
0595 </material>
0596
0597 <!-- CdWO4 -->
0598 <!-- see https://www.tandfonline.com/doi/pdf/10.1080/00223131.2008.10875862 -->
0599 <!-- see https://www.convertunits.com/molarmass/CdWO4 -->
0600 <material name="CdWO4" state="solid">
0601 <D unit="g/cm3" value="7.9"/>
0602 <fraction n="0.510" ref="tungsten"/>
0603 <fraction n="0.312" ref="cadmium"/>
0604 <fraction n="0.178" ref="oxygen"/>
0605 </material>
0606
0607 </materials>
0608 '''
0609
0610
0611 WORLD = '''
0612 <setup name="Default" version="1.0">
0613 <world ref="%s"/>
0614 </setup>
0615 '''
0616
0617 STRUCTURE = '''
0618 <structure>
0619 <volume name="%s">
0620 <materialref ref="%s"/>
0621 <solidref ref="%s"/>%s
0622 </volume>
0623 </structure>
0624 '''
0625
0626 MODULE_NAME = __main__.__file__.split("/")[-1].split("\\")[-1]
0627 HELP_MESSAGE = '''
0628
0629 Usage:
0630 python %s out_name input_file_1.stl input_file_2.stl input_file_N.stl"
0631
0632 or
0633
0634 python %s out_name path_to_stl_file/blah_blah_*.stl
0635
0636
0637 Materials:
0638
0639 Material are encoded in the stl file name
0640 For instance, my_geometry_part_Aluminum.stl - this part will be parsed as made of aluminum
0641 See %s --materials to display list of available materials
0642
0643
0644 '''%(MODULE_NAME,MODULE_NAME,MODULE_NAME)
0645
0646
0647
0648
0649
0650
0651 def __is_help__():
0652 ishelp = False
0653 for arg in sys.argv:
0654 if "-h" in arg.lower() and arg[0]=="-": ishelp = True
0655 if "help" in arg.lower(): ishelp = True
0656 if ishelp: print (HELP_MESSAGE)
0657
0658
0659 def __print_error__(text):
0660 print (text)
0661
0662
0663 def __print__(text):
0664 print (text)
0665
0666
0667 def __print_progress_bar__(text,percentage):
0668 sys.stdout.write("\r%s %5.1f%%"%(text,percentage))
0669 sys.stdout.flush()
0670 if percentage==100.: print()
0671
0672
0673 def __print_and_terminate__(text):
0674 __print_error__(text + " ==> terminating the program!")
0675 __print__(ERROR_CONTACT)
0676 raise SystemExit
0677
0678
0679 def __str_to_float__(text):
0680 try:
0681 return ast.literal_eval(text)
0682 except Exception as e:
0683 __print_and_terminate__("String to float conversion failed due to: "+str(e))
0684
0685 def __float_to_str__(val):
0686 return '{}'.format(val)
0687
0688 def __get_three_values__(line, delimiter):
0689 vals = line.split(delimiter)[-1]
0690 vals = vals.split()
0691 if len(vals)!=3:
0692
0693
0694
0695 __print_and_terminate__("Input format inconsistency: more than 3 values per line: "+line)
0696 return [__str_to_float__(val) for val in vals]
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708 def __vectr_subtr__(vector1, vector2):
0709 return [x[0]-x[1] for x in zip(vector1,vector2)]
0710
0711 def __vector_cross__(vector1, vector2):
0712 return [
0713 vector1[1]*vector2[2] - vector1[2]*vector2[1],
0714 - vector1[0]*vector2[2] + vector1[2]*vector2[0],
0715 vector1[0]*vector2[1] - vector1[1]*vector2[0],
0716 ]
0717
0718 def __vector_inner__(vector1,vector2):
0719 return sum([x[0]*x[1] for x in zip(vector1,vector2)])
0720
0721 def __get_orientation__(norm, v1, v2, v3):
0722 vec1 = __vectr_subtr__(v2, v1)
0723 vec2 = __vectr_subtr__(v3, v2)
0724 norm1 = __vector_cross__(vec1,vec2)
0725 return 1 if __vector_inner__(norm,norm1)>0 else -1
0726
0727 def __get_inputname_base__(fname):
0728 return fname.split("/")[-1].split(".stl")[0]
0729
0730
0731 def get_triangles(fname):
0732 f=open(fname,"r")
0733 solid = None
0734
0735 lines = f.readlines()
0736 nlines = len(lines)
0737 for l in xrange(nlines):
0738 __print_progress_bar__("Processing file %s: "%fname,100.*(l+1)/nlines)
0739 line = lines[l].lower()
0740
0741
0742
0743 if "facet " in line:
0744 solid = {}
0745
0746
0747 if "normal" in line:
0748 if "normal" in solid.keys():
0749 __print_and_terminate__("Input format inconsistency: duplicate normal for triangle")
0750 solid["normal"] = __get_three_values__(line, "normal")
0751 continue
0752
0753
0754
0755 if "vertex" in line:
0756 if "vertex" not in solid:
0757 solid["vertex"] = []
0758 if len(solid["vertex"])>=3:
0759 __print_and_terminate__("Input format inconsistency: more than 3 vertices per triangle")
0760 solid["vertex"].append(__get_three_values__(line,"vertex"))
0761 continue
0762
0763
0764
0765 if "endfacet" in line:
0766 yield solid
0767
0768
0769 def guess_material(fname):
0770 target = fname.lower()
0771 materials = [m["name"] for m in MATERIALS_LIST if m["name"].lower() in target]
0772 if len(materials)>1:
0773 __print__(" Ambigous materials for file: %s:"%fname)
0774 [__print__(" %s"%x) for x in materials]
0775 __print__(" ... please specify name properly - assigning Vacuum to this volume!")
0776 return MATERIALS_LIST[0]["name"]
0777 elif not materials:
0778 __print__(" Could not parse material for the file %s: - asigning Vacuum to this volume!"%fname)
0779 return MATERIALS_LIST[0]["name"]
0780
0781 __print__(" File %s - material parsed: %s"%(fname,materials[0]))
0782 return materials[0]
0783
0784 def stl_to_gdml(fname):
0785 outname = __get_inputname_base__(fname)
0786 outsolidname = outname+"-SOL"
0787
0788
0789 triangles = []
0790 sortedvertexes = []
0791 for triangle in get_triangles(fname):
0792 triangles.append(triangle)
0793 for vertex in triangle["vertex"]:
0794 x = __float_to_str__(vertex[0] + X_OFFSET)
0795 y = __float_to_str__(vertex[1] + Y_OFFSET)
0796 z = __float_to_str__(vertex[2] + Z_OFFSET)
0797 thekey = x+y+z
0798 sortedvertexes.append(thekey)
0799
0800
0801 sortedvertexes = sorted(sortedvertexes)
0802
0803
0804
0805 previous = None
0806 sortednoduplicates = []
0807 vertexidnoduplicates = []
0808 for tmpvertex in sortedvertexes:
0809 if tmpvertex == previous: continue
0810 sortednoduplicates.append(tmpvertex)
0811 vertexidnoduplicates.append(None)
0812 previous = tmpvertex
0813
0814
0815
0816 vertices = '\n <define>\n'
0817 solids = '\n <solids>\n'
0818 solids += ' <tessellated aunit="%s" lunit="%s" name="%s">\n'%(AUNIT,LUNIT,outsolidname)
0819 vertexid = 0
0820 for i in xrange(len(triangles)):
0821 triangle = triangles[i]
0822 __print_progress_bar__("generating gdml for %s: "%fname,100.*(i+1)/len(triangles))
0823 if len(triangle["vertex"])!=3:
0824 __print_and_terminate__("Illegal number of vertices per triangle: "+str(triangle["vertex"]))
0825 ids = []
0826 for vertex in triangle["vertex"]:
0827 x = __float_to_str__(vertex[0] + X_OFFSET)
0828 y = __float_to_str__(vertex[1] + Y_OFFSET)
0829 z = __float_to_str__(vertex[2] + Z_OFFSET)
0830 thekey = x+y+z
0831 theitem = bisect(sortednoduplicates, thekey)-1
0832 assert(theitem>=0)
0833
0834 if vertexidnoduplicates[theitem] is None:
0835 vertices+=' <position name="%s_v%d" unit="%s" x="%s" y="%s" z="%s"/>\n'% (outname,
0836 vertexid,
0837 LUNIT,
0838 x,
0839 y,
0840 z
0841 )
0842 vertexidnoduplicates[theitem] = vertexid
0843 vertexid+=1
0844
0845 ids.append(vertexidnoduplicates[theitem])
0846
0847
0848 orientation = __get_orientation__(triangle["normal"], *triangle["vertex"])
0849 idsforsolid = ids if orientation>0 else [ids[2],ids[1],ids[0]]
0850 solids+= ' <triangular vertex1="%s_v%d" vertex2="%s_v%d" vertex3="%s_v%d"/>\n'%(outname, idsforsolid[0],
0851 outname, idsforsolid[1],
0852 outname, idsforsolid[2]
0853 )
0854
0855
0856
0857
0858
0859 vertices+= ' </define>\n'
0860 solids+= ' </tessellated>\n'
0861 solids+= ' </solids>\n'
0862
0863
0864 material = guess_material(fname)
0865
0866
0867
0868 structure = STRUCTURE%(outname, material, outsolidname,"")
0869
0870
0871 world = WORLD%outname
0872
0873
0874
0875
0876
0877
0878 outfilename = fname[:-4] + ".gdml"
0879 fout = open(outfilename,"w")
0880 fout.write(HEADER)
0881 fout.write(SCHEMA)
0882
0883 fout.write(vertices)
0884 fout.write(solids)
0885 fout.write(structure)
0886 fout.write(world)
0887 fout.write(FOOTER)
0888 fout.close()
0889 return outfilename
0890
0891
0892 def creat_gdml_bundle(outname, infiles):
0893
0894 WORLD_BOX_SIZE = __float_to_str__(10000.)
0895 SOLIDNMAE = "world_solid"
0896 VOLUMENAME = "world_volume"
0897
0898
0899 solid = '\n <solids>\n'
0900 solid += ' <box lunit="%s" name="%s" x="%s" y="%s" z="%s" />\n'%(LUNIT,SOLIDNMAE,WORLD_BOX_SIZE,WORLD_BOX_SIZE,WORLD_BOX_SIZE)
0901 solid += ' </solids>\n'
0902
0903
0904 includes = "\n\n"
0905 for fname in infiles:
0906 gdmlname = stl_to_gdml(fname)
0907 includes += ' <physvol>\n'
0908 includes += ' <file name="%s"/>\n'%gdmlname
0909
0910
0911 includes += ' </physvol>\n'
0912
0913 includes += "\n"
0914 structure = STRUCTURE%(VOLUMENAME,"Vacuum", SOLIDNMAE,includes)
0915
0916
0917 world = WORLD%VOLUMENAME
0918
0919
0920
0921 outname = outname+".gdml"
0922 fout = open(outname,"w")
0923 fout.write(HEADER)
0924 fout.write(SCHEMA)
0925 fout.write(MATERIALS)
0926 fout.write(solid)
0927 fout.write(structure)
0928 fout.write(world)
0929 fout.write(FOOTER)
0930 fout.close()
0931
0932
0933
0934
0935
0936
0937
0938 def main():
0939 global X_OFFSET, Y_OFFSET, Z_OFFSET
0940 parser = argparse.ArgumentParser(description="Convert STL files to GDML", epilog=HELP_MESSAGE, formatter_class=argparse.RawDescriptionHelpFormatter)
0941 parser.add_argument("--x-offset", type=float, default=X_OFFSET, help="X offset in mm (default: %(default)s)")
0942 parser.add_argument("--y-offset", type=float, default=Y_OFFSET, help="Y offset in mm (default: %(default)s)")
0943 parser.add_argument("--z-offset", type=float, default=Z_OFFSET, help="Z offset in mm (default: %(default)s)")
0944 parser.add_argument("--materials", action="store_true", help="Show available materials")
0945 parser.add_argument("out_name", nargs="?", help="Output GDML bundle name")
0946 parser.add_argument("infiles", nargs="*", help="Input STL files")
0947 args = parser.parse_args()
0948 if args.materials:
0949 __print__(MATERIALS_INFO)
0950 return
0951 if not args.out_name or not args.infiles:
0952 parser.error("an output name and at least one input STL file are required")
0953 X_OFFSET, Y_OFFSET, Z_OFFSET = args.x_offset, args.y_offset, args.z_offset
0954 matchnames = [item for item in args.infiles if args.out_name.lower().split('.gdml')[0] == item.lower().split('.stl')[0]]
0955 if matchnames:
0956 parser.error("output name must not coincide with an input STL file name: " + matchnames[0])
0957 if ".stl" in args.out_name:
0958 parser.error("please provide an output GDML file name, not an STL file name")
0959 creat_gdml_bundle(args.out_name.split('.gdml')[0], args.infiles)
0960
0961
0962 if __name__ == "__main__":
0963 main()