File indexing completed on 2026-04-09 07:49:28
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008
0009 #include "NP.hh"
0010 #include <unordered_map>
0011
0012
0013 struct NPX
0014 {
0015 template<typename T>
0016 static NP* MakeValues( const std::vector<std::string>& keys, const std::vector<T>& vals );
0017 template<typename T>
0018 static NP* MakeValues( const std::vector<std::pair<std::string, T>>& values, const char* contains=nullptr );
0019 template<typename T>
0020 static std::string DescValues(const NP* a);
0021
0022 template<typename T>
0023 struct KV
0024 {
0025 std::vector<std::string> kk ;
0026 std::vector<T> vv ;
0027
0028 void add(const char* k, T v ){ kk.push_back(k); vv.push_back(v); }
0029 NP* values() const { return MakeValues<T>(kk, vv) ; }
0030 };
0031
0032
0033 static NP* MakeDemo(const char* dtype="<f4" , NP::INT ni=-1, NP::INT nj=-1, NP::INT nk=-1, NP::INT nl=-1, NP::INT nm=-1, NP::INT no=-1 );
0034
0035 template<typename T> static NP* Make( const std::vector<T>& src );
0036 template<typename T> static NP* Make( T d0, T v0, T d1, T v1 );
0037 template<typename T, typename... Args> static NP* Make(const T* src, Args ... shape );
0038 template<typename T, typename... Args> static NP* ArrayFromData(const T* src, Args ... shape );
0039
0040 template<typename T> static NP* FromString(const char* str, char delim=' ') ;
0041
0042
0043 static NP* Holder( const std::vector<std::string>& names );
0044
0045
0046 template<typename T, int N>
0047 static NP* ArrayFromVecOfArrays(const std::vector<std::array<T,N>>& va );
0048
0049 template<typename T, int N>
0050 static void VecOfArraysFromArray( std::vector<std::array<T,N>>& va, const NP* a );
0051
0052
0053
0054 template<typename T, typename S>
0055 static NP* ArrayFromVec__(const std::vector<S>& v, const std::vector<NP::INT>& itemshape );
0056
0057 template<typename T, typename S, typename... Args>
0058 static NP* ArrayFromVec(const std::vector<S>& v, Args ... args_itemshape );
0059
0060 template<typename T, typename S>
0061 static NP* ArrayFromVec_(const std::vector<S>& v, const char* str_itemshape );
0062
0063
0064 template<typename S>
0065 static void VecFromArray(std::vector<S>& v, const NP* a );
0066
0067 template<typename S>
0068 static int VecFromMap( std::vector<S>& v, const std::map<int, S>& m, bool contiguous_key=true );
0069
0070 template<typename S>
0071 static void VecFromMapUnordered(
0072 std::vector<S>& v,
0073 const std::unordered_map<int, S>& m,
0074 const std::vector<int>* key_order,
0075 bool* all_contiguous_key,
0076 int* _k0,
0077 int* _k1
0078 );
0079
0080
0081 template<typename S>
0082 static void MapFromVec( std::map<int, S>& m, const std::vector<S>& v, int k0=0, bool contiguous_key=true );
0083
0084 template<typename S>
0085 static void MapUnorderedFromVec( std::unordered_map<int, S>& m, const std::vector<S>& v, int kmin=0, bool is_contiguous_key=true );
0086
0087
0088 template<typename T, typename S>
0089 static NP* ArrayFromMap( const std::map<int, S>& m, bool contiguous_key=true );
0090
0091 template<typename T, typename S>
0092 static NP* ArrayFromMapUnordered(
0093 const std::unordered_map<int, S>& m, const std::vector<int>* key_order=nullptr );
0094
0095 template<typename S>
0096 static void KeyRangeMapUnordered( int* _k0, int* _k1, const std::unordered_map<int, S>& m );
0097
0098 template<typename S>
0099 static void MapFromArray( std::map<int, S>& m, const NP* a );
0100
0101 template<typename S>
0102 static void MapUnorderedFromArray( std::unordered_map<int, S>& m, const NP* a );
0103
0104
0105 template<typename S>
0106 static NP* ArrayFromDiscoMap( const std::map<int, S>& m );
0107 template<typename S>
0108 static void DiscoMapFromArray( std::map<int, S>& m, const NP* a );
0109 template<typename S>
0110 static std::string DescDiscoMap( const std::map<int, S>& m );
0111
0112
0113 template<typename S>
0114 static NP* ArrayFromDiscoMapUnordered( const std::unordered_map<int, S>& m );
0115 template<typename S>
0116 static void DiscoMapUnorderedFromArray( std::unordered_map<int, S>& m, const NP* a );
0117 template<typename S>
0118 static std::string DescDiscoMapUnordered( const std::unordered_map<int, S>& m );
0119
0120
0121
0122
0123
0124 template<typename T>
0125 static NP* FromNumpyString(const char* str, bool dump=false) ;
0126
0127 static NP* CategoryArrayFromString(const char* str, int catfield, const char* cats, char delim=',');
0128 static NP* LoadCategoryArrayFromTxtFile(const char* base, const char* relp, int catfield, const char* cats, char delim=',');
0129 static NP* LoadCategoryArrayFromTxtFile(const char* path, int catfield, const char* cats, char delim=',');
0130
0131 static void Import_MSD( std::map<std::string,double>& msd, const NP* a);
0132 static NP* Serialize_MSD( const std::map<std::string,double>& msd );
0133 static std::string Desc_MSD(const std::map<std::string,double>& msd);
0134
0135 static NP* ArrayFromEnumMap( const std::map<int, std::string>& catMap) ;
0136
0137 static NP* MakeCharArray( const std::vector<std::string>& nn );
0138
0139 template<typename F, typename T>
0140 static NP* BOA( NP* a, NP* b, NP::INT a_column=-1, NP::INT b_column=-1, std::ostream* out=nullptr );
0141
0142 };
0143
0144
0145
0146 template<typename T>
0147 inline NP* NPX::MakeValues( const std::vector<std::string>& keys, const std::vector<T>& vals )
0148 {
0149 assert( keys.size() == vals.size() );
0150 if(vals.size() == 0 ) return nullptr ;
0151
0152 NP* vv = NPX::Make<T>( vals ) ;
0153 vv->set_names( keys );
0154 return vv ;
0155 }
0156
0157 template<typename T>
0158 inline NP* NPX::MakeValues( const std::vector<std::pair<std::string, T>>& values, const char* contains )
0159 {
0160 if(NP::VERBOSE) std::cout
0161 << "NPX::MakeValues values.size " << values.size()
0162 << " contains " << ( contains ? contains : "-" )
0163 << std::endl
0164 ;
0165
0166 std::vector<std::string> nams ;
0167 std::vector<T> vals ;
0168
0169 for(NP::INT i=0 ; i < NP::INT(values.size()) ; i++)
0170 {
0171 const std::pair<std::string, T>& kv = values[i] ;
0172 const char* k = kv.first.c_str() ;
0173 T v = kv.second ;
0174
0175 bool select = contains == nullptr || U::Contains( k, contains ) ;
0176
0177 if(NP::VERBOSE) std::cout
0178 << "NPX::MakeValues "
0179 << std::setw(3) << i
0180 << " v " << std::setw(10) << std::fixed << std::setprecision(4) << v
0181 << " k " << std::setw(60) << k
0182 << " select " << select
0183 << std::endl
0184 ;
0185
0186 if(select)
0187 {
0188 nams.push_back(k);
0189 vals.push_back(v);
0190 }
0191 }
0192 if(NP::VERBOSE) std::cout << "NPX::MakeValues vals.size " << vals.size() << std::endl ;
0193
0194 NP* vv = MakeValues<T>(nams, vals);
0195 return vv ;
0196 }
0197
0198 template<typename T>
0199 inline std::string NPX::DescValues(const NP* a)
0200 {
0201 std::stringstream ss ;
0202 ss << std::endl << "NPX::descValues" << std::endl ;
0203 for(unsigned i=0 ; i < a->names.size() ; i++)
0204 {
0205 const char* k = a->names[i].c_str();
0206 T v = a->get_named_value<T>(k, 0) ;
0207 ss
0208 << std::setw(30) << k
0209 << " : "
0210 << std::setw(10) << v
0211 << std::endl
0212 ;
0213 }
0214 std::string str = ss.str();
0215 return str ;
0216 }
0217
0218
0219 inline NP* NPX::MakeDemo(const char* dtype, NP::INT ni, NP::INT nj, NP::INT nk, NP::INT nl, NP::INT nm, NP::INT no )
0220 {
0221 NP* a = new NP(dtype, ni, nj, nk, nl, nm, no);
0222 a->fillIndexFlat();
0223 return a ;
0224 }
0225
0226
0227
0228 template <typename T>
0229 inline NP* NPX::Make( const std::vector<T>& src )
0230 {
0231 NP* a = NP::Make<T>(src.size());
0232 a->read(src.data());
0233 return a ;
0234 }
0235
0236 template <typename T>
0237 inline NP* NPX::Make(T d0, T v0, T d1, T v1 )
0238 {
0239 std::vector<T> src = {d0, v1, d1, v1 } ;
0240 return NPX::Make<T>(src) ;
0241 }
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265 template<typename T, typename... Args>
0266 inline NP* NPX::Make(const T* src, Args ... args )
0267 {
0268 std::cerr << "TODO: change NPX::Make to NPX::ArrayFromData \n" ;
0269 return ArrayFromData(src, std::forward<Args>(args)...) ;
0270 }
0271
0272 template<typename T, typename... Args>
0273 inline NP* NPX::ArrayFromData(const T* src, Args ... args )
0274 {
0275 std::string dtype = descr_<T>::dtype() ;
0276 std::vector<NP::INT> shape = {args...};
0277 if(shape.size() > 0 && shape[0] == 0) return nullptr ;
0278 NP* a = new NP(dtype.c_str(), shape );
0279 a->read2(src);
0280 return a ;
0281 }
0282
0283
0284
0285 template <typename T>
0286 inline NP* NPX::FromString(const char* str, char delim)
0287 {
0288 std::vector<T> vec ;
0289 std::stringstream ss(str);
0290 std::string s ;
0291 while(getline(ss, s, delim)) vec.push_back(U::To<T>(s.c_str()));
0292 NP* a = Make<T>(vec) ;
0293 return a ;
0294 }
0295
0296
0297
0298
0299
0300
0301
0302 inline NP* NPX::Holder( const std::vector<std::string>& names )
0303 {
0304 NP* a = NP::Make<int>(0) ;
0305 a->set_names(names) ;
0306 return a ;
0307 }
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322 template<typename T, int N>
0323 inline NP* NPX::ArrayFromVecOfArrays(const std::vector<std::array<T,N>>& va )
0324 {
0325 NP::INT ni = va.size();
0326 NP::INT nj = N ;
0327 NP* a = NP::Make<T>(ni, nj);
0328 T* aa = a->values<T>();
0329 for(NP::INT i=0 ; i < ni ; i++)
0330 {
0331 const std::array<T,N>& arr = va[i] ;
0332 for(NP::INT j=0 ; j < nj ; j++) aa[i*nj+j] = arr[j] ;
0333 }
0334 return a ;
0335 }
0336
0337
0338 template<typename T, int N>
0339 inline void NPX::VecOfArraysFromArray( std::vector<std::array<T,N>>& va, const NP* a )
0340 {
0341 assert( a && a->uifc == 'f' && a->ebyte == sizeof(T) );
0342 assert( a && a->shape.size() == 2 );
0343
0344 NP::INT ni = a->shape[0];
0345 NP::INT nj = a->shape[1];
0346 const T* aa = a->cvalues<T>();
0347
0348 va.resize(ni);
0349 for(NP::INT i=0 ; i < ni ; i++)
0350 {
0351 std::array<T,N>& arr = va[i] ;
0352 for(NP::INT j=0 ; j < nj ; j++) arr[j] = aa[i*nj+j] ;
0353 }
0354
0355 }
0356
0357
0358
0359
0360
0361
0362 template<typename T, typename S>
0363 inline NP* NPX::ArrayFromVec__(const std::vector<S>& v, const std::vector<NP::INT>& itemshape )
0364 {
0365 assert( sizeof(S) >= sizeof(T) );
0366 NP::INT ni = v.size() ;
0367 NP::INT nj = sizeof(S) / sizeof(T) ;
0368
0369 const T* src = (T*)v.data() ;
0370
0371 std::vector<NP::INT> shape ;
0372 shape.push_back(ni) ;
0373
0374 if(itemshape.size() == 0 )
0375 {
0376 shape.push_back(nj) ;
0377 }
0378 else
0379 {
0380 NP::INT itemcheck = 1 ;
0381 for(NP::INT i=0 ; i < NP::INT(itemshape.size()) ; i++)
0382 {
0383 shape.push_back(itemshape[i]) ;
0384 itemcheck *= itemshape[i] ;
0385 }
0386 bool consistent = itemcheck == nj ;
0387
0388 if(!consistent) std::cerr
0389 << "NPX::ArrayFromVec__"
0390 << " ERROR "
0391 << " consistent " << ( consistent ? "YES" : "NO " )
0392 << " itemcheck " << itemcheck
0393 << " nj " << nj
0394 << " itemshape.size " << itemshape.size()
0395 << std::endl
0396 ;
0397
0398 assert(consistent);
0399 }
0400
0401
0402 NP* a = NP::Make_<T>(shape) ;
0403 a->read2(src);
0404 return a ;
0405 }
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438 template<typename T, typename S, typename... Args>
0439 inline NP* NPX::ArrayFromVec(const std::vector<S>& v, Args ... args_itemshape )
0440 {
0441 std::vector<NP::INT> itemshape = {args_itemshape...};
0442 return ArrayFromVec__<T,S>(v, itemshape );
0443 }
0444
0445 template<typename T, typename S>
0446 inline NP* NPX::ArrayFromVec_(const std::vector<S>& v, const char* str_itemshape )
0447 {
0448 std::vector<NP::INT> itemshape ;
0449 U::MakeVec(itemshape, str_itemshape, ',' );
0450 return ArrayFromVec__<T,S>(v, itemshape );
0451 }
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464 template<typename S>
0465 inline void NPX::VecFromArray(std::vector<S>& v, const NP* a )
0466 {
0467 if(a == nullptr || a->shape.size() == 0 ) return ;
0468 NP::INT ni = a->shape[0] ;
0469 unsigned ib = a->item_bytes() ;
0470 bool expected_sizeof_item = sizeof(S) == ib ;
0471
0472 if(!expected_sizeof_item)
0473 std::cerr
0474 << "NPX::VecFromArray"
0475 << " expected_sizeof_item " << ( expected_sizeof_item ? "YES" : "NO" )
0476 << " sizeof(S) " << sizeof(S)
0477 << " a.item_bytes " << ib
0478 << " a.sstr " << a->sstr()
0479 << std::endl
0480 << " a.lpath " << a->get_lpath()
0481 << std::endl
0482 << " CHECK FOR COMPILATION OPTIONS THAT CHANGE STRUCT SIZES "
0483 << std::endl
0484 << " FOR EXAMPLE WITH_CHILD CHANGES sysrap/sn.h "
0485 << std::endl
0486 << " ANOTHER POSSIBILITY IS LOADING AN ARRAY WRITTEN BEFORE STRUCT SIZE CHANGES "
0487 << std::endl
0488 ;
0489
0490 assert( expected_sizeof_item );
0491
0492 v.clear() ;
0493 v.resize(ni);
0494
0495 memcpy( v.data(), a->bytes(), a->arr_bytes() );
0496 }
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519 template<typename S>
0520 inline int NPX::VecFromMap( std::vector<S>& v, const std::map<int, S>& m, bool contiguous_key )
0521 {
0522 NP::INT ni = NP::INT(m.size()) ;
0523
0524 v.clear();
0525 v.resize(ni);
0526
0527 typename std::map<int,S>::const_iterator it = m.begin() ;
0528 int k0 = it->first ;
0529
0530 for(NP::INT idx=0 ; idx < ni ; idx++)
0531 {
0532 int k = it->first ;
0533 v[idx] = it->second ;
0534
0535 if(contiguous_key) assert( k == k0 + idx );
0536
0537
0538 std::advance(it, 1);
0539 }
0540 return k0 ;
0541 }
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573 template<typename S>
0574 inline void NPX::VecFromMapUnordered(
0575 std::vector<S>& v,
0576 const std::unordered_map<int, S>& m,
0577 const std::vector<int>* key_order,
0578 bool* all_contiguous_key,
0579 int* _k0,
0580 int* _k1
0581 )
0582 {
0583 NP::INT ni = m.size() ;
0584 v.clear();
0585 v.resize(ni);
0586
0587 if(key_order)
0588 {
0589 assert( key_order->size() == m.size() ) ;
0590 }
0591
0592 NP::INT count(0) ;
0593 if( key_order == nullptr ) KeyRangeMapUnordered(_k0, _k1, m ) ;
0594
0595
0596 NP::INT k0_check(-999) ;
0597
0598 for(NP::INT idx=0 ; idx < ni ; idx++)
0599 {
0600 NP::INT k = key_order ? (*key_order)[idx] : *_k0 + idx ;
0601
0602
0603 if( idx == 0 )
0604 {
0605 k0_check = k ;
0606 count += 1 ;
0607 }
0608 else
0609 {
0610 if( k == k0_check + idx ) count += 1 ;
0611 }
0612
0613 const S& s = m.at(k);
0614 v[idx] = s ;
0615 }
0616
0617 *all_contiguous_key = ni > 0 && count == ni ;
0618
0619 if(key_order == nullptr)
0620 {
0621 assert( *all_contiguous_key ) ;
0622 assert( *_k1 - *_k0 + 1 == ni ) ;
0623 assert( k0_check == *_k0 );
0624 }
0625
0626 }
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642 template<typename S>
0643 inline void NPX::MapFromVec( std::map<int, S>& m, const std::vector<S>& v, int k0, bool contiguous_key )
0644 {
0645 assert( contiguous_key == true );
0646
0647 NP::INT ni = NP::INT(v.size()) ;
0648 m.clear();
0649
0650 for(NP::INT i=0 ; i < ni ; i++)
0651 {
0652 const S& item = v[i] ;
0653 NP::INT key = k0 + i ;
0654 m[key] = item ;
0655 }
0656 }
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668 template<typename S>
0669 inline void NPX::MapUnorderedFromVec( std::unordered_map<int, S>& m, const std::vector<S>& v, int kmin, bool is_contiguous_key )
0670 {
0671 assert( is_contiguous_key == true );
0672
0673 NP::INT ni = NP::INT(v.size()) ;
0674 m.clear();
0675
0676 for(NP::INT idx=0 ; idx < ni ; idx++)
0677 {
0678 const S& item = v[idx] ;
0679 NP::INT key = kmin + idx ;
0680 m[key] = item ;
0681 }
0682 }
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708
0709 template<typename T, typename S>
0710 inline NP* NPX::ArrayFromMap( const std::map<int, S>& m, bool contiguous_key )
0711 {
0712 assert( sizeof(S) >= sizeof(T) );
0713
0714 std::vector<S> v ;
0715 int k0 = NPX::VecFromMap<S>( v, m, contiguous_key );
0716 NP* a = NPX::ArrayFromVec<T,S>(v) ;
0717
0718 int ContiguousKey = contiguous_key ? 1 : 0 ;
0719
0720 if(NP::VERBOSE) std::cout
0721 << "NPX::ArrayFromMap"
0722 << " k0 " << k0
0723 << " ContiguousKey " << ContiguousKey
0724 << std::endl
0725 ;
0726
0727 a->set_meta<int>("k0", k0) ;
0728 a->set_meta<int>("ContiguousKey", ContiguousKey) ;
0729
0730 return a ;
0731 }
0732
0733
0734
0735
0736
0737
0738
0739
0740
0741
0742
0743
0744
0745
0746
0747
0748 template<typename T, typename S>
0749 inline NP* NPX::ArrayFromMapUnordered( const std::unordered_map<int, S>& m, const std::vector<int>* key_order )
0750 {
0751 assert( sizeof(S) >= sizeof(T) );
0752
0753 std::vector<S> v ;
0754 bool all_contiguous_key(false) ;
0755 int kmin(0) ;
0756 int kmax(0) ;
0757
0758 NPX::VecFromMapUnordered<S>( v, m, key_order, &all_contiguous_key, &kmin, &kmax );
0759 NP* a = NPX::ArrayFromVec<T,S>(v) ;
0760
0761 a->set_meta<int>("kmin", kmin) ;
0762 a->set_meta<int>("kmax", kmax) ;
0763 a->set_meta<int>("ContiguousKey", all_contiguous_key ) ;
0764 a->set_meta<std::string>("Creator", "NPX::ArrayFromMapUnordered" );
0765
0766 return a ;
0767 }
0768
0769
0770
0771
0772
0773
0774
0775
0776
0777
0778
0779
0780 template<typename S>
0781 inline void NPX::KeyRangeMapUnordered( int* _k0, int* _k1, const std::unordered_map<int, S>& m )
0782 {
0783 assert( _k0 );
0784 assert( _k1 );
0785
0786 *_k0 = std::numeric_limits<int>::max() ;
0787 *_k1 = std::numeric_limits<int>::min() ;
0788
0789 typedef std::unordered_map<int,S> UIS ;
0790 for(typename UIS::const_iterator it=m.begin() ; it != m.end() ; it++ )
0791 {
0792 int k = it->first ;
0793 if( k < *_k0 ) *_k0 = k ;
0794 if( k > *_k1 ) *_k1 = k ;
0795 }
0796 }
0797
0798
0799
0800
0801
0802
0803
0804 template<typename S>
0805 inline void NPX::MapFromArray( std::map<int, S>& m, const NP* a )
0806 {
0807 if(a == nullptr || a->shape.size() == 0 ) return ;
0808
0809 int k0 = a->get_meta<int>("k0");
0810 int ContiguousKey = a->get_meta<int>("ContiguousKey") ;
0811 if(NP::VERBOSE) std::cout
0812 << "NPX::MapFromArray"
0813 << " k0 " << k0
0814 << " ContiguousKey " << ContiguousKey
0815 << std::endl
0816 ;
0817
0818 std::vector<S> v ;
0819 NPX::VecFromArray<S>(v, a);
0820
0821 NPX::MapFromVec(m, v, k0, ContiguousKey == 1 );
0822 }
0823
0824
0825
0826 template<typename S>
0827 inline void NPX::MapUnorderedFromArray( std::unordered_map<int, S>& m, const NP* a )
0828 {
0829 if(a == nullptr || a->shape.size() == 0 ) return ;
0830
0831 int kmin = a->get_meta<int>("kmin");
0832 int kmax = a->get_meta<int>("kmax");
0833 int ContiguousKey = a->get_meta<int>("ContiguousKey") ;
0834 bool is_contiguous_key = ContiguousKey == 1 ;
0835
0836
0837 if(NP::VERBOSE) std::cout
0838 << "NPX::MapUnorderedFromArray"
0839 << " kmin " << kmin
0840 << " kmax " << kmax
0841 << " is_contiguous_key " << ( is_contiguous_key ? "YES" : "NO " )
0842 << std::endl
0843 ;
0844
0845 std::vector<S> v ;
0846 NPX::VecFromArray<S>(v, a);
0847
0848 NPX::MapUnorderedFromVec<S>(m, v, kmin, is_contiguous_key );
0849 }
0850
0851
0852
0853
0854
0855
0856
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874
0875 template<typename S>
0876 inline NP* NPX::ArrayFromDiscoMap( const std::map<int, S>& m )
0877 {
0878 return nullptr ;
0879 }
0880
0881 template<typename S>
0882 inline NP* NPX::ArrayFromDiscoMapUnordered( const std::unordered_map<int, S>& m )
0883 {
0884 return nullptr ;
0885 }
0886
0887
0888
0889
0890
0891 template<>
0892 inline NP* NPX::ArrayFromDiscoMap( const std::map<int,int>& m )
0893 {
0894 NP::INT ni = m.size() ;
0895 NP::INT nj = 2 ;
0896 NP* a = NP::Make<int>(ni, nj) ;
0897 int* aa = a->values<int>();
0898
0899 typedef std::map<int,int> MII ;
0900 MII::const_iterator it = m.begin();
0901
0902 for(NP::INT i=0 ; i < ni ; i++)
0903 {
0904 aa[i*nj+0] = it->first ;
0905 aa[i*nj+1] = it->second ;
0906 it++ ;
0907 }
0908 return a ;
0909 }
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926 template<>
0927 inline NP* NPX::ArrayFromDiscoMapUnordered( const std::unordered_map<int,int>& m )
0928 {
0929
0930
0931 std::vector<int> keys ;
0932 typedef std::unordered_map<int,int> MII ;
0933 for(MII::const_iterator it=m.begin() ; it != m.end() ; it++) keys.push_back(it->first);
0934
0935
0936 std::sort(keys.begin(), keys.end());
0937
0938
0939 NP::INT ni = m.size() ;
0940 assert( NP::INT(keys.size()) == ni );
0941
0942
0943 NP::INT nj = 2 ;
0944 NP* a = NP::Make<int>(ni, nj) ;
0945 int* aa = a->values<int>();
0946
0947
0948 for(NP::INT i=0 ; i < ni ; i++)
0949 {
0950 NP::INT key = keys[i] ;
0951 int val = m.at(key) ;
0952 aa[i*nj+0] = key ;
0953 aa[i*nj+1] = val ;
0954 }
0955 return a ;
0956 }
0957
0958
0959
0960
0961
0962
0963
0964
0965
0966
0967
0968 template<typename S>
0969 inline void NPX::DiscoMapFromArray( std::map<int, S>& m, const NP* a ){}
0970
0971 template<typename S>
0972 inline void NPX::DiscoMapUnorderedFromArray( std::unordered_map<int, S>& m, const NP* a ){}
0973
0974
0975
0976
0977 template<>
0978 inline void NPX::DiscoMapFromArray( std::map<int, int>& m, const NP* a )
0979 {
0980 assert( a && a->uifc == 'i' && a->ebyte == 4 && a->shape.size() == 2 );
0981 NP::INT ni = a->shape[0] ;
0982 NP::INT nj = a->shape[1] ;
0983 assert( nj == 2 );
0984
0985 const int* aa = a->cvalues<int>();
0986 for(NP::INT i=0 ; i < ni ; i++)
0987 {
0988 int k = aa[i*nj+0] ;
0989 int v = aa[i*nj+1] ;
0990 m[k] = v ;
0991 }
0992 }
0993
0994
0995 template<>
0996 inline void NPX::DiscoMapUnorderedFromArray( std::unordered_map<int, int>& m, const NP* a )
0997 {
0998 assert( a && a->uifc == 'i' && a->ebyte == 4 && a->shape.size() == 2 );
0999 NP::INT ni = a->shape[0] ;
1000 NP::INT nj = a->shape[1] ;
1001 assert( nj == 2 );
1002
1003 const int* aa = a->cvalues<int>();
1004 for(NP::INT i=0 ; i < ni ; i++)
1005 {
1006 int k = aa[i*nj+0] ;
1007 int v = aa[i*nj+1] ;
1008 m[k] = v ;
1009 }
1010 }
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021 template<typename S>
1022 inline std::string NPX::DescDiscoMap( const std::map<int, S>& m )
1023 {
1024 std::stringstream ss ;
1025 ss << "NPX::DescDiscoMap" << std::endl << " m.size " << m.size() ;
1026 std::string s = ss.str();
1027 return s ;
1028 }
1029
1030 template<typename S>
1031 inline std::string NPX::DescDiscoMapUnordered( const std::unordered_map<int, S>& m )
1032 {
1033 std::stringstream ss ;
1034 ss << "NPX::DescDiscoMapUnordered" << std::endl << " m.size " << m.size() ;
1035 std::string s = ss.str();
1036 return s ;
1037 }
1038
1039
1040
1041
1042 template<>
1043 inline std::string NPX::DescDiscoMap( const std::map<int,int>& m )
1044 {
1045 NP::INT ni = m.size() ;
1046 typedef std::map<int,int> MII ;
1047 MII::const_iterator it = m.begin();
1048 std::stringstream ss ;
1049 ss << "NPX::DescDiscoMap" << std::endl << " m.size " << ni << std::endl ;
1050 for(NP::INT i=0 ; i < ni ; i++)
1051 {
1052 ss << "( " << it->first << " : " << it->second << " ) " << std::endl ;
1053 it++ ;
1054 }
1055 std::string s = ss.str();
1056 return s ;
1057 }
1058
1059
1060 template<>
1061 inline std::string NPX::DescDiscoMapUnordered( const std::unordered_map<int,int>& m )
1062 {
1063 NP::INT ni = m.size() ;
1064 typedef std::unordered_map<int,int> MII ;
1065 MII::const_iterator it = m.begin();
1066 std::stringstream ss ;
1067 ss << "NPX::DescDiscoMapUnordered" << std::endl << " m.size " << ni << std::endl ;
1068 for(NP::INT i=0 ; i < ni ; i++)
1069 {
1070 ss << "( " << it->first << " : " << it->second << " ) " << std::endl ;
1071 it++ ;
1072 }
1073 std::string s = ss.str();
1074 return s ;
1075 }
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090 template <typename T>
1091 inline NP* NPX::FromNumpyString(const char* str, bool dump)
1092 {
1093 static const char* dtype_pfx = "dtype=" ;
1094
1095 std::vector<T> vec ;
1096 std::stringstream fss(str);
1097
1098 int num_field_0 = 0 ;
1099 std::string line ;
1100 while(getline(fss, line))
1101 {
1102 if(strlen(line.c_str())==0) continue ;
1103 if(dump) std::cout << "{" << line << "}" << std::endl ;
1104 std::istringstream iss(line);
1105 std::vector<std::string> fields ;
1106 std::string field ;
1107 while( iss >> field ) fields.push_back(field) ;
1108
1109 int num_field = 0 ;
1110
1111 if(dump) std::cout << "fields.size " << fields.size() << std::endl ;
1112 if(dump) for(NP::INT j=0 ; j < NP::INT(fields.size()) ; j++ ) std::cout << "{" << fields[j].c_str() << "}\n" ;
1113
1114 for(NP::INT j=0 ; j < NP::INT(fields.size()) ; j++ )
1115 {
1116 const char* fld = fields[j].c_str() ;
1117 char* fldd = U::FirstToLastDigit(fld);
1118 if(fldd == nullptr) continue ;
1119
1120
1121 bool dtype_field = 0 == strncmp(fld, dtype_pfx, strlen(dtype_pfx));
1122 if(dtype_field) continue ;
1123
1124 T val = U::To<T>(fldd) ;
1125
1126 if(dump) std::cout
1127 << "{" << fld << "}"
1128 << "{" << fldd << "}"
1129 << "{" << val << "}"
1130 << " num_field: " << num_field
1131 << std::endl
1132 ;
1133 num_field += 1 ;
1134 vec.push_back( val );
1135 }
1136 if( num_field_0 == 0 )
1137 {
1138 num_field_0 = num_field ;
1139 }
1140 else
1141 {
1142 assert( num_field_0 == num_field );
1143 }
1144 }
1145
1146 NP* a = Make<T>(vec) ;
1147 a->change_shape(-1, num_field_0);
1148
1149 return a ;
1150 }
1151
1152 inline NP* NPX::CategoryArrayFromString(const char* str, int catfield, const char* cats_, char delim )
1153 {
1154 std::vector<std::string> cats ;
1155 U::MakeVec(cats, cats_, delim );
1156
1157 int num_field = 0 ;
1158 std::vector<int> data ;
1159 std::string line ;
1160 std::stringstream fss(str) ;
1161 while(std::getline(fss, line))
1162 {
1163 std::istringstream iss(line);
1164 std::vector<std::string> fields ;
1165 std::string field ;
1166 while( iss >> field ) fields.push_back(field) ;
1167
1168 if(num_field == 0) num_field = fields.size() ;
1169 else assert( int(fields.size()) == num_field );
1170
1171 assert( catfield < num_field );
1172 for(int i=0 ; i < num_field ; i++)
1173 {
1174 const std::string& fld = fields[i] ;
1175 int val = i == catfield ? U::Category(cats, fld ) : std::atoi(fld.c_str()) ;
1176 data.push_back(val);
1177 }
1178 }
1179
1180 NP* a = Make<int>( data );
1181 a->change_shape(-1, num_field);
1182 a->set_names(cats);
1183 return a ;
1184 }
1185
1186 inline NP* NPX::LoadCategoryArrayFromTxtFile(const char* base, const char* relp, int catfield, const char* cats, char delim )
1187 {
1188 std::string path = U::form_path(base, relp);
1189 return LoadCategoryArrayFromTxtFile(path.c_str(), catfield, cats, delim) ;
1190 }
1191 inline NP* NPX::LoadCategoryArrayFromTxtFile(const char* path, int catfield, const char* cats, char delim )
1192 {
1193 const char* str = U::ReadString2(path);
1194 if(str == nullptr) return nullptr ;
1195 NP* a = CategoryArrayFromString(str, catfield, cats, delim );
1196 return a ;
1197 }
1198
1199 inline void NPX::Import_MSD( std::map<std::string, double>& msd, const NP* a)
1200 {
1201 assert( a && a->uifc == 'f' && a->ebyte == 8 );
1202 assert( a->shape.size() == 1 );
1203 assert( NP::INT(a->names.size()) == a->shape[0] );
1204
1205 const double* vv = a->cvalues<double>() ;
1206 unsigned num_vals = a->shape[0] ;
1207
1208 for(unsigned i=0 ; i < num_vals ; i++)
1209 {
1210 const std::string& key = a->names[i] ;
1211 const double& val = vv[i] ;
1212 msd[key] = val ;
1213 }
1214 }
1215
1216 inline NP* NPX::Serialize_MSD( const std::map<std::string, double>& msd )
1217 {
1218 typedef std::map<std::string, double> MSD ;
1219 MSD::const_iterator it = msd.begin();
1220
1221 std::vector<std::string> keys ;
1222 std::vector<double> vals ;
1223
1224 for(unsigned i=0 ; i < msd.size() ; i++)
1225 {
1226 const std::string& key = it->first ;
1227 const double& val = it->second ;
1228
1229 keys.push_back(key);
1230 vals.push_back(val);
1231
1232 std::advance(it, 1);
1233 }
1234
1235 NP* a = MakeValues( keys, vals );
1236 return a ;
1237 }
1238
1239 inline std::string NPX::Desc_MSD(const std::map<std::string, double>& msd)
1240 {
1241 std::stringstream ss ;
1242 ss << "NPX::Desc_MSD" << std::endl ;
1243
1244 typedef std::map<std::string, double> MSD ;
1245 MSD::const_iterator it = msd.begin();
1246 for(unsigned i=0 ; i < msd.size() ; i++)
1247 {
1248 const std::string& key = it->first ;
1249 const double& val = it->second ;
1250 ss << " key " << key << " val " << val << std::endl ;
1251 std::advance(it, 1);
1252 }
1253 std::string s = ss.str();
1254 return s ;
1255 }
1256
1257 inline NP* NPX::ArrayFromEnumMap( const std::map<int, std::string>& catMap)
1258 {
1259 unsigned num_cat = catMap.size() ;
1260 NP* a = NP::Make<int>(num_cat);
1261 int* aa = a->values<int>() ;
1262 typedef std::map<int, std::string> MIS ;
1263 MIS::const_iterator it = catMap.begin();
1264
1265 for(unsigned i=0 ; i < num_cat ; i++)
1266 {
1267 aa[i] = it->first ;
1268 a->names.push_back(it->second) ;
1269 std::advance(it, 1);
1270 }
1271 return a ;
1272 }
1273
1274 inline NP* NPX::MakeCharArray( const std::vector<std::string>& nn )
1275 {
1276 NP::INT ni = NP::INT(nn.size());
1277 NP::INT maxlen = 0 ;
1278 for(NP::INT i=0 ; i < ni ; i++) maxlen = std::max( NP::INT(strlen(nn[i].c_str())), maxlen ) ;
1279 NP::INT nj = maxlen + 1 ;
1280
1281 NP* a = NP::Make<char>(ni, nj) ;
1282 char* aa = a->values<char>() ;
1283 for(NP::INT i=0 ; i < ni ; i++) for(NP::INT j=0 ; j < nj ; j++) aa[i*nj+j] = nn[i].c_str()[j] ;
1284 return a ;
1285 }
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300 template<typename F, typename T>
1301 inline NP* NPX::BOA( NP* a, NP* b, NP::INT a_column, NP::INT b_column, std::ostream* out )
1302 {
1303 if(out) *out
1304 << "NPX::BOA"
1305 << " A " << ( a ? a->sstr() : "-" )
1306 << " B " << ( b ? b->sstr() : "-" )
1307 << "\n"
1308 ;
1309
1310 bool abort = a == nullptr || b == nullptr ;
1311 if(abort && out) *out << "NPX::BOA ABORT A or B null \n" ;
1312 if(abort) return nullptr ;
1313
1314 assert( a->shape.size() == 2 );
1315 assert( b->shape.size() == 2 );
1316
1317 NP::INT a_ni = a->shape[0] ;
1318 NP::INT b_ni = b->shape[0] ;
1319
1320 if(a->names.size() == 0) for(NP::INT i=0 ; i < a_ni ; i++) a->names.push_back( U::FormName_("A", i, nullptr )) ;
1321 if(b->names.size() == 0) for(NP::INT i=0 ; i < b_ni ; i++) b->names.push_back( U::FormName_("B", i, nullptr )) ;
1322
1323 assert( NP::INT(a->names.size()) == a_ni );
1324 assert( NP::INT(b->names.size()) == b_ni );
1325
1326 bool samelength = a_ni == b_ni ;
1327 if(!samelength && out) *out << "NPX::BOA ABORT as not same length a_ni " << a_ni << " b_ni " << b_ni << "\n" ;
1328 if(!samelength) return nullptr ;
1329
1330 NP::INT ni = a_ni ;
1331
1332 NP::INT a_nj = a->shape[1] ;
1333 NP::INT b_nj = b->shape[1] ;
1334
1335 const T* aa = a->cvalues<T>();
1336 const T* bb = b->cvalues<T>();
1337
1338 NP::INT c_ni = ni ;
1339 NP::INT c_nj = 4 ;
1340
1341 NP* c = NP::Make<F>(c_ni, c_nj);
1342 c->set_meta<std::string>("creator", "NPX::BOA");
1343 c->set_meta<int>("a_column", a_column );
1344 c->set_meta<int>("b_column", b_column );
1345
1346 F* cc = c->values<F>();
1347
1348 c->labels = new std::vector<std::string>(c_nj) ;
1349 (*c->labels)[0] = "A" ;
1350 (*c->labels)[1] = "B" ;
1351 (*c->labels)[2] = "B/A" ;
1352 (*c->labels)[3] = "A/B" ;
1353
1354 for(NP::INT i=0 ; i < ni ; i++)
1355 {
1356 T av = aa[i*a_nj+a_nj+a_column] ;
1357 T bv = bb[i*b_nj+b_nj+b_column] ;
1358 F boa = F(bv)/F(av);
1359 F aob = F(av)/F(bv);
1360
1361 cc[i*c_nj+0] = F(av) ;
1362 cc[i*c_nj+1] = F(bv) ;
1363 cc[i*c_nj+2] = boa ;
1364 cc[i*c_nj+3] = aob ;
1365
1366 const char* an = a->names[i].c_str() ;
1367 const char* bn = b->names[i].c_str() ;
1368 std::string name = U::FormName_(bn,":", an );
1369 c->names.push_back(name) ;
1370 }
1371 return c ;
1372 }
1373
1374
1375
1376
1377
1378
1379