File indexing completed on 2026-04-09 07:48:48
0001
0002 """
0003 ggeo.py
0004 =========
0005
0006 See also GNodeLib.py
0007
0008 TODO:
0009
0010 * connection between solids and PV names
0011
0012
0013
0014
0015
0016
0017 Dumping using single node index and triplet RPO (ridx/pidx/oidx repeat/placement/offset) indexing::
0018
0019 ggeo.py 0 # world volume
0020 ggeo.py 1/0/0 # first placement of outer volume of first repeat
0021 ggeo.py 1/ # missing elements of the triplet default to 0
0022
0023 ggeo.py 2/0/0 # first placement of outer volume of second repeat ridx/pidx/oidx
0024
0025 When using the triplet form of node specification wildcards are
0026 accepted in the first ridx slot (eg 5:9) and third oidx slot (eg *),
0027 for example dumping all all volumes in ridx 5,6,7,8 with::
0028
0029 epsilon:issues blyth$ ggeo.py 5:9/0/* --brief
0030 nidx: 69668 triplet: 5000000 sh:5f0014 sidx: 0 nrpo( 69668 5 0 0 ) shape( 95 20 base_steel0x360d8f0 Water///Steel)
0031 nidx: 69078 triplet: 6000000 sh:5e0014 sidx: 0 nrpo( 69078 6 0 0 ) shape( 94 20 uni10x34cdcb0 Water///Steel)
0032 nidx: 68488 triplet: 7000000 sh:5d0014 sidx: 0 nrpo( 68488 7 0 0 ) shape( 93 20 sStrutBallhead0x352a360 Water///Steel)
0033 nidx: 70258 triplet: 8000000 sh:600010 sidx: 0 nrpo( 70258 8 0 0 ) shape( 96 16 uni_acrylic30x35ff3d0 Water///Acrylic)
0034
0035
0036 The --names option dumps PV and LV names, for example dumping PV, LV names of the first instance placement
0037 of all volumes in ridx 1 thru 4::
0038
0039 epsilon:GItemList blyth$ ggeo.py 1:5/ --names
0040 nrpo( 176632 1 0 0 ) PMT_3inch_log_phys0x4437d00 PMT_3inch_log0x4436df0 114 PMT_3inch_pmt_solid0x4436210
0041 nrpo( 176633 1 0 1 ) PMT_3inch_body_phys0x4437230 PMT_3inch_body_log0x4436ce0 112 PMT_3inch_body_solid_ell_ell_helper0x44364d0
0042 nrpo( 176634 1 0 2 ) PMT_3inch_inner1_phys0x44372b0 PMT_3inch_inner1_log0x4436f00 110 PMT_3inch_inner1_solid_ell_helper0x4436560
0043 nrpo( 176635 1 0 3 ) PMT_3inch_inner2_phys0x4437360 PMT_3inch_inner2_log0x4437010 111 PMT_3inch_inner2_solid_ell_helper0x4436640
0044 nrpo( 176636 1 0 4 ) PMT_3inch_cntr_phys0x4437410 PMT_3inch_cntr_log0x4437120 113 PMT_3inch_cntr_solid0x44366d0
0045 nrpo( 70960 2 0 0 ) pLPMT_NNVT_MCPPMT0x3cbba60 NNVTMCPPMTlMaskVirtual0x3cb41a0 103 NNVTMCPPMTsMask_virtual0x3cb3b40
0046 nrpo( 70961 2 0 1 ) NNVTMCPPMTpMask0x3c9fe00 NNVTMCPPMTlMask0x3c9fc80 98 NNVTMCPPMTsMask0x3c9fa80
0047 nrpo( 70962 2 0 2 ) NNVTMCPPMT_PMT_20inch_log_phys0x3c9fe80 NNVTMCPPMT_PMT_20inch_log0x3caec40 102 NNVTMCPPMT_PMT_20inch_pmt_solid0x3ca9320
0048 nrpo( 70963 2 0 3 ) NNVTMCPPMT_PMT_20inch_body_phys0x3caefa0 NNVTMCPPMT_PMT_20inch_body_log0x3caeb60 101 NNVTMCPPMT_PMT_20inch_body_solid0x3cad240
0049 nrpo( 70964 2 0 4 ) NNVTMCPPMT_PMT_20inch_inner1_phys0x3caf030 NNVTMCPPMT_PMT_20inch_inner1_log0x3caed60 99 NNVTMCPPMT_PMT_20inch_inner1_solid_1_Ellipsoid0x3503950
0050 nrpo( 70965 2 0 5 ) NNVTMCPPMT_PMT_20inch_inner2_phys0x3caf0f0 NNVTMCPPMT_PMT_20inch_inner2_log0x3caee80 100 NNVTMCPPMT_PMT_20inch_inner2_solid0x3cae8f0
0051 nrpo( 70966 3 0 0 ) pLPMT_Hamamatsu_R128600x3cbbae0 HamamatsuR12860lMaskVirtual0x3c9a5c0 109 HamamatsuR12860sMask_virtual0x3c99fb0
0052 nrpo( 70967 3 0 1 ) HamamatsuR12860pMask0x3c9b320 HamamatsuR12860lMask0x3c9b1a0 104 HamamatsuR12860sMask0x3c9afa0
0053 nrpo( 70968 3 0 2 ) HamamatsuR12860_PMT_20inch_log_phys0x3c9b3b0 HamamatsuR12860_PMT_20inch_log0x3c93920 108 HamamatsuR12860_PMT_20inch_pmt_solid_1_90x3cb68e0
0054 nrpo( 70969 3 0 3 ) HamamatsuR12860_PMT_20inch_body_phys0x345b3c0 HamamatsuR12860_PMT_20inch_body_log0x3c93830 107 HamamatsuR12860_PMT_20inch_body_solid_1_90x3ca7680
0055 nrpo( 70970 3 0 4 ) HamamatsuR12860_PMT_20inch_inner1_phys0x3c94040 HamamatsuR12860_PMT_20inch_inner1_log0x345b160 105 HamamatsuR12860_PMT_20inch_inner1_solid_I0x3c96fa0
0056 nrpo( 70971 3 0 5 ) HamamatsuR12860_PMT_20inch_inner2_phys0x3c94100 HamamatsuR12860_PMT_20inch_inner2_log0x345b290 106 HamamatsuR12860_PMT_20inch_inner2_solid_1_90x3c93610
0057 nrpo( 304636 4 0 0 ) mask_PMT_20inch_vetolMaskVirtual_phys0x4433460 mask_PMT_20inch_vetolMaskVirtual0x3ca10e0 126 mask_PMT_20inch_vetosMask_virtual0x3ca0a80
0058 nrpo( 304637 4 0 1 ) mask_PMT_20inch_vetopMask0x3ca1e40 mask_PMT_20inch_vetolMask0x3ca1cb0 121 mask_PMT_20inch_vetosMask0x3ca1aa0
0059 nrpo( 304638 4 0 2 ) PMT_20inch_veto_log_phys0x3ca5fa0 PMT_20inch_veto_log0x3ca5470 125 PMT_20inch_veto_pmt_solid_1_20x3ca38b0
0060 nrpo( 304639 4 0 3 ) PMT_20inch_veto_body_phys0x3ca57a0 PMT_20inch_veto_body_log0x3ca5360 124 PMT_20inch_veto_body_solid_1_20x3ca4230
0061 nrpo( 304640 4 0 4 ) PMT_20inch_veto_inner1_phys0x3ca5820 PMT_20inch_veto_inner1_log0x3ca5580 122 PMT_20inch_veto_inner1_solid0x3ca4f10
0062 nrpo( 304641 4 0 5 ) PMT_20inch_veto_inner2_phys0x3ca58d0 PMT_20inch_veto_inner2_log0x3ca5690 123 PMT_20inch_veto_inner2_solid0x3ca5130
0063
0064 Same for ridx 5 thru 8::
0065
0066 epsilon:GItemList blyth$ ggeo.py 5:9/ --names
0067 nrpo( 69668 5 0 0 ) lUpper_phys0x35b5ac0 lUpper0x35b5a00 95 base_steel0x360d8f0
0068 nrpo( 69078 6 0 0 ) lFasteners_phys0x34ce040 lFasteners0x34cdf00 94 uni10x34cdcb0
0069 nrpo( 68488 7 0 0 ) lSteel_phys0x352c890 lSteel0x352c760 93 sStrutBallhead0x352a360
0070 nrpo( 70258 8 0 0 ) lAddition_phys0x35ff770 lAddition0x35ff5f0 96 uni_acrylic30x35ff3d0
0071
0072 Names for first two placements of ridx 5 thru 8::
0073
0074 epsilon:GItemList blyth$ ggeo.py 5:9/0:2 --names
0075 nrpo( 69668 5 0 0 ) lUpper_phys0x35b5ac0 lUpper0x35b5a00 95 base_steel0x360d8f0
0076 nrpo( 69669 5 1 0 ) lUpper_phys0x35b5bb0 lUpper0x35b5a00 95 base_steel0x360d8f0
0077 nrpo( 69078 6 0 0 ) lFasteners_phys0x34ce040 lFasteners0x34cdf00 94 uni10x34cdcb0
0078 nrpo( 69079 6 1 0 ) lFasteners_phys0x34ce140 lFasteners0x34cdf00 94 uni10x34cdcb0
0079 nrpo( 68488 7 0 0 ) lSteel_phys0x352c890 lSteel0x352c760 93 sStrutBallhead0x352a360
0080 nrpo( 68489 7 1 0 ) lSteel_phys0x352a4a0 lSteel0x352c760 93 sStrutBallhead0x352a360
0081 nrpo( 70258 8 0 0 ) lAddition_phys0x35ff770 lAddition0x35ff5f0 96 uni_acrylic30x35ff3d0
0082 nrpo( 70259 8 1 0 ) lAddition_phys0x35ff870 lAddition0x35ff5f0 96 uni_acrylic30x35ff3d0
0083
0084
0085 Using suppression of some prolific names can dump all interesting names at once::
0086
0087 epsilon:ana blyth$ ggeo.sh 0:10/ --names --suppress
0088 python3 /Users/blyth/opticks/ana/ggeo.py 0:10/ --names --suppress
0089 [2021-04-24 13:57:42,444] p41483 {/Users/blyth/opticks/ana/ggeo.py:777} INFO - using suppression (HBeam|ixture|anchor|Steel2|Plane|Wall|Receiver|Strut0x|sBar0x) specificed by envvar OPTICKS_GGEO_SUPPRESS
0090 nrpo( 0 0 0 0 ) lWorld0x33e33d0_PV lWorld0x33e33d0 130 sWorld0x33e3370
0091 nrpo( 1 0 0 1 ) pTopRock0x33f3c00 lTopRock0x33f3b30 12 sTopRock0x33f3aa0
0092 nrpo( 2 0 0 2 ) pExpHall0x33f40b0 lExpHall0x33f3fb0 11 sExpHall0x33f3f20
0093 nrpo( 3 0 0 3 ) lUpperChimney_phys0x4e6e210 lUpperChimney0x4e6c7a0 3 Upper_Chimney0x4e6c340
0094 nrpo( 4 0 0 4 ) pUpperChimneyLS0x4e6cbc0 lUpperChimneyLS0x4e6c8a0 0 Upper_LS_tube0x4e6c450
0095 nrpo( 5 0 0 5 ) pUpperChimneySteel0x4e6cc90 lUpperChimneySteel0x4e6c9b0 1 Upper_Steel_tube0x4e6c570
0096 nrpo( 6 0 0 6 ) pUpperChimneyTyvek0x4e6cd60 lUpperChimneyTyvek0x4e6cac0 2 Upper_Tyvek_tube0x4e6c690
0097 nrpo( 7 0 0 7 ) pTopTracker0x4e7f260 lAirTT0x4e713c0 10 sAirTT0x4e71260
0098 nrpo( 65717 0 0 197 ) pBtmRock0x33f9200 lBtmRock0x33f89c0 129 sBottomRock0x33f4390
0099 nrpo( 65718 0 0 198 ) pPoolLining0x33f9160 lPoolLining0x33f90a0 128 sPoolLining0x33f8a80
0100 nrpo( 65719 0 0 199 ) pOuterWaterPool0x3490fa0 lOuterWaterPool0x33f9470 127 sOuterWaterPool0x33f9360
0101 nrpo( 67840 0 0 2320 ) pCentralDetector0x3492d70 lReflectorInCD0x34916c0 120 sReflectorInCD0x3491470
0102 nrpo( 67841 0 0 2321 ) pInnerWater0x3492b80 lInnerWater0x3491d30 119 sInnerWater0x3491ae0
0103 nrpo( 67842 0 0 2322 ) pAcrylic0x3492c20 lAcrylic0x34923a0 90 sAcrylic0x3492150
0104 nrpo( 67843 0 0 2323 ) pTarget0x3492cc0 lTarget0x3492a10 89 sTarget0x34927c0
0105 nrpo( 304632 0 0 3080 ) lLowerChimney_phys0x4e706b0 lLowerChimney0x4e6eac0 118 sWaterTube0x4e6e9b0
0106 nrpo( 304633 0 0 3081 ) pLowerChimneyAcrylic0x4e6f220 lLowerChimneyAcrylic0x4e6ece0 115 sChimneyAcrylic0x4e6ebc0
0107 nrpo( 304634 0 0 3082 ) pLowerChimneyLS0x4e6f2e0 lLowerChimneyLS0x4e6eef0 116 sChimneyLS0x4e6ede0
0108 nrpo( 304635 0 0 3083 ) pLowerChimneySteel0x4e6f3b0 lLowerChimneySteel0x4e6f110 117 sChimneySteel0x4e6eff0
0109 nrpo( 176632 1 0 0 ) PMT_3inch_log_phys0x43c2530 PMT_3inch_log0x43c1620 114 PMT_3inch_pmt_solid0x43c0a40
0110 nrpo( 176633 1 0 1 ) PMT_3inch_body_phys0x43c1a60 PMT_3inch_body_log0x43c1510 112 PMT_3inch_body_solid_ell_ell_helper0x43c0d00
0111 nrpo( 176634 1 0 2 ) PMT_3inch_inner1_phys0x43c1ae0 PMT_3inch_inner1_log0x43c1730 110 PMT_3inch_inner1_solid_ell_helper0x43c0d90
0112 nrpo( 176635 1 0 3 ) PMT_3inch_inner2_phys0x43c1b90 PMT_3inch_inner2_log0x43c1840 111 PMT_3inch_inner2_solid_ell_helper0x43c0e70
0113 nrpo( 176636 1 0 4 ) PMT_3inch_cntr_phys0x43c1c40 PMT_3inch_cntr_log0x43c1950 113 PMT_3inch_cntr_solid0x43c0f00
0114 nrpo( 70961 2 0 1 ) NNVTMCPPMTpMask0x3c2cad0 NNVTMCPPMTlMask0x3c2c950 98 NNVTMCPPMTsMask0x3c2c750
0115 nrpo( 70962 2 0 2 ) NNVTMCPPMT_PMT_20inch_log_phys0x3c2cb50 NNVTMCPPMT_PMT_20inch_log0x3c2a6b0 102 NNVTMCPPMT_PMT_20inch_pmt_solid0x3c21980
0116 nrpo( 70963 2 0 3 ) NNVTMCPPMT_PMT_20inch_body_phys0x3c2aa10 NNVTMCPPMT_PMT_20inch_body_log0x3c2a5d0 101 NNVTMCPPMT_PMT_20inch_body_solid0x3c258a0
0117 nrpo( 70964 2 0 4 ) NNVTMCPPMT_PMT_20inch_inner1_phys0x3c2aaa0 NNVTMCPPMT_PMT_20inch_inner1_log0x3c2a7d0 99 NNVTMCPPMT_PMT_20inch_inner1_solid_1_Ellipsoid0x3497520
0118 nrpo( 70965 2 0 5 ) NNVTMCPPMT_PMT_20inch_inner2_phys0x3c2ab60 NNVTMCPPMT_PMT_20inch_inner2_log0x3c2a8f0 100 NNVTMCPPMT_PMT_20inch_inner2_solid0x3c2a360
0119 nrpo( 70967 3 0 1 ) HamamatsuR12860pMask0x3c394b0 HamamatsuR12860lMask0x3c39330 104 HamamatsuR12860sMask0x3c39130
0120 nrpo( 70968 3 0 2 ) HamamatsuR12860_PMT_20inch_log_phys0x3c39540 HamamatsuR12860_PMT_20inch_log0x3c36c90 108 HamamatsuR12860_PMT_20inch_pmt_solid_1_90x3c4a970
0121 nrpo( 70969 3 0 3 ) HamamatsuR12860_PMT_20inch_body_phys0x33eeec0 HamamatsuR12860_PMT_20inch_body_log0x3c36ba0 107 HamamatsuR12860_PMT_20inch_body_solid_1_90x3c28080
0122 nrpo( 70970 3 0 4 ) HamamatsuR12860_PMT_20inch_inner1_phys0x3c373b0 HamamatsuR12860_PMT_20inch_inner1_log0x33eec60 105 HamamatsuR12860_PMT_20inch_inner1_solid_I0x3c32bc0
0123 nrpo( 70971 3 0 5 ) HamamatsuR12860_PMT_20inch_inner2_phys0x3c37470 HamamatsuR12860_PMT_20inch_inner2_log0x33eed90 106 HamamatsuR12860_PMT_20inch_inner2_solid_1_90x3c36980
0124 nrpo( 304637 4 0 1 ) mask_PMT_20inch_vetopMask0x3c2eb60 mask_PMT_20inch_vetolMask0x3c2e9d0 121 mask_PMT_20inch_vetosMask0x3c2e7c0
0125 nrpo( 304638 4 0 2 ) PMT_20inch_veto_log_phys0x3c3e950 PMT_20inch_veto_log0x3c3de20 125 PMT_20inch_veto_pmt_solid_1_20x3c305d0
0126 nrpo( 304639 4 0 3 ) PMT_20inch_veto_body_phys0x3c3e150 PMT_20inch_veto_body_log0x3c3dd10 124 PMT_20inch_veto_body_solid_1_20x3c3cc50
0127 nrpo( 304640 4 0 4 ) PMT_20inch_veto_inner1_phys0x3c3e1d0 PMT_20inch_veto_inner1_log0x3c3df30 122 PMT_20inch_veto_inner1_solid0x3c3d8c0
0128 nrpo( 304641 4 0 5 ) PMT_20inch_veto_inner2_phys0x3c3e280 PMT_20inch_veto_inner2_log0x3c3e040 123 PMT_20inch_veto_inner2_solid0x3c3dae0
0129 nrpo( 68488 5 0 0 ) lSteel_phys0x34c07b0 lSteel0x34c0680 93 sStrutBallhead0x34be280
0130 nrpo( 69078 6 0 0 ) lFasteners_phys0x3461f60 lFasteners0x3461e20 94 uni10x3461bd0
0131 nrpo( 69668 7 0 0 ) lUpper_phys0x35499e0 lUpper0x3549920 95 base_steel0x35a1810
0132 nrpo( 70258 8 0 0 ) lAddition_phys0x3593690 lAddition0x3593510 96 uni_acrylic30x35932f0
0133 nrpo( 10 9 0 0 ) pPanel_0_f_0x4e7c3c0 lPanel0x4e71970 7 sPanel0x4e71750
0134 nrpo( 11 9 0 1 ) pPanelTape0x4e7c6a0 lPanelTape0x4e71b00 6 sPanelTape0x4e71a70
0135 [2021-04-24 13:57:42,496] p41483 {/Users/blyth/opticks/ana/ggeo.py:601} INFO - supressed 3193 volumes
0136 epsilon:ana blyth$
0137
0138
0139
0140
0141
0142
0143 A convenient visualization workflow is to use the above python triple indexing to find PV names to target, eg::
0144
0145 OTracerTest --targetpvn lFasteners_phys ## do not include the 0x reference in the targetted name, as it will differ between machines/invokations
0146 OTracerTest --target 69078 ## using raw indices is NOT advisable as they go stale very quickly with changed geometry
0147
0148 Volume idsmry dumping::
0149
0150 epsilon:ana blyth$ ggeo.py 3199 -i
0151 iden( 3199 5000000 2f001b -1 ) nrpo( 3199 5 0 0 ) shape( 47 27 pmt-hemi0xc0fed900x3e85f00 MineralOil///Pyrex)
0152 iden( 3200 5000001 2e001c -1 ) nrpo( 3200 5 0 1 ) shape( 46 28 pmt-hemi-vac0xc21e2480x3e85290 Pyrex///Vacuum)
0153 iden( 3201 5000002 2b001d -1 ) nrpo( 3201 5 0 2 ) shape( 43 29 pmt-hemi-cathode0xc2f1ce80x3e842d0 Vacuum///Bialkali)
0154 iden( 3202 5000003 2c001e -1 ) nrpo( 3202 5 0 3 ) shape( 44 30 pmt-hemi-bot0xc22a9580x3e844c0 Vacuum///OpaqueVacuum)
0155 iden( 3203 5000004 2d001e -1 ) nrpo( 3203 5 0 4 ) shape( 45 30 pmt-hemi-dynode0xc346c500x3e84610 Vacuum///OpaqueVacuum)
0156 iden( 3204 57f 30001f -1 ) nrpo( 3204 0 0 1407 ) shape( 48 31 AdPmtCollar0xc2c52600x3e86030 MineralOil///UnstStainlessSteel)
0157 iden( 3205 5000100 2f001b -1 ) nrpo( 3205 5 1 0 ) shape( 47 27 pmt-hemi0xc0fed900x3e85f00 MineralOil///Pyrex)
0158 iden( 3206 5000101 2e001c -1 ) nrpo( 3206 5 1 1 ) shape( 46 28 pmt-hemi-vac0xc21e2480x3e85290 Pyrex///Vacuum)
0159 iden( 3207 5000102 2b001d -1 ) nrpo( 3207 5 1 2 ) shape( 43 29 pmt-hemi-cathode0xc2f1ce80x3e842d0 Vacuum///Bialkali)
0160
0161
0162 ::
0163
0164 In [52]: gc(10)
0165 gc.identity[10] nidx/midx/bidx/sidx [530 8 3 1]
0166 gc.mlibnames[10] : sPlane0x47c46c0
0167 gc.blibnames[10] : Air///Air
0168
0169 gt : gc.transforms0[530]
0170 [[ 0. 1. 0. 0. ]
0171 [ -1. 0. 0. 0. ]
0172 [ 0. 0. 1. 0. ]
0173 [20133.6 -6711.2 23504.15 1. ]]
0174
0175 tr : transform
0176 [[ 0. 1. 0. 0. ]
0177 [ -1. 0. 0. 0. ]
0178 [ 0. 0. 1. 0. ]
0179 [20133.6 -6711.2 23504.15 1. ]]
0180
0181 it : inverted transform
0182 [[ 0. -1. 0. 0. ]
0183 [ 1. 0. 0. 0. ]
0184 [ -0. 0. 1. 0. ]
0185 [ 6711.2 20133.6 -23504.15 1. ]]
0186
0187 bb : bbox4
0188 [[ 16748.4492 -10141.8008 23497.5 1. ]
0189 [ 23518.75 -3280.6001 23510.8008 1. ]]
0190
0191 cbb : (bb[0]+bb[1])/2.
0192 [20133.5996 -6711.2004 23504.1504 1. ]
0193
0194 c4 : center4
0195 [20133.5996 -6711.2002 23504.1504 1. ]
0196
0197 ce : center_extent
0198 [20133.6 -6711.2 23504.15 3430.6003]
0199
0200 ic4 : np.dot( c4, it) : inverse transform applied to center4
0201 [0. 0. 0. 1.]
0202
0203 ibb : np.dot( bb, it) : inverse transform applied to bbox4
0204 [[-3430.6006 3385.1504 -6.6504 1. ]
0205 [ 3430.6001 -3385.1504 6.6504 1. ]]
0206
0207
0208 """
0209 from __future__ import print_function
0210 import os, re, sys, logging, argparse
0211 log = logging.getLogger(__name__)
0212 import numpy as np
0213 from opticks.ana.blib import BLib
0214 from opticks.ana.key import key_
0215 from opticks.ana.OpticksIdentity import OpticksIdentity
0216 from opticks.ana.rsttable import RSTTable
0217
0218 tx_load = lambda _:list(map(str.strip, open(_).readlines()))
0219
0220 def Three2Four(a, w=1):
0221 """
0222 :param a: array shaped with last dimension 3
0223 :param w: 1 or 0 (points or vectors)
0224 :return r: corresponding array which last dimension increased from 3 to 4
0225 """
0226 s = list(a.shape)
0227 assert s[-1] == 3, "unexpected shape %r , last dimension must be 3" % s
0228 assert w in (1,0), "w must be 1 or 0"
0229 s[-1] = 4
0230 b = np.ones(s) if w == 1 else np.zeros(s)
0231 d = len(s)
0232 if d == 1:
0233 b[:3] = a
0234 if d == 2:
0235 b[:,:3] = a
0236 elif d == 3:
0237 b[:,:,:3] = a
0238 elif d == 4:
0239 b[:,:,:,:3] = a
0240 else:
0241 assert 0, "unexpected shape %r " % s
0242 pass
0243 r = b
0244 return r
0245
0246
0247
0248 class GGeo(object):
0249 KEY = key_(os.environ["OPTICKS_KEY"])
0250 KEYDIR = KEY.keydir
0251 VERSION = KEY.version
0252 DIGEST = KEY.digest
0253 SUPPRESS_ = os.environ.get("OPTICKS_GGEO_SUPPRESS", "")
0254 SUPPRESS_PTN = "("+SUPPRESS_.replace(",","|")+")"
0255 SUPPRESS = None if SUPPRESS_PTN == "()" else re.compile(SUPPRESS_PTN)
0256
0257
0258 @classmethod
0259 def Suppress(cls, name):
0260 """
0261 :param name:
0262 :return bool: True when the name contains one of the suppressed strings provided by envvar OPTICKS_GGEO_SUPPRESS
0263 """
0264 if cls.SUPPRESS is None:
0265 return False
0266 else:
0267 return not cls.SUPPRESS.search(name) is None
0268 pass
0269
0270 volume_names = list(map(lambda _:"volume_%s" % _, "transforms center_extent bbox meshes nodeinfo identity".split()))
0271 placement_names = list(map(lambda _:"placement_%s"%_, "itransforms iidentity".split()))
0272 face_names = list(map(lambda _:"face_%s"%_, "sensors boundaries nodes indices".split()))
0273 vertex_names = list(map(lambda _:"vertex_%s"%_, "colors normals vertices".split()))
0274 names = volume_names + placement_names + face_names + vertex_names
0275
0276 all_volume_names = list(map(lambda _:"all_volume_%s" % _, "nodeinfo identity center_extent bbox transforms inverse_transforms".split()))
0277
0278 PV = "{keydir}/GNodeLib/all_volume_PVNames.txt"
0279 LV = "{keydir}/GNodeLib/all_volume_LVNames.txt"
0280 MS = "{keydir}/GItemList/GMeshLib.txt"
0281
0282 @classmethod
0283 def Path(cls, ridx, name, subdir="GMergedMesh", alldir="GNodeLib"):
0284 """
0285 :param ridx: -1 for all volumes from GNodeLib, 0,1,2,3,... for GMergedMesh Composite "Solids"
0286 """
0287 keydir = cls.KEYDIR
0288 if ridx == -1:
0289 fmt = "{keydir}/{alldir}/{name}.npy"
0290 elif ridx > -1:
0291 fmt = "{keydir}/{subdir}/{ridx}/{name}.npy"
0292 else:
0293 assert 0
0294 pass
0295 return os.path.expandvars(fmt.format(**locals()))
0296
0297 @classmethod
0298 def TxtPath(cls, name):
0299 keydir = cls.KEYDIR
0300 return os.path.expandvars("{keydir}/{name}".format(**locals()))
0301
0302 @classmethod
0303 def Array(cls, ridx, name):
0304 path = cls.Path(ridx, name)
0305 a = np.load(path)
0306 return a
0307
0308 @classmethod
0309 def Txt(cls, name):
0310 path = cls.TxtPath(name)
0311 return np.array(tx_load(path))
0312
0313
0314 @classmethod
0315 def Attn(cls, ridx, name):
0316 return "_%s_%d" % (name, ridx)
0317
0318 def __init__(self, args=None):
0319 self.args = args
0320 self.suppress_count = 0
0321 keydir = self.KEYDIR
0322 path = os.path.expandvars("{keydir}/GMergedMesh".format(**locals()))
0323 mmidx = sorted(map(int,os.listdir(path)))
0324 num_repeats = len(mmidx)
0325 self.num_repeats = num_repeats
0326 blib = BLib(keydir)
0327 self.blib = np.array(blib.names().split("\n"))
0328 self.pv = np.loadtxt(self.PV.format(**locals()), dtype="|S100")
0329 self.lv = np.loadtxt(self.LV.format(**locals()), dtype="|S100")
0330 self.ms = np.loadtxt(self.MS.format(**locals()), dtype="|S100")
0331 self.msn = list(map(lambda _:_.decode('utf-8'),self.ms))
0332
0333 self.mlib = self.get_txt("GItemList/GMeshLib.txt", "_mlib")
0334 self.midx = (self.all_volume_identity[:,2] >> 16) & 0xffff
0335 self.bidx = (self.all_volume_identity[:,2] >> 0) & 0xffff
0336 self.mlibnames = self.mlib[self.midx]
0337 self.blibnames = self.blib[self.bidx]
0338 self.mmidx = mmidx
0339
0340
0341
0342
0343
0344
0345
0346 def get_array(self, ridx, name):
0347 """
0348 Array actually loaded only the first time
0349 """
0350 attn = self.Attn(ridx,name)
0351 if getattr(self, attn, None) is None:
0352 a = self.Array(ridx, name)
0353 setattr(self, attn, a)
0354 pass
0355 return getattr(self, attn)
0356
0357 def get_txt(self, name, attn):
0358 if getattr(self, attn, None) is None:
0359 a = self.Txt(name)
0360 setattr(self, attn, a)
0361 pass
0362 return getattr(self, attn)
0363
0364 def summary0(self):
0365 log.info("num_repeats:{gg.num_repeats}".format(gg=self))
0366 for ridx in range(self.num_repeats):
0367 for name in self.names:
0368 a = self.get_array(ridx,name)
0369 print("{ridx:2d} {name:25s} {shape!r}".format(ridx=ridx,name=name,shape=a.shape))
0370 pass
0371 print()
0372 pass
0373
0374 def get_tot_volumes(self):
0375 return self.get_num_volumes(-1)
0376 num_volumes = property(get_tot_volumes)
0377
0378 def get_num_volumes(self, ridx):
0379 name = "all_volume_transforms" if ridx == -1 else "volume_transforms"
0380 a = self.get_array(ridx,name)
0381 return a.shape[0]
0382
0383 def get_num_placements(self, ridx):
0384 if ridx == -1:
0385 return 1
0386 pass
0387 name = "placement_itransforms"
0388 a = self.get_array(ridx,name)
0389 return a.shape[0]
0390
0391 def summary(self):
0392 """
0393 Array shapes
0394 """
0395 log.info("num_repeats:{gg.num_repeats}".format(gg=self))
0396
0397 fmt = "{ridx:10d} {num_volumes:15d} {num_placements:15d} {num_placed_vol:15d}"
0398 print("%10s %15s %15s %15s" % ("ridx","num_volumes", "num_placements", "num_placed_vol"))
0399 tot_vol = 0
0400 tot_vol_ = self.get_num_volumes(-1)
0401 for ridx in range(self.num_repeats):
0402 num_volumes = self.get_num_volumes(ridx)
0403 num_placements = self.get_num_placements(ridx)
0404 num_placed_vol = num_volumes*num_placements
0405 tot_vol += num_placed_vol
0406 print(fmt.format(**locals()))
0407 pass
0408 print("%10s %15s %15s %15d" % ("","","tot_vol:",tot_vol))
0409 print("%10s %15s %15s %15d" % ("","","tot_vol_:",tot_vol_))
0410 print()
0411
0412 for name in self.names:
0413 shape = []
0414 for ridx in range(self.num_repeats):
0415 a = self.get_array(ridx,name)
0416 shape.append("{shape!r:20s}".format(shape=a.shape))
0417 pass
0418 print("{name:25s} {shape}".format(name=name,shape="".join(shape)))
0419 pass
0420 for name in self.all_volume_names:
0421 ridx = -1
0422 a = self.get_array(ridx,name)
0423 print("{name:25s} {shape!r}".format(name=name,shape=a.shape))
0424 pass
0425
0426 def get_all_transforms(self):
0427 """
0428 Access transforms of all volumes via triplet indexing.
0429 The ordering of the transforms is not the same as all_volume_transforms.
0430 However can still check the match using the identity info to find
0431 the node index.
0432 """
0433 log.info("get_all_transforms and do identity consistency check : triplet->node->triplet")
0434 tot_volumes = self.get_tot_volumes()
0435 tr = np.zeros([tot_volumes,4,4],dtype=np.float32)
0436 count = 0
0437 for ridx in range(self.num_repeats):
0438 num_placements = self.get_num_placements(ridx)
0439 num_volumes = self.get_num_volumes(ridx)
0440 for pidx in range(num_placements):
0441 for oidx in range(num_volumes):
0442 nidx = self.get_node_index(ridx,pidx,oidx)
0443 tr[nidx] = self.get_transform(ridx,pidx,oidx)
0444 count += 1
0445 pass
0446 pass
0447 pass
0448 assert tot_volumes == count
0449 all_volume_transforms = self.get_array(-1,"all_volume_transforms")
0450 assert np.allclose( all_volume_transforms, tr )
0451 return tr
0452
0453
0454 def get_transform_n(self, nidx):
0455 all_volume_transforms = self.get_array(-1,"all_volume_transforms")
0456 return all_volume_transforms[nidx]
0457
0458 def get_inverse_transform_n(self, nidx):
0459 all_volume_inverse_transforms = self.get_array(-1,"all_volume_inverse_transforms")
0460 return all_volume_inverse_transforms[nidx]
0461
0462
0463 def get_inverse_transform(self, ridx, pidx, oidx):
0464 """
0465 No triplet way to do this yet, have to go via node index
0466 """
0467 nidx = self.get_node_index(ridx,pidx,oidx)
0468 return self.get_inverse_transform_n(nidx)
0469
0470 def get_transform(self, ridx, pidx, oidx):
0471 """
0472 :param ridx: repeat idx, 0 for remainder
0473 :param pidx: placement index of the instance, 0 for remainder
0474 :param oidx: offset index, within the instance or among the remainder
0475
0476 DONE in get_all_transforms, verified both routes match for all nodes including the remainders
0477 """
0478
0479 placement_itransforms = self.get_array(ridx, "placement_itransforms")
0480 volume_transforms = self.get_array(ridx, "volume_transforms")
0481 itr = placement_itransforms[pidx]
0482 vtr = volume_transforms[oidx].reshape(4,4)
0483
0484 ggt = np.dot( vtr, itr )
0485
0486
0487 nidx = self.get_node_index(ridx,pidx,oidx)
0488
0489
0490 ntr = self.get_transform_n(nidx)
0491
0492 assert np.allclose( ggt, ntr )
0493 return ggt
0494
0495 def get_node_index(self, ridx, pidx, oidx):
0496 """
0497 :param ridx: repeat index, 0 for remainder
0498 :param pidx: placement index of the instance, 0 for remainder
0499 :param oidx: offset index, within the instance or among the remainder
0500 :return nidx: all_volume node index
0501
0502 The node index obtained from the placement_identity is used
0503 to do a reverse conversion check using nrpo, looking up
0504 the triplet identity from the node index. These indices
0505 are consistency checked with the inputs.
0506 """
0507 placement_iidentity = self.get_array(ridx, "placement_iidentity")
0508 iid = placement_iidentity[pidx, oidx]
0509 nidx = iid[0]
0510
0511 nidx2,ridx2,pidx2,oidx2 = self.nrpo[nidx]
0512 assert nidx2 == nidx
0513 assert ridx2 == ridx
0514 assert pidx2 == pidx
0515
0516 if oidx2 != oidx:
0517 log.debug("mismatch oidx2:%d(from nrpo/iid) oidx:%d(from range(num_volumes)) " % (oidx2, oidx))
0518 pass
0519
0520 return nidx
0521
0522
0523 def get_lvidx(self, ridx, pidx, oidx):
0524 nidx = self.get_node_index(ridx,pidx,oidx)
0525 midx = self.midx[nidx]
0526 return midx
0527
0528 def get_soname(self, ridx, pidx, oidx, trim=False):
0529 """
0530 :param ridx: repeat index
0531 :param pidx: placement index
0532 :param oidx: offset index within the repeated piece of geometry
0533 :param trim: when True trims any 0xdeadbeef pointer suffix
0534 """
0535 midx = self.get_lvidx(ridx, pidx, oidx)
0536 msn = self.msn[midx]
0537 return msn.split("0x")[0] if trim else msn
0538
0539 def make_nrpo(self):
0540 """
0541 See okc/OpticksIdentity::Decode
0542 """
0543 gg = self
0544 avi = gg.all_volume_identity
0545 tid = avi[:,1]
0546 nrpo = OpticksIdentity.NRPO(tid)
0547 return nrpo
0548
0549 def _get_nrpo(self):
0550 if getattr(self,'_nrpo',None) is None:
0551 setattr(self,'_nrpo',self.make_nrpo())
0552 return self._nrpo
0553 nrpo = property(_get_nrpo)
0554
0555 def get_triplet_index(self, nidx):
0556 """
0557 cf ggeo/GGeo::getIdentity
0558
0559 :param nidx: all_volume node index
0560 :return nidx,ridx,pidx,oidx:
0561 """
0562 return self.nrpo[nidx]
0563
0564
0565 all_volume_center_extent = property(lambda self:self.get_array(-1,"all_volume_center_extent"))
0566 all_volume_bbox = property(lambda self:self.get_array(-1,"all_volume_bbox"))
0567 all_volume_identity = property(lambda self:self.get_array(-1,"all_volume_identity"))
0568 all_volume_transforms = property(lambda self:self.get_array(-1,"all_volume_transforms"))
0569
0570
0571 volume_transforms0 = property(lambda self:self.get_array(0,"volume_transforms"))
0572 volume_transforms1 = property(lambda self:self.get_array(1,"volume_transforms"))
0573 volume_transforms2 = property(lambda self:self.get_array(2,"volume_transforms"))
0574 volume_transforms3 = property(lambda self:self.get_array(3,"volume_transforms"))
0575 volume_transforms4 = property(lambda self:self.get_array(4,"volume_transforms"))
0576 volume_transforms5 = property(lambda self:self.get_array(5,"volume_transforms"))
0577
0578 placement_itransforms0 = property(lambda self:self.get_array(0,"placement_itransforms"))
0579 placement_itransforms1 = property(lambda self:self.get_array(1,"placement_itransforms"))
0580 placement_itransforms2 = property(lambda self:self.get_array(2,"placement_itransforms"))
0581 placement_itransforms3 = property(lambda self:self.get_array(3,"placement_itransforms"))
0582 placement_itransforms4 = property(lambda self:self.get_array(4,"placement_itransforms"))
0583 placement_itransforms5 = property(lambda self:self.get_array(5,"placement_itransforms"))
0584
0585 placement_iidentity0 = property(lambda self:self.get_array(0,"placement_iidentity"))
0586 placement_iidentity1 = property(lambda self:self.get_array(1,"placement_iidentity"))
0587 placement_iidentity2 = property(lambda self:self.get_array(2,"placement_iidentity"))
0588 placement_iidentity3 = property(lambda self:self.get_array(3,"placement_iidentity"))
0589 placement_iidentity4 = property(lambda self:self.get_array(4,"placement_iidentity"))
0590 placement_iidentity5 = property(lambda self:self.get_array(5,"placement_iidentity"))
0591
0592
0593 def __call__(self,*args):
0594 """
0595 A single integer argument is interpreted as a node index (nidx),
0596 otherwise 2 or 3 args are interpreted as ridx,pidx,oidx with
0597 oidx defaulting to zero if not provided.::
0598
0599 gg(0,0,1000) # triplet addressing to remainder volumes, NB all are ridx:0 pidx:0
0600 gg(2792) # same volume via node indexing
0601
0602 gg(5,0,2) # first placement of cathode volume (DYB)
0603 gg(3201) # same volume via node indexing
0604
0605 gg(5,671,2) # last placement of cathode volume (DYB)
0606 gg(11410) # same volume via node indexing
0607
0608 """
0609 log.debug("args %s len(args) %d " % (str(args), len(args)))
0610
0611 nidxs = []
0612
0613 if len(args) == 1:
0614 nidx = args[0]
0615 nidxs.append(nidx)
0616 elif len(args) == 2 or len(args) == 3:
0617 if len(args) == 2:
0618 a_ridx,a_pidx = args
0619 a_oidx = "*"
0620 elif len(args) == 3:
0621 a_ridx,a_pidx,a_oidx = args
0622 else:
0623 assert 0
0624 pass
0625 log.debug("a_ridx %s a_pidx %s a_oidx %s" % (a_ridx,a_pidx,a_oidx))
0626
0627 if type(a_ridx) is int:
0628 ridxs = [a_ridx]
0629 elif ":" in a_ridx:
0630 ridxs = range(*map(int,a_ridx.split(":")))
0631 else:
0632 assert 0, a_ridx
0633 pass
0634
0635 log.debug("ridxs %s " % str(ridxs))
0636
0637 if type(a_pidx) is int:
0638 pidxs = [a_pidx]
0639 elif ":" in a_pidx:
0640 pidxs = range(*map(int,a_pidx.split(":")))
0641 else:
0642 assert 0, a_pidx
0643 pass
0644
0645
0646 for ridx in ridxs:
0647 if a_oidx == "*":
0648 num_volumes = self.get_num_volumes(ridx)
0649 oidxs = range(num_volumes)
0650 else:
0651 oidxs = [a_oidx]
0652 pass
0653 for pidx in pidxs:
0654 for oidx in oidxs:
0655 nidx = self.get_node_index(ridx,pidx,oidx)
0656 nidxs.append(nidx)
0657 pass
0658 pass
0659 pass
0660 else:
0661 assert 0, "expecting argument of 1/2/3 integers"
0662 pass
0663
0664 for nidx in nidxs:
0665 if self.args.nidx:
0666 print(nidx)
0667 elif self.args.brief:
0668 self.brief(nidx)
0669 elif self.args.names:
0670 self.names(nidx)
0671 elif self.args.sonames:
0672 self.sonames(nidx)
0673 elif self.args.soidx:
0674 self.soidx(nidx)
0675 else:
0676 self.dump_node(nidx)
0677 pass
0678 pass
0679
0680 if self.suppress_count > 0:
0681 log.info("supressed %d volumes " % self.suppress_count )
0682 pass
0683
0684
0685 def idsmry(self, nidx):
0686 """
0687 volume identity summary
0688 """
0689 iden = self.all_volume_identity[nidx]
0690 nidx2,triplet,shape,_ = iden
0691 assert nidx == nidx2
0692 sidx = iden[-1].view(np.int32)
0693 iden_s = "nidx:{nidx:6d} triplet:{triplet:8x} sh:{sh:6x} sidx:{sidx:5d} ".format(nidx=nidx,triplet=triplet,sh=shape,sidx=sidx)
0694
0695 nrpo = self.nrpo[nidx]
0696 nrpo_s = "nrpo( %6d %5d %5d %5d )" % tuple(nrpo)
0697
0698 midx = self.midx[nidx]
0699 bidx = self.bidx[nidx]
0700 shape_s = "shape( %3d %3d %40s %40s)" % (midx,bidx, self.mlibnames[nidx], self.blibnames[nidx] )
0701 print( "%s %s %s " % (iden_s, nrpo_s, shape_s) )
0702
0703
0704 def names(self, nidx):
0705 pv = self.pv[nidx].decode('utf-8')
0706
0707 lv = self.lv[nidx].decode('utf-8')
0708 midx = self.midx[nidx]
0709 nrpo = self.nrpo[nidx]
0710 msn = self.msn[midx]
0711
0712 would_suppress = self.Suppress(pv) or self.Suppress(lv) or self.Suppress(msn)
0713 suppress = self.args.suppress and would_suppress
0714 sup = "S" if would_suppress else " "
0715 if suppress:
0716 self.suppress_count += 1
0717 else:
0718 nrpo_s = "nrpo( %6d %5d %5d %5d )" % tuple(nrpo)
0719 print( "%1s %s %50s %50s %3d %s " % (sup, nrpo_s, pv, lv, midx, msn) )
0720 pass
0721
0722 def sonames(self, nidx):
0723 midx = self.midx[nidx]
0724 msn = self.msn[midx]
0725 if args.terse:
0726 print(msn)
0727 elif args.errout:
0728 print(midx,file=sys.stdout)
0729 print(msn, file=sys.stderr)
0730 else:
0731 print( "%3d %s " % (midx, msn) )
0732 pass
0733
0734 def soidx(self, nidx):
0735 midx = self.midx[nidx]
0736 msn = self.msn[midx]
0737 if args.terse:
0738 print(midx)
0739 elif args.errout:
0740 print(midx,file=sys.stdout)
0741 print(msn, file=sys.stderr)
0742 else:
0743 print( "%3d %s " % (midx, msn) )
0744 pass
0745
0746
0747 def bbsmry(self, nidx):
0748 gg = self
0749 bb = gg.all_volume_bbox[nidx]
0750 ce = gg.all_volume_center_extent[nidx]
0751 print(" {nidx:5d} {ce!s:20s} ".format(nidx=nidx,bb=bb,ce=ce))
0752
0753 def brief(self,nidx):
0754 gg = self
0755 gg.idsmry(nidx)
0756
0757 def dump_node(self,nidx):
0758 gg = self
0759 gg.idsmry(nidx)
0760
0761
0762
0763
0764 bb = gg.all_volume_bbox[nidx]
0765 ce = gg.all_volume_center_extent[nidx]
0766 c4 = ce.copy()
0767 c4[3] = 1.
0768
0769 tr = gg.all_volume_transforms[nidx]
0770 it = np.linalg.inv(tr)
0771 ibb = np.dot( bb, it )
0772 cbb = (bb[0]+bb[1])/2.
0773 assert np.allclose( c4, cbb )
0774
0775 ic4 = np.dot( c4, it )
0776 gt = gg.all_volume_transforms[nidx]
0777
0778 print("\ngt : gg.all_volume_transforms[%d]" % nidx)
0779 print(gt)
0780 print("\ntr : transform")
0781 print(tr)
0782 print("\nit : inverted transform")
0783 print(it)
0784 print("\nbb : bbox4")
0785 print(bb)
0786 print("\ncbb : (bb[0]+bb[1])/2.")
0787 print(cbb)
0788 print("\nc4 : center4")
0789 print(c4)
0790 print("\nce : center_extent")
0791 print(ce)
0792 print("\nic4 : np.dot( c4, it) : inverse transform applied to center4 : expect close to origin ")
0793 print(ic4)
0794 print("\nibb : np.dot( bb, it) : inverse transform applied to bbox4 : expect symmetric around origin")
0795 print(ibb)
0796
0797 def consistency_check(self):
0798 gg = self
0799 log.info("consistency_check")
0800 gg.summary()
0801
0802 tr = gg.get_all_transforms()
0803
0804
0805
0806 def parse_args(doc, **kwa):
0807 np.set_printoptions(suppress=True, precision=3, linewidth=200)
0808 parser = argparse.ArgumentParser(doc)
0809 parser.add_argument( "idx", nargs="*", help="Node index or triplet index of form \"1/0/0\" or \"1/\" to dump.")
0810 parser.add_argument( "--nidx", default=False, action="store_true", help="Dump only the node index, useful when the input is triplet index." )
0811 parser.add_argument( "--level", default="info", help="logging level" )
0812 parser.add_argument( "-c","--check", action="store_true", help="Consistency check" )
0813 parser.add_argument( "-i","--idsmry", action="store_true", help="Slice identity summary interpreting idx as slice range." )
0814 parser.add_argument( "-b","--bbsmry", action="store_true", help="Slice bbox summary interpreting idx as slice range." )
0815 parser.add_argument( "--brief", action="store_true", help="Brief summary of nodes selected by idx." )
0816 parser.add_argument( "--names", action="store_true", help="Identity and PV/LV/SO names of nodes selected by idx." )
0817 parser.add_argument( "--mm", action="store_true", help="MM Names" )
0818 parser.add_argument( "--mmtrim", action="store_true", help="MM Names with 0x addr trimmed" )
0819 parser.add_argument( "--mmtrimpath", default="$TMP/mm.txt", help="path to mmtrim names, used by CSGOptix/cxr_table.sh " )
0820 parser.add_argument( "--mmsmry", action="store_true", help="MM Names" )
0821 parser.add_argument( "--sonames", action="store_true", help="Dump solid names for the nodes selected by idx." )
0822 parser.add_argument( "--soidx", action="store_true", help="Dump solid_idx (aka: lvidx or meshidx/midx) for the nodes selected by node or triplet idx." )
0823 parser.add_argument( "--suppress", action="store_true", help="Suppress dumping/listing volumes with names including a list of suppressed strings provided by envvar OPTICKS_GGEO_SUPPRESS")
0824 parser.add_argument( "-t","--terse", action="store_true", help="Terse output" )
0825 parser.add_argument( "-s","--errout", action="store_true", help="Split output writing to both stderr and stdout" )
0826 args = parser.parse_args()
0827 fmt = '[%(asctime)s] p%(process)s {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s'
0828 logging.basicConfig(level=getattr(logging,args.level.upper()), format=fmt)
0829 if len(args.idx) == 0:
0830 args.idx = [0]
0831 pass
0832 return args
0833
0834
0835 def misc(gg):
0836 bbox = gg.all_volume_bbox
0837 print("gg.all_volume_bbox\n",bbox)
0838 t000 = gg.get_transform(0,0,0)
0839 print("t000\n",t000)
0840
0841 def triplet_(rpo):
0842 elem = []
0843 for s in rpo.split("/"):
0844 if s == "*" or ":" in s:
0845 elem.append(s)
0846 else:
0847 if s.isdigit():
0848 elem.append(int(s))
0849 else:
0850 elem.append(0)
0851 pass
0852 pass
0853 pass
0854 return elem
0855
0856
0857 if __name__ == '__main__':
0858 args = parse_args(__doc__)
0859
0860 log.info("[ GGeo")
0861 gg = GGeo(args)
0862 log.info("] GGeo")
0863
0864 if args.suppress:
0865 log.info("using suppression %s specificed by envvar OPTICKS_GGEO_SUPPRESS " % gg.SUPPRESS_PTN )
0866 else:
0867 log.info("suppression %s specificed by envvar OPTICKS_GGEO_SUPPRESS can be enabled with --suppression option " % gg.SUPPRESS_PTN )
0868 pass
0869
0870 if args.check:
0871 gg.consistency_check()
0872
0873 elif args.mmsmry:
0874
0875 labels = ["ridx","plc","vol", "component name", "note (%s)" % gg.DIGEST[:8] ]
0876 hfmt = ["%4s", "%6s", "%5s", "%-40s", "%-25s" ]
0877 rfmt = ["%4d", "%6d", "%5d", "%-40s", "%-25s" ]
0878 wids = [4, 6, 5, 40 , 25 ]
0879 pre = ["", "", "", " ", " " ]
0880 post = ["", "", "", " ", " " ]
0881
0882 mm_notes = {}
0883 mm_notes[0] = "non-repeated remainder"
0884 mm_notes[9] = "repeated parts of TT"
0885
0886 t = np.empty( [len(gg.mmidx), len(labels)], dtype=np.object )
0887
0888 for i, ridx in enumerate(gg.mmidx):
0889 pidx = 0
0890 oidx = 0
0891 num_vol = gg.get_num_volumes(ridx)
0892 num_plc = gg.get_num_placements(ridx)
0893 msn = gg.get_soname(ridx, pidx, oidx, trim=args.mmtrim)
0894 mm_name = "%d:%s" % (num_vol, msn)
0895 mm_note = mm_notes.get(i, "")
0896 row = tuple([ridx, num_plc, num_vol, mm_name, mm_note])
0897 line = " ".join(rfmt) % row
0898 print(line)
0899 t[i] = row
0900 pass
0901 rst = RSTTable.Render(t, labels, wids, hfmt, rfmt, pre, post )
0902 print(rst)
0903 pass
0904
0905 elif args.mm or args.mmtrim:
0906 mm_names = []
0907 for ridx in gg.mmidx:
0908 pidx = 0
0909 oidx = 0
0910 num_vol = gg.get_num_volumes(ridx)
0911 msn = gg.get_soname(ridx, pidx, oidx, trim=args.mmtrim)
0912 mm_name = "%d:%s" % (num_vol, msn)
0913 mm_names.append(mm_name)
0914 pass
0915 txt = "\n".join(mm_names)
0916 print(txt)
0917 mmtrimpath = os.path.expandvars(args.mmtrimpath)
0918 log.info("writing this list to mmtrimpath %s " % mmtrimpath )
0919 open(mmtrimpath, "w").write(txt)
0920
0921 elif args.idsmry or args.bbsmry:
0922
0923 beg = int(args.idx[0])
0924 end = int(args.idx[1]) if len(args.idx) > 1 else min(gg.num_volumes,int(args.idx[0])+50)
0925 for idx in list(range(beg, end)):
0926 if args.idsmry:
0927 gg.idsmry(idx)
0928 elif args.bbsmry:
0929 gg.bbsmry(idx)
0930 else:
0931 pass
0932 pass
0933 pass
0934 else:
0935 for idx in args.idx:
0936 if str(idx).isdigit():
0937 gg(int(idx))
0938 else:
0939 gg(*triplet_(idx))
0940 pass
0941 pass
0942 pass
0943
0944