Back to home page

EIC code displayed by LXR

 
 

    


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 #import numpy as np
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         #print 
0693         #print delimiter
0694         #print vals
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 #def __get_orientation__(norm, vertex1, vertex2, vertex3):
0700 #   v1 = np.array(vertex1)
0701 #   v2 = np.array(vertex2)
0702 #   v3 = np.array(vertex3)
0703 #   vec1 = v2 - v1
0704 #   vec2 = v3 - v2
0705 #   norm1 = np.cross(vec1,vec2)
0706 #   return 1 if np.inner(norm,norm1)>0 else -1
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         # start facet 
0743         if "facet " in line:
0744             solid = {}
0745 
0746         # Get normal to triangle
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         # Get vertices
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         # Finalize the triangle
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     # sort vertices
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     #__print__("Soring vertices - may take some time...")
0801     sortedvertexes = sorted(sortedvertexes)
0802     #__print__("... done sorting")
0803 
0804     # remove duplicates from verticves
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     # create gdml vertices
0815     # create gdml solids
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             # add vertex to gdml
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             #  add vertex to facet
0845             ids.append(vertexidnoduplicates[theitem])
0846 
0847         # create facet
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     # finalize 
0859     vertices+= '    </define>\n'
0860     solids+=   '        </tessellated>\n'
0861     solids+=   '    </solids>\n'
0862 
0863     # material
0864     material = guess_material(fname) # "Vacuum"
0865 
0866 
0867     # structure
0868     structure = STRUCTURE%(outname, material, outsolidname,"")
0869 
0870     # world
0871     world = WORLD%outname
0872     
0873 
0874     
0875     # create output gdml file
0876     # I performed some modifications here so that the output file is produced
0877     # at the same directory except with a .gdml extension
0878     outfilename = fname[:-4] + ".gdml"
0879     fout = open(outfilename,"w")
0880     fout.write(HEADER)
0881     fout.write(SCHEMA)
0882     #fout.write(MATERIALS)
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     # some world constants
0894     WORLD_BOX_SIZE = __float_to_str__(10000.)
0895     SOLIDNMAE  = "world_solid"
0896     VOLUMENAME = "world_volume"
0897 
0898     # solids
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     # structure 
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         #includes += '                <position name="stk_corner_bolts_pos" x="stk_adjust_x_position" y="stk_adjust_y_position" z="stk_adjust_z_position" unit="mm"/>'
0910         #includes += '                <rotationref ref="old_to_new_coordinatesystem_rotation" />'
0911         includes += '             </physvol>\n'
0912 
0913     includes += "\n"
0914     structure = STRUCTURE%(VOLUMENAME,"Vacuum", SOLIDNMAE,includes)
0915 
0916     # world
0917     world = WORLD%VOLUMENAME
0918 
0919 
0920     # create top level gdml file
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 #__is_help__()
0935 #stl_to_gdml(sys.argv[1])
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()