Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:49:36

0001 #pragma once
0002 
0003 /**
0004 sframe.h : NEW CODE SHOULD NOT USE sframe.h : INSTEAD USE sfr.h
0005 ==================================================================
0006 
0007 TODO: see if this can be replaced with sfr.h ?
0008 
0009 TODO: once bring in U4Tree.h/stree.h translation up this to double precision
0010 
0011 
0012 Provided by CSGFoundry::getFrame methods
0013 
0014 * for MOI lookups CSGTarget::getFrameComponents sets the transforms
0015 
0016 
0017 
0018 Persisted into (4,4,4) array.
0019 Any extension should be in quad4 blocks
0020 for persisting, alignment and numpy convenience
0021 
0022 Note that some variables like *frs* are
0023 persisted in metadata, not in the array.
0024 
0025 Currently *frs* is usually the same as *moi* from MOI envvar
0026 but are using *frs* to indicate intension for generalization
0027 to frame specification using global instance index rather than MOI
0028 which uses the gas specific instance index.
0029 
0030 TODO: should be using Tran<double> for transforming , might as well
0031       do the lot in double : double4,dquad,dqat4
0032 
0033 
0034 **/
0035 
0036 #include <cassert>
0037 #include <vector>
0038 #include <cstring>
0039 #include <string>
0040 #include <cstdlib>
0041 
0042 #include "scuda.h"
0043 #include "squad.h"
0044 
0045 #ifdef WITH_SCUDA_DOUBLE
0046 #include "squad_double.h"
0047 #include "scuda_double.h"
0048 #endif
0049 
0050 #include "sqat4.h"
0051 #include "stran.h"
0052 #include "spath.h"
0053 #include "sphoton.h"
0054 
0055 #include "sfr.h"
0056 
0057 #include "NP.hh"
0058 
0059 
0060 struct sframe
0061 {
0062     static constexpr const bool VERBOSE = false ;
0063     static constexpr const char* NAME = "sframe" ;  // formerly with .npy, now splitting ext for easier stem changes
0064     static constexpr const char* DEFAULT_FRS = "-1" ;
0065     static constexpr const char* DEFAULT_NAME = "ALL" ;
0066 
0067     static constexpr const unsigned NUM_4x4 = 4 ;
0068     static constexpr const unsigned NUM_VALUES = NUM_4x4*4*4 ;
0069     static constexpr const float EPSILON = 1e-5 ;
0070 
0071     float4 ce = {} ;   // f4:center-extent           4x4:0
0072     quad   q1 = {} ;   // i4:cegs
0073     quad   q2 = {} ;   // i4:cegs.., f4:gridscale
0074     quad   q3 = {} ;   // i4:midx,mord,gord,inst
0075 
0076     qat4   m2w = {} ;  // f4:inst transform          4x4:1
0077     qat4   w2m = {} ;  // f4:iinst transform         4x4:2
0078 
0079     quad4  aux = {} ;  // i4:ins,gas,sen_id,sen_idx  4x4:3
0080 
0081 
0082     // CAUTION : ABOVE HEAD PERSISTED BY MEMCPY INTO ARRAY,  BELOW TAIL ADDED AS METADATA
0083 
0084     // on the edge, the above are memcpy in/out by load/save
0085     const char* frs = nullptr ;
0086     Tran<double>* tr_m2w = nullptr ;
0087     Tran<double>* tr_w2m = nullptr ;
0088     // TODO: Tran is already (t,v,i) triplet : so can have just the one Tran
0089 
0090     const char* ek = nullptr ;
0091     const char* ev = nullptr ;
0092     const char* ekvid = nullptr ;
0093     const char* tree = nullptr ;  // tree digest
0094     const char* dynamic = nullptr ;  // dynamic digest
0095 
0096     sframe();
0097     sframe(const sframe& other);
0098     ~sframe();
0099     void cleanup();
0100 
0101     sfr spawn_lite() const ;
0102     void populate( const sfr& l );
0103 
0104     void zero() ;
0105     bool is_zero() const ;
0106 
0107     std::string desc() const ;
0108 
0109     static sframe Load( const char* dir, const char* name=NAME);
0110     static sframe Load_(const char* path );
0111     static sframe Fabricate(float tx=0.f, float ty=0.f, float tz=0.f);
0112     static int PopulateFromRaw(sframe& fr, const char* raw, char delim);
0113 
0114     // DO NOT ADD METHODS TO THIS : INSTEAD USE sfr.h
0115 
0116     void set_grid(const std::vector<int>& cegs, float gridscale);
0117     int ix0() const ;
0118     int ix1() const ;
0119     int iy0() const ;
0120     int iy1() const ;
0121     int iz0() const ;
0122     int iz1() const ;
0123     int num_photon() const ;
0124     float gridscale() const ;
0125 
0126     void set_tree(    const char* _tree );
0127     void set_dynamic( const char* _dynamic );
0128 
0129     void set_ekv( const char* k ) ;
0130     void set_ekv( const char* k, const char* v ) ;
0131     const char* form_ekvid() const ;
0132     const char* getFrameId() const ;
0133 
0134     const char* get_frs() const ; // returns nullptr when frs is default
0135     bool is_frs_default() const ;
0136 
0137     const char* get_name() const ; // returns nullptr when frs is default
0138 
0139     void set_midx_mord_gord(int midx, int mord, int gord);
0140     int midx() const ;
0141     int mord() const ;
0142     int gord() const ;
0143 
0144 
0145 
0146 
0147     void set_inst(int inst);
0148     int inst() const ;
0149 
0150     void set_identity(int ins, int gas, int sensor_identifier, int sensor_index );  // formerly set_ins_gas_ias
0151     int ins() const ;
0152     int gas() const ;
0153     int sensor_identifier() const ;
0154     int sensor_index() const ;
0155 
0156     void set_propagate_epsilon(float eps);
0157     void set_hostside_simtrace();
0158 
0159     float propagate_epsilon() const ;
0160     bool  is_hostside_simtrace() const ;
0161 
0162 
0163     float* data() ;
0164     const float* cdata() const ;
0165 
0166     void write( float* dst, unsigned num_values ) const ;
0167     NP* getFrameArray() const ;
0168     void save(const char* dir, const char* name=NAME) const ;
0169     void save_extras(const char* dir) ;  // not const as may *prepare*
0170 
0171 
0172     void read( const float* src, unsigned num_values ) ;
0173     void load(const char* dir, const char* name=NAME) ;
0174     void load_(const char* path ) ;
0175     void load(const NP* a) ;
0176 
0177 
0178 
0179     void prepare();   // below are const by asserting that *prepare* has been called
0180 
0181     NP* transform_photon_m2w( const NP* ph, bool normalize=true ) const ; // hit OR photon (hmm could do record too)
0182     NP* transform_photon_w2m( const NP* ph, bool normalize=true ) const ;
0183     NP* transform_photon( const NP* ph, bool normalize, bool inverse  ) const ;
0184 
0185 
0186     void transform_m2w( sphoton& p, bool normalize=true ) const ;
0187     void transform_w2m( sphoton& p, bool normalize=true ) const ;
0188 
0189 
0190     Tran<double>* getTransform() const ;
0191 
0192 
0193     void setTranslate(float x, float y, float z);
0194     void setTransform(const qat4* m2w_ );
0195 
0196     void set_m2w(const glm::tmat4x4<double>& g_m2w);
0197     void set_w2m(const glm::tmat4x4<double>& g_w2m);
0198 
0199 };
0200 
0201 
0202 // ctor
0203 inline sframe::sframe()
0204     :
0205     tr_m2w(nullptr),
0206     tr_w2m(nullptr)
0207 {
0208 #ifdef SFRAME_DEBUG
0209     printf("//sframe::sframe ctor NULL: tr_m2w %p tr_w2m %p \n", tr_m2w, tr_w2m );
0210 #endif
0211 }
0212 
0213 /**
0214 sframe copy ctor
0215 --------------------
0216 
0217 notes/issues/sframe_dtor_double_free_from_CSGOptiX__initFrame.rst
0218 
0219 Note that a simple copy of non-nullptr transform pointers without the "prepare"
0220 would cause double ownership of tr_m2w tr_w2m and subsequent dtor double free errors.
0221 
0222 **/
0223 
0224 // copy ctor
0225 inline sframe::sframe(const sframe& other)
0226 {
0227     ce = other.ce ;
0228     q1 = other.q1 ;
0229     q2 = other.q2 ;
0230     q3 = other.q3 ;
0231     m2w = other.m2w ;
0232     w2m = other.w2m ;
0233     aux = other.aux ;
0234 
0235     frs = other.frs ? strdup(other.frs) : nullptr ;
0236 
0237     tr_m2w = nullptr ;
0238     tr_w2m = nullptr ;
0239     prepare();   // set the above from the m2w, w2m
0240 
0241     ek = other.ek ? strdup(other.ek) : nullptr ;
0242     ev = other.ev ? strdup(other.ev) : nullptr ;
0243     ekvid = other.ekvid ? strdup(other.ekvid) : nullptr ;
0244     tree = other.tree ? strdup(other.tree) : nullptr ;
0245     dynamic = other.dynamic ? strdup(other.dynamic) : nullptr ;
0246 
0247 
0248 #ifdef SFRAME_DEBUG
0249     printf("//sframe.copy.ctor NEW: tr_m2w %p tr_w2m %p \n", tr_m2w, tr_w2m );
0250 #endif
0251 }
0252 
0253 /**
0254 sframe::spawn_lite
0255 -------------------
0256 
0257 transitional
0258 
0259 **/
0260 
0261 inline sfr sframe::spawn_lite() const
0262 {
0263     sfr l ;
0264     l.ce.x = ce.x ;
0265     l.ce.y = ce.y ;
0266     l.ce.z = ce.z ;
0267     l.ce.w = ce.w ;
0268 
0269     l.m2w = tr_m2w->t ;
0270     l.w2m = tr_w2m->t ;
0271 
0272     return l ;
0273 }
0274 
0275 inline void sframe::populate( const sfr& l )
0276 {
0277     set_m2w(l.m2w);
0278     set_w2m(l.w2m);
0279 
0280     ce.x = l.ce.x ;
0281     ce.y = l.ce.y ;
0282     ce.z = l.ce.z ;
0283     ce.w = l.ce.w ;
0284 }
0285 
0286 
0287 
0288 
0289 
0290 /**
0291 sframe::~sframe dtor
0292 ----------------------
0293 
0294 **/
0295 inline sframe::~sframe()
0296 {
0297 #ifdef SFRAME_DEBUG
0298     printf("//sframe::~sframe tr_m2w %p tr_w2m %p \n", tr_m2w, tr_w2m );
0299 #endif
0300     //cleanup();  // JUST LEAKING FOR NOW : SEE PLAN IN notes/issues/sframe_dtor_double_free_from_CSGOptiX__initFrame.rst
0301 }
0302 
0303 inline void sframe::cleanup()
0304 {
0305     free((void*)frs);
0306     delete tr_m2w ;
0307     delete tr_w2m ;
0308     free((void*)ek);
0309     free((void*)ev);
0310     free((void*)ekvid);
0311 }
0312 
0313 
0314 inline void sframe::zero()
0315 {
0316     ce = {} ;   // 0
0317     q1 = {} ;
0318     q2 = {} ;
0319     q3 = {} ;
0320     m2w = {} ;  // 1
0321     w2m = {} ;  // 2
0322     aux = {} ;  // 3
0323 
0324     frs = nullptr ;
0325     tr_m2w = nullptr ;
0326     tr_w2m = nullptr ;
0327     ek = nullptr ;
0328     ev = nullptr ;
0329     ekvid = nullptr ;
0330     tree = nullptr ;
0331     dynamic = nullptr ;
0332 }
0333 
0334 
0335 inline bool sframe::is_zero() const
0336 {
0337     return ce.x == 0. && ce.y == 0. && ce.z == 0. && ce.w == 0. ;
0338 }
0339 
0340 
0341 
0342 
0343 inline std::string sframe::desc() const
0344 {
0345     std::stringstream ss ;
0346     ss << "sframe::desc"
0347        << " inst " << inst()
0348        << " frs " << ( frs ? frs : "-" ) << std::endl
0349        << " tree " << ( tree ? tree : "-" ) << std::endl
0350        << " dynamic " << ( dynamic ? dynamic : "-" ) << std::endl
0351        << " ekvid " << ( ekvid ? ekvid : "-" )
0352        << " ek " << ( ek ? ek : "-" )
0353        << " ev " << ( ev ? ev : "-" )
0354        << std::endl
0355        << " ce  " << ce
0356        << " is_zero " << is_zero()
0357        << std::endl
0358        << " m2w " << m2w
0359        << std::endl
0360        << " w2m " << w2m
0361        << std::endl
0362        << " midx " << std::setw(4) << midx()
0363        << " mord " << std::setw(4) << mord()
0364        << " gord " << std::setw(4) << gord()
0365        << std::endl
0366        << " inst " << std::setw(4) << inst()
0367        << std::endl
0368        << " ix0  " << std::setw(4) << ix0()
0369        << " ix1  " << std::setw(4) << ix1()
0370        << " iy0  " << std::setw(4) << iy0()
0371        << " iy1  " << std::setw(4) << iy1()
0372        << " iz0  " << std::setw(4) << iz0()
0373        << " iz1  " << std::setw(4) << iz1()
0374        << " num_photon " << std::setw(4) << num_photon()
0375        << std::endl
0376        << " ins  " << std::setw(4) << ins()
0377        << " gas  " << std::setw(4) << gas()
0378        << " sensor_identifier  " << std::setw(7) << sensor_identifier()
0379        << " sensor_index  " << std::setw(5) << sensor_index()
0380        << std::endl
0381        << " propagate_epsilon " << std::setw(10) << std::fixed << std::setprecision(5) << propagate_epsilon()
0382        << " is_hostside_simtrace " << ( is_hostside_simtrace() ? "YES" : "NO" )
0383        << std::endl
0384        ;
0385     std::string str = ss.str();
0386     return str ;
0387 }
0388 
0389 
0390 inline sframe sframe::Load(const char* dir, const char* name) // static
0391 {
0392     sframe fr ;
0393     fr.load(dir, name);
0394     return fr ;
0395 }
0396 inline sframe sframe::Load_(const char* path) // static
0397 {
0398     sframe fr ;
0399     fr.load_(path);
0400     return fr ;
0401 }
0402 /**
0403 sframe::Fabricate
0404 --------------------
0405 
0406 Placeholder frame for testing, optionally with translation transform.
0407 
0408 **/
0409 inline sframe sframe::Fabricate(float tx, float ty, float tz) // static
0410 {
0411     sframe fr ;
0412     fr.setTranslate(tx, ty, tz) ;
0413     fr.prepare();
0414     return fr ;
0415 }
0416 
0417 /**
0418 sframe::PopulateFromRaw
0419 -------------------------
0420 
0421 NOTE NEAR DUPLICATION WITH stree::get_frame_from_raw
0422 
0423 **/
0424 
0425 
0426 inline int sframe::PopulateFromRaw(sframe& fr, const char* raw, char delim ) // static
0427 {
0428 
0429     // 1. split *raw* into elem values using delim
0430 
0431     std::vector<double> elem ;
0432     sstr::split<double>( elem, raw, delim );
0433     int num_elem = elem.size();
0434 
0435     std::cout
0436         << "sframe::PopulateFromRaw"
0437         << " raw [" << ( raw ? raw : "-" ) << "]"
0438         << " num_elem " << num_elem
0439         << " elem " << sstr::desc<double>(elem)
0440         << "\n"
0441         ;
0442 
0443     if( num_elem == 4 || num_elem == 3 || num_elem == 2 || num_elem == 1  )
0444     {
0445          float tx = num_elem > 0 ? elem[0] : 0.f ;
0446          float ty = num_elem > 1 ? elem[1] : 0.f ;
0447          float tz = num_elem > 2 ? elem[2] : 0.f ;
0448          float extent = num_elem > 3 ? elem[3] : 1000.f ;
0449 
0450          fr.setTranslate( tx, ty, tz );
0451          fr.ce.w = extent ;   // HMM: maybe not equivalent to sfr.h ?
0452     }
0453     else
0454     {
0455          std::cerr
0456              << "sframe::PopulateFromRaw"
0457              << " UNHANDLED num_elem " << num_elem
0458              << " raw [" << ( raw ? raw : "-" ) << "]"
0459              << "\n" ;
0460          assert(0);
0461          std::raise(SIGINT);
0462     }
0463     fr.prepare();
0464     return 0;
0465 }
0466 
0467 
0468 
0469 
0470 inline void sframe::set_grid(const std::vector<int>& cegs, float gridscale)
0471 {
0472     assert( cegs.size() == 8 );   // use SFrameGenstep::StandardizeCEGS to convert 4/7/8 to 8
0473 
0474     q1.i.x = cegs[0] ;  // ix0   these are after standardization
0475     q1.i.y = cegs[1] ;  // ix1
0476     q1.i.z = cegs[2] ;  // iy0
0477     q1.i.w = cegs[3] ;  // iy1
0478 
0479     q2.i.x = cegs[4] ;  // iz0
0480     q2.i.y = cegs[5] ;  // iz1
0481     q2.i.z = cegs[6] ;  // num_photon
0482     q2.f.w = gridscale ;
0483 
0484     //assert( cegs[7] == 1 ); // expecting 1 for cegs[7] other than fine regions where 2 (or 4) might be used
0485 
0486 }
0487 
0488 inline int sframe::ix0() const { return q1.i.x ; }
0489 inline int sframe::ix1() const { return q1.i.y ; }
0490 inline int sframe::iy0() const { return q1.i.z ; }
0491 inline int sframe::iy1() const { return q1.i.w ; }
0492 inline int sframe::iz0() const { return q2.i.x ; }
0493 inline int sframe::iz1() const { return q2.i.y ; }
0494 inline int sframe::num_photon() const { return q2.i.z ; }
0495 inline float sframe::gridscale() const { return q2.f.w ; }
0496 
0497 
0498 inline void sframe::set_tree( const char* _tree )
0499 {
0500     tree = _tree ? strdup(_tree) :  nullptr ;
0501 }
0502 inline void sframe::set_dynamic( const char* _dynamic )
0503 {
0504     dynamic = _dynamic ? strdup(_dynamic) :  nullptr ;
0505 }
0506 
0507 
0508 
0509 
0510 inline void sframe::set_ekv( const char* k )
0511 {
0512     char* v = getenv(k) ;
0513     set_ekv(k, v);
0514 }
0515 
0516 inline void sframe::set_ekv( const char* k, const char* v )
0517 {
0518     ek = k ? strdup(k) : nullptr ;
0519     ev = v ? strdup(v) : nullptr ;
0520     ekvid = form_ekvid();
0521 }
0522 
0523 inline const char* sframe::form_ekvid() const
0524 {
0525     std::stringstream ss ;
0526     ss << "sframe_"
0527        << ( ek ? ek : "ek" )
0528        << "_"
0529        ;
0530     for(int i=0 ; i < int(ev?strlen(ev):0) ; i++) ss << ( ev[i] == ':' ? '_' : ev[i] ) ;
0531     std::string str = ss.str();
0532     return strdup(str.c_str());
0533 }
0534 inline const char* sframe::getFrameId() const
0535 {
0536     return ekvid ;
0537 }
0538 
0539 
0540 
0541 inline const char* sframe::get_frs() const
0542 {
0543     return is_frs_default() ? nullptr : frs ;
0544 }
0545 inline bool sframe::is_frs_default() const
0546 {
0547     return frs != nullptr && strcmp(frs, DEFAULT_FRS) == 0 ;
0548 }
0549 inline const char* sframe::get_name() const
0550 {
0551     const char* f = get_frs();
0552     return f ? f : DEFAULT_NAME ;
0553 }
0554 
0555 inline void sframe::set_midx_mord_gord(int midx, int mord, int gord)
0556 {
0557     q3.i.x = midx ;
0558     q3.i.y = mord ;
0559     q3.i.z = gord ;
0560 }
0561 inline int sframe::midx() const { return q3.i.x ; }
0562 inline int sframe::mord() const { return q3.i.y ; }
0563 inline int sframe::gord() const { return q3.i.z ; }
0564 inline int sframe::inst() const { return q3.i.w ; }
0565 
0566 inline void sframe::set_inst(int inst){ q3.i.w = inst ; }
0567 
0568 inline void sframe::set_identity(int ins, int gas, int sensor_identifier, int sensor_index ) // formerly set_ins_gas_ias
0569 {
0570     aux.q0.i.x = ins ;
0571     aux.q0.i.y = gas ;
0572     aux.q0.i.z = sensor_identifier ;
0573     aux.q0.i.w = sensor_index  ;
0574 }
0575 inline int sframe::ins() const { return aux.q0.i.x ; }
0576 inline int sframe::gas() const { return aux.q0.i.y ; }
0577 inline int sframe::sensor_identifier() const { return aux.q0.i.z ; }
0578 inline int sframe::sensor_index() const {      return aux.q0.i.w ; }
0579 
0580 
0581 inline void sframe::set_propagate_epsilon(float eps){     aux.q1.f.x = eps ; }
0582 inline void sframe::set_hostside_simtrace(){              aux.q1.u.y = 1u ; }
0583 
0584 inline float sframe::propagate_epsilon() const   { return aux.q1.f.x ; }
0585 inline bool sframe::is_hostside_simtrace() const { return aux.q1.u.y == 1u ; }
0586 
0587 
0588 inline const float* sframe::cdata() const
0589 {
0590     return (const float*)&ce.x ;
0591 }
0592 inline float* sframe::data()
0593 {
0594     return (float*)&ce.x ;
0595 }
0596 inline void sframe::write( float* dst, unsigned num_values ) const
0597 {
0598     assert( num_values == NUM_VALUES );
0599     char* dst_bytes = (char*)dst ;
0600     char* src_bytes = (char*)cdata();
0601     unsigned num_bytes = sizeof(float)*num_values ;
0602     memcpy( dst_bytes, src_bytes, num_bytes );
0603 }
0604 
0605 inline void sframe::read( const float* src, unsigned num_values )
0606 {
0607     assert( num_values == NUM_VALUES );
0608     char* src_bytes = (char*)src ;
0609     char* dst_bytes = (char*)data();
0610     unsigned num_bytes = sizeof(float)*num_values ;
0611     memcpy( dst_bytes, src_bytes, num_bytes );
0612 }
0613 
0614 inline NP* sframe::getFrameArray() const
0615 {
0616     NP* a = NP::Make<float>(NUM_4x4, 4, 4) ;
0617     write( a->values<float>(), NUM_4x4*4*4 ) ;
0618 
0619     a->set_meta<std::string>("creator", "sframe::getFrameArray");
0620     if(frs) a->set_meta<std::string>("frs", frs);
0621     if(tree) a->set_meta<std::string>("tree", tree);
0622     if(dynamic) a->set_meta<std::string>("dynamic", dynamic);
0623     if(ek) a->set_meta<std::string>("ek", ek);
0624     if(ev) a->set_meta<std::string>("ev", ev);
0625     if(ekvid) a->set_meta<std::string>("ekvid", ekvid);
0626 
0627     return a ;
0628 }
0629 inline void sframe::save(const char* dir, const char* name_ ) const
0630 {
0631     if(VERBOSE) std::cout
0632         << "[ sframe::save "
0633         << " dir : " << ( dir ? dir : "MISSING_DIR" )
0634         << " name: " << ( name_ ? name_ : "MISSING_NAME" )
0635         << std::endl
0636         ;
0637 
0638     std::string name = U::form_name( name_ , ".npy" ) ;
0639     NP* a = getFrameArray();
0640 
0641     a->save(dir, name.c_str());
0642 
0643     if(VERBOSE) std::cout
0644        << "] sframe::save "
0645        << std::endl
0646        ;
0647 
0648 }
0649 inline void sframe::save_extras(const char* dir)
0650 {
0651     if(tr_m2w == nullptr) prepare();
0652     tr_m2w->save(dir, "m2w.npy");
0653     tr_w2m->save(dir, "w2m.npy");
0654 }
0655 
0656 
0657 inline void sframe::load(const char* dir, const char* name_ )
0658 {
0659     std::string name = U::form_name( name_ , ".npy" ) ;
0660     const NP* a = NP::Load(dir, name.c_str() );
0661     load(a);
0662 }
0663 inline void sframe::load_(const char* path_)   // eg $A_FOLD/sframe.npy
0664 {
0665     const NP* a = NP::Load(path_);
0666     if(!a) std::cerr
0667        << "sframe::load_ ERROR : non-existing"
0668        << " path_ " << path_
0669        << std::endl
0670        ;
0671     assert(a);
0672     load(a);
0673 }
0674 inline void sframe::load(const NP* a)
0675 {
0676     read( a->cvalues<float>() , NUM_VALUES );
0677     std::string _frs = a->get_meta<std::string>("frs", "");
0678     std::string _tree = a->get_meta<std::string>("tree", "");
0679     std::string _dynamic = a->get_meta<std::string>("dynamic", "");
0680 
0681     if(!_frs.empty()) frs = strdup(_frs.c_str());
0682     if(!_tree.empty()) tree = strdup(_tree.c_str());
0683     if(!_dynamic.empty()) dynamic = strdup(_dynamic.c_str());
0684 }
0685 
0686 
0687 
0688 /**
0689 sframe::prepare
0690 -----------------
0691 
0692 
0693 **/
0694 
0695 inline void sframe::prepare()
0696 {
0697     tr_m2w = Tran<double>::ConvertFromQat(&m2w) ;
0698     tr_w2m = Tran<double>::ConvertFromQat(&w2m) ;
0699 }
0700 
0701 
0702 /**
0703 sframe::transform_photon_m2w
0704 -------------------------------
0705 
0706 Canonical call from SEvt::setFrame for transforming input photons into frame
0707 When normalize is true the mom and pol are normalized after the transformation.
0708 
0709 Note that the transformed photon array is always in double precision.
0710 That will be narrowed down to float prior to upload by QEvt::setInputPhoton
0711 
0712 **/
0713 
0714 inline NP* sframe::transform_photon_m2w( const NP* ph, bool normalize ) const
0715 {
0716     bool inverse = false ;
0717     return transform_photon(ph, normalize, inverse);
0718 }
0719 inline NP* sframe::transform_photon_w2m( const NP* ph, bool normalize ) const
0720 {
0721     bool inverse = true ;
0722     return transform_photon(ph, normalize, inverse);
0723 }
0724 
0725 inline NP* sframe::transform_photon( const NP* ph, bool normalize, bool inverse  ) const
0726 {
0727     if( ph == nullptr ) return nullptr ;
0728     Tran<double>* tr = inverse ? tr_w2m : tr_m2w ;
0729     if(!tr) std::cerr << "sframe::transform_photon MUST sframe::prepare before calling sframe::transform_photon " << std::endl;
0730     assert( tr ) ;
0731     NP* pht = Tran<double>::PhotonTransform(ph, normalize, tr, false );
0732     assert( pht->ebyte == 8 );
0733     return pht ;
0734 }
0735 
0736 inline void sframe::transform_m2w( sphoton& p, bool normalize ) const
0737 {
0738     if(!tr_m2w) std::cerr << "sframe::transform_m2w MUST sframe::prepare before calling this " << std::endl;
0739     assert( tr_m2w) ;
0740     p.transform( tr_m2w->t, normalize );
0741 }
0742 
0743 inline void sframe::transform_w2m( sphoton& p, bool normalize ) const
0744 {
0745     if(!tr_w2m) std::cerr << "sframe::transform_w2m MUST sframe::prepare before calling this " << std::endl;
0746     assert( tr_w2m) ;
0747     p.transform( tr_w2m->t, normalize );
0748 }
0749 
0750 
0751 inline Tran<double>* sframe::getTransform() const
0752 {
0753     double eps = 1e-3 ; // formerly used 1e-6 gives idenity check warnings
0754     Tran<double>* geotran = Tran<double>::FromPair( &m2w, &w2m, eps );
0755     return geotran ;
0756 }
0757 
0758 inline void sframe::setTranslate(float x, float y, float z)  // UNTESTED
0759 {
0760     qat4 m2w(x,y,z);
0761     setTransform(&m2w);
0762 }
0763 
0764 inline void sframe::setTransform(const qat4* m2w_ )  // UNTESTED
0765 {
0766     const qat4* w2m_ = Tran<double>::Invert(m2w_);
0767     qat4::copy(m2w, *m2w_ );
0768     qat4::copy(w2m, *w2m_ );
0769 }
0770 
0771 
0772 inline void sframe::set_m2w(const glm::tmat4x4<double>& g_m2w)
0773 {
0774     const qat4* q_m2w = Tran<double>::ConvertFrom(g_m2w);
0775     qat4::copy(m2w, *q_m2w);
0776 }
0777 inline void sframe::set_w2m(const glm::tmat4x4<double>& g_w2m)
0778 {
0779     const qat4* q_w2m = Tran<double>::ConvertFrom(g_w2m);
0780     qat4::copy(w2m, *q_w2m);
0781 }
0782 
0783 
0784 
0785 
0786 
0787 
0788 
0789 
0790 
0791 
0792 
0793 
0794 
0795 inline std::ostream& operator<<(std::ostream& os, const sframe& fr)
0796 {
0797     os << fr.desc() ;
0798     return os;
0799 }
0800 
0801