Program Listing for File DataLogger.h#
↰ Return to documentation for file (include/Karana/KUtils/DataLogger.h)
/*
*Copyright(c)2024-2026KaranaDynamicsPtyLtd.Allrightsreserved.
*
*NOTICETOUSER:
*
*Thissourcecodeand/ordocumentation(the"LicensedMaterials")is
*theconfidentialandproprietaryinformationofKaranaDynamicsInc.
*UseoftheseLicensedMaterialsisgovernedbythetermsandconditions
*ofaseparatesoftwarelicenseagreementbetweenKaranaDynamicsandthe
*Licensee("LicenseAgreement").Unlessexpresslypermittedunderthat
*agreement,anyreproduction,modification,distribution,ordisclosure
*oftheLicensedMaterials,inwholeorinpart,toanythirdparty
*withoutthepriorwrittenconsentofKaranaDynamicsisstrictlyprohibited.
*
*THELICENSEDMATERIALSAREPROVIDED"ASIS"WITHOUTWARRANTYOFANYKIND.
*KARANADYNAMICSDISCLAIMSALLWARRANTIES,EXPRESSORIMPLIED,INCLUDING
*BUTNOTLIMITEDTOWARRANTIESOFMERCHANTABILITY,NON-INFRINGEMENT,AND
*FITNESSFORAPARTICULARPURPOSE.
*
*INNOEVENTSHALLKARANADYNAMICSBELIABLEFORANYDAMAGESWHATSOEVER,
*INCLUDINGBUTNOTLIMITEDTOLOSSOFPROFITS,DATA,ORUSE,EVENIF
*ADVISEDOFTHEPOSSIBILITYOFSUCHDAMAGES,WHETHERINCONTRACT,TORT,
*OROTHERWISEARISINGOUTOFORINCONNECTIONWITHTHELICENSEDMATERIALS.
*
*U.S.GovernmentEndUsers:TheLicensedMaterialsarea"commercialitem"
*asdefinedat48C.F.R.2.101,andareprovidedtotheU.S.Government
*onlyasacommercialenditemunderthetermsofthislicense.
*
*AnyuseoftheLicensedMaterialsinindividualorcommercialsoftwaremust
*include,intheuserdocumentationandinternalsourcecodecomments,
*thisNotice,Disclaimer,andU.S.GovernmentUseProvision.
*/
//Turnformattingofftoavoidchangingtheorderoftheseincludes.
//clang-formatoff
#include"hdf5.h"
//clang-formaton
#include"H5PTpublic.h"
#include"Karana/KCore/LockingBase.h"
#include"Karana/KCore/UsageTrackingMap.h"
#include"Karana/Math/Defs.h"
#include<Eigen/Core>
#include<cstring>
#include<format>
#include<functional>
#include<typeindex>
namespaceKarana::KUtils{
namespacekc=Karana::Core;
namespacekm=Karana::Math;
template<typenameT>
structis_eigen_type:std::false_type{};//NOLINT(readability-identifier-naming)
template<intRows,intCols>
structis_eigen_type<Eigen::Matrix<double,Rows,Cols,Eigen::RowMajor>>:std::true_type{};
template<intRows>structis_eigen_type<Eigen::Matrix<double,Rows,1>>:std::true_type{};
template<typenameT>inlineconstexprboolis_eigen_type_v=is_eigen_type<T>::value;
template<typenameT>
structis_eigen_vector:std::false_type{};//NOLINT(readability-identifier-naming)
template<intRows>structis_eigen_vector<Eigen::Matrix<double,Rows,1>>:std::true_type{};
template<typenameT>inlineconstexprboolis_eigen_vector_v=is_eigen_vector<T>::value;
template<typenameT>
structextract_matrix_dimensions{//NOLINT(readability-identifier-naming)
staticconstexprintrows=-1;
staticconstexprintcols=-1;
};
template<int_rows>structextract_matrix_dimensions<Eigen::Matrix<double,_rows,1>>{
staticconstexprintrows=_rows;
staticconstexprintcols=1;
};
template<int_rows,int_cols>
structextract_matrix_dimensions<Eigen::Matrix<double,_rows,_cols,Eigen::RowMajor>>{
staticconstexprintrows=_rows;
staticconstexprintcols=_cols;
};
template<typenameT>constexprintextract_rows_v=extract_matrix_dimensions<T>::rows;
template<typenameT>constexprintextract_cols_v=extract_matrix_dimensions<T>::cols;
template<typenameT>structextract_rows{//NOLINT(readability-identifier-naming)
staticconstexprintvalue=-1;//Defaultcase(shouldnevermatch)
};
template<introws>structextract_rows<Eigen::Matrix<double,rows,1>>{
staticconstexprintvalue=rows;
};
template<typenameT>constexprintextract_vector_rows_v=extract_rows<T>::value;
//ForwarddeclareH5Writer
classH5Writer;
classPacketTableConfig:publickc::LockingBase{
friendH5Writer;
public:
PacketTableConfig(std::string_viewname);
statickc::ks_ptr<PacketTableConfig>create(std::string_viewname);
~PacketTableConfig();
template<classT>
requiresstd::same_as<std::invoke_result_t<T>,km::Vec>
voidaddData(std::string_viewname,constT&f,intvector_size,boolas_scalars=false){
//Ensurethisisnothealthy.
ensureNotHealthy();
if(as_scalars){
for(intk=0;k<vector_size;k++){
_h5_types.push_back(H5T_NATIVE_DOUBLE);
_names.emplace_back(std::format("{}_{}",name,k));
_offsets.push_back(_offset+k*sizeof(double));
}
}else{
hsize_tdims[1]{hsize_t(vector_size)};
_h5_types.push_back(H5Tarray_create2(H5T_NATIVE_DOUBLE,1,dims));
_names.emplace_back(name);
_offsets.push_back(_offset);
}
size_tsize=vector_size*sizeof(double);
_funcs.push_back([f,offset=_offset,size](char*buf){
km::Vecval=f();
void*dark=val.data();
std::memcpy(buf+offset,dark,size);
});
//Incrementtheoffsetforthenextfunction.
_offset+=size;
}
template<classT>
requiresstd::same_as<std::invoke_result_t<T>,km::Mat>
voidaddData(std::string_viewname,
constT&f,
intmatrix_rows,
intmatrix_cols,
boolas_scalars=false){
//Ensurethisisnothealthy.
ensureNotHealthy();
if(as_scalars){
for(intj=0;j<matrix_rows;j++){
for(intk=0;k<matrix_cols;k++){
_h5_types.push_back(H5T_NATIVE_DOUBLE);
_names.emplace_back(std::format("{}_{}_{}",name,j,k));
_offsets.push_back(_offset+(j*matrix_cols+k)*sizeof(double));
}
}
}else{
hsize_tdims[2]{hsize_t(matrix_rows),hsize_t(matrix_cols)};
_h5_types.push_back(H5Tarray_create2(H5T_NATIVE_DOUBLE,2,dims));
_names.emplace_back(name);
_offsets.push_back(_offset);
}
size_tsize=matrix_rows*matrix_cols*sizeof(double);
_funcs.push_back([f,offset=_offset,size](char*buf){
km::Matval=f();
void*dark=val.data();
std::memcpy(buf+offset,dark,size);
});
//Incrementtheoffsetforthenextfunction.
_offset+=size;
}
template<classT,classR=typenamestd::invoke_result<T>::type>
requires(is_eigen_type_v<R>andis_eigen_vector_v<R>)
voidaddData(std::string_viewname,constT&f,boolas_scalars=false){
//Ensurethisisnothealthy.
ensureNotHealthy();
constexprintrows=extract_rows_v<R>;
static_assert(rows!=Eigen::Dynamic,
"Vectormusthaveafixedsize(nodynamicrows).Foradynamicvector,"
"usetheaddDatasignaturethattakesinanintegerforthenumberrows"
"asanextraargument.");
if(as_scalars){
for(intk=0;k<rows;k++){
_h5_types.push_back(H5T_NATIVE_DOUBLE);
_names.emplace_back(std::format("{}_{}",name,k));
_offsets.push_back(_offset+k*sizeof(double));
}
}else{
hsize_tdims[1]{hsize_t(rows)};
_h5_types.push_back(H5Tarray_create2(H5T_NATIVE_DOUBLE,1,dims));
_names.emplace_back(name);
_offsets.push_back(_offset);
}
//Createacopytostoreinthenewfunction
size_tsize=rows*sizeof(double);
_funcs.push_back([f,offset=_offset,size](char*buf){
Eigen::Matrix<double,rows,1>val=f();
void*dark=val.data();
std::memcpy(buf+offset,dark,size);
});
//Incrementtheoffsetforthenextfunction.
_offset+=size;
}
template<classT,classR=typenamestd::invoke_result<T>::type>
requires(is_eigen_type_v<R>andnotis_eigen_vector_v<R>)
voidaddData(std::string_viewname,constT&f,boolas_scalars=false){
//Ensurethisisnothealthy.
ensureNotHealthy();
constexprintrows=extract_rows_v<R>;
constexprintcols=extract_rows_v<R>;
static_assert(rows!=Eigen::Dynamicandcols!=Eigen::Dynamic,
"Matrixmusthaveafixedsize(nodynamicrowsorcolumns).Fora"
"dynamicmatrix,usetheaddDatasignaturethattakesinintegersfor"
"therowsandcolumnsofadynamicmatrixasextraarguments.");
if(as_scalars){
for(intj=0;j<rows;j++){
for(intk=0;k<cols;k++){
_h5_types.push_back(H5T_NATIVE_DOUBLE);
_names.emplace_back(std::format("{}_{}_{}",name,j,k));
_offsets.push_back(_offset+(j*cols+k)*sizeof(double));
}
}
}else{
hsize_tdims[2]{hsize_t(rows),hsize_t(cols)};
_h5_types.push_back(H5Tarray_create2(H5T_NATIVE_DOUBLE,2,dims));
_names.emplace_back(name);
_offsets.push_back(_offset);
}
size_tsize=rows*cols*sizeof(double);
_funcs.push_back([f,offset=_offset,size](char*buf){
Eigen::Matrix<double,rows,cols,Eigen::RowMajor>val=f();
void*dark=val.data();
std::memcpy(buf+offset,dark,size);
});
//Incrementtheoffsetforthenextfunction.
_offset+=size;
}
template<classT,classR=typenamestd::invoke_result<T>::type>
requires(notis_eigen_type_v<R>)
voidaddData(std::string_viewname,constT&f){
//Ensurethisisnothealthy.
ensureNotHealthy();
autoit=_h5TypeMap.find(typeid(R));
if(it==_h5TypeMap.end()){
throwstd::runtime_error(std::format("CannotstoreH5datafor\"{}\".",name));
}
_h5_types.push_back(it->second);
_names.emplace_back(name);
//Createacopytostoreinthenewfunction
size_toffset=_offset;
size_tsize=sizeof(R);
_offsets.push_back(offset);
_funcs.push_back([f,offset,size](char*buf){
Rval=f();
void*dark=&val;
std::memcpy(buf+offset,dark,size);
});
//Incrementtheoffsetforthenextfunction.
_offset+=size;
}
voidfillBuf();
protected:
void_makeHealthy();
void_makeNotHealthy();
private:
//Thedatatypeofthepackettable.
hid_t_data_type;
//Buffertoholdthetabledata
char*_buf=nullptr;
std::vector<std::function<void(char*buf)>>_funcs;
std::vector<std::string>_names;
std::vector<hid_t>_h5_types;
std::vector<size_t>_offsets;
size_t_offset=0;
staticconststd::unordered_map<std::type_index,hid_t>_h5TypeMap;
};
classH5Writer:publickc::Base{
public:
H5Writer(std::string_viewfilename);
statickc::ks_ptr<H5Writer>create(std::string_viewfilename);
~H5Writer();
voidcreateTable(constkc::ks_ptr<PacketTableConfig>&config);
voidlog();
voidlogTable(conststd::string&name);
voidactivateTable(conststd::string&name);
voiddeactivateTable(conststd::string&name);
std::vector<std::string>getActiveTableNames();
std::vector<std::string>getTableNames();
private:
hid_t_file;
kc::UsageTrackingMap<hid_t, PacketTableConfig>_tables;
std::map<hid_t,kc::ks_ptr<PacketTableConfig>>_active_tables;
std::unordered_map<std::string,hid_t>_table_names;
std::vector<std::function<void()>>_fns_on_close;
std::unordered_set<hid_t>_ids_to_close;
};
}//namespaceKarana::KUtils