File indexing completed on 2026-04-09 07:49:46
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "NP.hh"
0011
0012
0013 #include "ssys.h"
0014 #include "spath.h"
0015 #include "sphoton.h"
0016 #include "sseq_record.h"
0017 #include "sstr.h"
0018 #include "scuda.h"
0019
0020
0021
0022 struct SRecord
0023 {
0024 static constexpr const char* NAME = "record.npy" ;
0025 static constexpr const char* RPOS_SPEC = "4,GL_FLOAT,GL_FALSE,64,0,false";
0026 static constexpr const char* _level = "SRecord__level" ;
0027 static int level ;
0028
0029 NP* record;
0030 int record_first ;
0031 int record_count ;
0032
0033 float4 mn = {} ;
0034 float4 mx = {} ;
0035 float4 ce = {} ;
0036
0037 static NP* LoadArray( const char* _fold, const char* _slice );
0038 static SRecord* Load( const char* _fold, const char* _slice=nullptr );
0039
0040 SRecord(NP* record);
0041 void init() ;
0042
0043 const float* get_mn() const ;
0044 const float* get_mx() const ;
0045 const float* get_ce() const ;
0046
0047 const float get_t0() const ;
0048 const float get_t1() const ;
0049 std::string desc() const ;
0050
0051 void getPhotonAtTime( std::vector<sphoton>* pp, std::vector<quad4>* qq, const char* iprt ) const ;
0052 static bool FindInterpolatedPhotonFromRecordAtTime( sphoton& p, const std::vector<sphoton>& point, float t);
0053
0054 NP* getPhotonAtTime( const char* iprt ) const;
0055 NP* getSimtraceAtTime( const char* iprt ) const;
0056
0057
0058 };
0059
0060
0061 int SRecord::level = ssys::getenvint(_level,0) ;
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 inline NP* SRecord::LoadArray(const char* _fold, const char* _slice )
0099 {
0100 const char* path = spath::Resolve(_fold, NAME);
0101 bool looks_unresolved = spath::LooksUnresolved(path, _fold);
0102 if(looks_unresolved)
0103 {
0104 std::cout
0105 << "SRecord::LoadArray"
0106 << " FAILED : DUE TO MISSING ENVVAR\n"
0107 << " _fold [" << ( _fold ? _fold : "-" ) << "]\n"
0108 << " path [" << ( path ? path : "-" ) << "]\n"
0109 << " looks_unresolved " << ( looks_unresolved ? "YES" : "NO " )
0110 << "\n"
0111 ;
0112 return nullptr ;
0113 }
0114
0115 NP* a = nullptr ;
0116
0117 if( _slice == nullptr )
0118 {
0119 a = NP::Load(path);
0120 a->set_meta<std::string>("SRecord__LoadArray", "NP::Load");
0121 }
0122 else if(sseq_record::LooksLikeRecordSeqSelection(_slice))
0123 {
0124 a = sseq_record::LoadRecordSeqSelection(_fold, _slice);
0125 a->set_meta<std::string>("SRecord__LoadArray_METHOD", "sseq_record::LoadRecordSeqSelection");
0126 a->set_meta<std::string>("SRecord__LoadArray_SLICE", _slice );
0127 }
0128 else if(NP::LooksLikeWhereSelection(_slice))
0129 {
0130 a = NP::LoadThenSlice<float>(path, _slice);
0131 a->set_meta<std::string>("SRecord__LoadArray_METHOD", "NP::LoadThenSlice");
0132 a->set_meta<std::string>("SRecord__LoadArray_SLICE", _slice );
0133 }
0134 else
0135 {
0136 a = NP::LoadSlice(path, _slice);
0137 a->set_meta<std::string>("SRecord__LoadArray_METHOD", "NP::LoadSlice");
0138 a->set_meta<std::string>("SRecord__LoadArray_SLICE", _slice );
0139 }
0140 return a ;
0141 }
0142
0143
0144 inline SRecord* SRecord::Load(const char* _fold, const char* _slice )
0145 {
0146 NP* _record = LoadArray(_fold, _slice);
0147 return _record ? new SRecord(_record) : nullptr ;
0148 }
0149
0150
0151
0152
0153 inline SRecord::SRecord(NP* _record)
0154 :
0155 record(_record),
0156 record_first(0),
0157 record_count(0)
0158 {
0159 init();
0160 }
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171 inline void SRecord::init()
0172 {
0173 assert(record->shape.size() == 4);
0174 bool is_compressed = record->ebyte == 2 ;
0175 assert( is_compressed == false );
0176
0177 record_first = 0 ;
0178 record_count = record->shape[0]*record->shape[1] ;
0179
0180 bool skip_flagmask_zero = true ;
0181 sphoton::MinMaxPost(&mn.x, &mx.x, record, skip_flagmask_zero );
0182 ce = scuda::center_extent( mn, mx );
0183
0184 record->set_meta<float>("x0", mn.x );
0185 record->set_meta<float>("x1", mx.x );
0186
0187 record->set_meta<float>("y0", mn.y );
0188 record->set_meta<float>("y1", mx.y );
0189
0190 record->set_meta<float>("z0", mn.z );
0191 record->set_meta<float>("z1", mx.z );
0192
0193 record->set_meta<float>("t0", mn.w );
0194 record->set_meta<float>("t1", mx.w );
0195
0196 record->set_meta<float>("cx", ce.x );
0197 record->set_meta<float>("cy", ce.y );
0198 record->set_meta<float>("cz", ce.z );
0199 record->set_meta<float>("ce", ce.w );
0200 }
0201
0202
0203
0204 inline const float* SRecord::get_mn() const
0205 {
0206 return &mn.x ;
0207 }
0208 inline const float* SRecord::get_mx() const
0209 {
0210 return &mx.x ;
0211 }
0212 inline const float* SRecord::get_ce() const
0213 {
0214 return &ce.x ;
0215 }
0216
0217 inline const float SRecord::get_t0() const
0218 {
0219 return mn.w ;
0220 }
0221 inline const float SRecord::get_t1() const
0222 {
0223 return mx.w ;
0224 }
0225
0226
0227 inline std::string SRecord::desc() const
0228 {
0229 const char* lpath = record ? record->lpath.c_str() : nullptr ;
0230
0231 std::stringstream ss ;
0232 ss
0233 << "[SRecord.desc\n"
0234 << " lpath [" << ( lpath ? lpath : "-" ) << "]\n"
0235 << std::setw(20) << " mn " << mn
0236 << std::endl
0237 << std::setw(20) << " mx " << mx
0238 << std::endl
0239 << std::setw(20) << " ce " << ce
0240 << std::endl
0241 << std::setw(20) << " record.sstr " << record->sstr()
0242 << std::endl
0243 << std::setw(20) << " record_first " << record_first
0244 << std::endl
0245 << std::setw(20) << " record_count " << record_count
0246 << std::endl
0247 << ( record ? record->descMeta() : "-" )
0248 << std::endl
0249 << "]SRecord.desc\n"
0250 ;
0251 std::string str = ss.str() ;
0252 return str ;
0253 }
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289 inline void SRecord::getPhotonAtTime( std::vector<sphoton>* pp, std::vector<quad4>* qq, const char* _iprt ) const
0290 {
0291 NP* iprt = NP::ARange_FromString<float>(_iprt);
0292 const float* tt = iprt ? iprt->cvalues<float>() : nullptr ;
0293
0294 int ni = record->shape[0] ;
0295 int nj = iprt ? iprt->num_items() : 0 ;
0296 int nl = record->shape[1] ;
0297 int item_bytes = record->item_bytes() ;
0298
0299 assert( nj > 0 && tt );
0300 int count0 = -1 ;
0301
0302 for(int i=0 ; i < ni ; i++)
0303 {
0304
0305 std::vector<sphoton> point(nl) ;
0306 memcpy( point.data(), record->bytes() + i*item_bytes, item_bytes );
0307
0308 int count = 0 ;
0309 for(int j=0 ; j < nj ; j++)
0310 {
0311 float t = tt[j] ;
0312 sphoton p = {} ;
0313 bool found = FindInterpolatedPhotonFromRecordAtTime( p, point, t);
0314 if(!found) continue ;
0315
0316 count += 1 ;
0317
0318 quad4 q = {} ;
0319 p.populate_simtrace_input(q);
0320
0321 if(pp) pp->push_back(p);
0322 if(qq) qq->push_back(q);
0323 }
0324
0325 bool consistent_count = count0 == -1 || count0 == count ;
0326 if( count0 == -1 ) count0 = count ;
0327
0328 if(!consistent_count || level > 0) std::cout
0329 << "SRecord::getPhotonAtTime"
0330 << " i " << std::setw(6) << i
0331 << " count0 " << count0
0332 << " count " << count
0333 << " consistent_count " << ( consistent_count ? "YES" : "NO " )
0334 << ( consistent_count ? "" : "(adjust time range to achieve consistency)" )
0335 << " level " << level
0336 << "\n"
0337 ;
0338 }
0339
0340
0341 if(level > 0) std::cout
0342 << "SRecord::getPhotonAtTime"
0343 << " [" << _level << "] " << level
0344 << " _iprt " << ( _iprt ? _iprt : "-" )
0345 << " iprt " << ( iprt ? iprt->sstr() : "-" )
0346 << " ni " << ni
0347 << " nj " << nj
0348 << " nl " << nl
0349 << " tt " << ( tt ? "YES" : "NO " )
0350 << " record " << ( record ? record->sstr() : "-" )
0351 << " count0 " << count0
0352 << " pp.size " << ( pp ? int(pp->size()) : -1 )
0353 << " qq.size " << ( qq ? int(qq->size()) : -1 )
0354 << "\n"
0355 ;
0356
0357 }
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372 inline bool SRecord::FindInterpolatedPhotonFromRecordAtTime( sphoton& p, const std::vector<sphoton>& point, float t)
0373 {
0374 int nl = point.size();
0375 for(int l=1 ; l < nl ; l++)
0376 {
0377 const sphoton& p0 = point[l-1] ;
0378 const sphoton& p1 = point[l] ;
0379 bool straddle = p0.time <= t && t < p1.time ;
0380
0381 if(level > 3) std::cout
0382 << "SRecord::FindInterpolatedPhotonFromRecordAtTime"
0383 << " nl " << nl
0384 << " l " << std::setw(3) << l
0385 << " t " << std::fixed << std::setw(7) << std::setprecision(3) << t
0386 << " p0.time " << std::fixed << std::setw(7) << std::setprecision(3) << p0.time
0387 << " p1.time " << std::fixed << std::setw(7) << std::setprecision(3) << p1.time
0388 << " straddle " << ( straddle ? "YES" : "NO " )
0389 << "\n"
0390 ;
0391
0392 if(straddle)
0393 {
0394 p = p0 ;
0395 float frac = (t - p0.time)/(p1.time - p0.time) ;
0396 p.pos = lerp( p0.pos, p1.pos, frac ) ;
0397 p.time = t ;
0398 return true ;
0399 }
0400 }
0401 return false ;
0402 }
0403
0404
0405 inline NP* SRecord::getPhotonAtTime( const char* iprt ) const
0406 {
0407 std::vector<sphoton> vpp ;
0408 getPhotonAtTime(&vpp, nullptr, iprt);
0409 int num_pp = vpp.size();
0410 NP* pp = num_pp > 0 ? NPX::ArrayFromVec<float,sphoton>(vpp, 4, 4 ) : nullptr ;
0411 return pp ;
0412 }
0413
0414 inline NP* SRecord::getSimtraceAtTime( const char* iprt ) const
0415 {
0416 std::vector<quad4> vqq ;
0417 getPhotonAtTime(nullptr, &vqq, iprt);
0418 int num_qq = vqq.size();
0419 NP* qq = num_qq > 0 ? NPX::ArrayFromVec<float,quad4>(vqq, 4, 4 ) : nullptr ;
0420 return qq ;
0421 }
0422
0423