9 Commits
v0.3 ... v0.4

Author SHA1 Message Date
7284314fcb README: fix example hyperref 2021-02-01 09:35:06 +01:00
fbbf202a58 README: fix usage link 2021-01-27 16:56:04 +01:00
52b41ed9a8 README: fix usage link 2021-01-27 16:54:52 +01:00
9afc1958f9 README: add TOC header 2021-01-27 16:53:18 +01:00
ef17897ece README: table of contents 2021-01-27 16:51:53 +01:00
66ad358abc fix docu hyperlink 2021-01-27 10:33:38 +01:00
35439dc987 * add custom.py to README
* Cython: add column_header to print_group
* tdm_reaper.cpp/.hpp: allow for custom header and default header with
ids
* add custom.py as example
* fix minimal.py/usage.py to run successfully by default
2021-01-27 10:30:29 +01:00
855cd3adf6 fix column structure for print_group() => issue #5 2021-01-27 09:07:21 +01:00
c54784bb5b submit_files: clear all members 2021-01-27 08:50:06 +01:00
8 changed files with 121 additions and 29 deletions

View File

@@ -16,7 +16,14 @@ _technical data management_ data model. The TDM format was introduced by
[LabVIEW](https://www.ni.com/de-de/shop/labview.html), LabWindows™/CVI™, [LabVIEW](https://www.ni.com/de-de/shop/labview.html), LabWindows™/CVI™,
Measurement Studio, SignalExpress, and [DIAdem](https://www.ni.com/de-de/shop/data-acquisition-and-control/application-software-for-data-acquisition-and-control-category/what-is-diadem.html). Measurement Studio, SignalExpress, and [DIAdem](https://www.ni.com/de-de/shop/data-acquisition-and-control/application-software-for-data-acquisition-and-control-category/what-is-diadem.html).
## Data Format ## Overview
* [TDM file format](#Dataformat)
* [Build and Installation](#Installation)
* [Usage and Examples](#Usage)
* [References](#References)
## Dataformat
Datasets encoded in the TDM/TDX format come along in pairs comprised of a Datasets encoded in the TDM/TDX format come along in pairs comprised of a
.tdm (header) and a .tdx (data) file. While the .tdm file is a human-readable .tdm (header) and a .tdx (data) file. While the .tdm file is a human-readable
@@ -267,7 +274,7 @@ for grp in grpids :
print("failed to print channelgroup: " + str(grp) + " : " + str(e)) print("failed to print channelgroup: " + str(grp) + " : " + str(e))
``` ```
For a full example including more details see [python/usage.py](python/usage.py) For a full example including more details see the [extensive example](python/usage.py)
and the absolute minimal example [minimal usage](python/minimal.py). In order and the absolute minimal example [minimal usage](python/minimal.py). In order
to simply extract all data of the TDM datatset and dump it to files in a given to simply extract all data of the TDM datatset and dump it to files in a given
(existing!) directory, do (existing!) directory, do
@@ -275,9 +282,13 @@ to simply extract all data of the TDM datatset and dump it to files in a given
```Python ```Python
import tdm_reaper import tdm_reaper
jack = tdm_reaper.tdmreaper(b'samples/SineData.tdm',b'samples/SineData.tdx') jack = tdm_reaper.tdmreaper(b'samples/SineData.tdm',b'samples/SineData.tdx')
jack.write_all(b"./my_tdm_data/") jack.write_all(b"./my_tdm_data_directory/")
``` ```
The interface allows to construct customized file/column headers from any
meta-data and provide these headers for usage in file output (see the
[example](python/custom.py)).
## References ## References
### TDM ### TDM

View File

@@ -36,9 +36,9 @@ cdef class tdmreaper:
return jn.loads(chnstr.decode()) return jn.loads(chnstr.decode())
# print a channel(-group) # print a channel(-group)
def print_channelgroup(self, string id, const char* filename, def print_channelgroup(self, string id, const char* filename, bool include_meta,
bool include_meta, char delimiter): char delimiter, string column_header):
self.cpp_tdm.print_group(id,filename,include_meta,delimiter) self.cpp_tdm.print_group(id,filename,include_meta,delimiter,column_header)
def print_channel(self, string id, const char* filename, def print_channel(self, string id, const char* filename,
bool include_meta): bool include_meta):
self.cpp_tdm.print_channel(id,filename,include_meta) self.cpp_tdm.print_channel(id,filename,include_meta)
@@ -48,4 +48,4 @@ cdef class tdmreaper:
grpids = self.cpp_tdm.get_channelgroup_ids() grpids = self.cpp_tdm.get_channelgroup_ids()
for id in grpids : for id in grpids :
grpfile = outputdir.decode() + "/channelgroup_" + id.decode() + ".csv" grpfile = outputdir.decode() + "/channelgroup_" + id.decode() + ".csv"
self.cpp_tdm.print_group(id,grpfile.encode(),True,ord(',')) self.cpp_tdm.print_group(id,grpfile.encode(),True,ord(','),"".encode())

View File

@@ -24,5 +24,6 @@ cdef extern from "tdm_reaper.hpp":
string get_channelgroup_info(string id) except+ string get_channelgroup_info(string id) except+
string get_channel_info(string id) except+ string get_channel_info(string id) except+
# print a channel(-group) # print a channel(-group)
void print_group(string id, const char* filename, bool include_meta, char delimiter) except+ void print_group(string id, const char* filename, bool include_meta,
char delimiter, string column_header) except+
void print_channel(string id, const char* filename, bool include_meta) except+ void print_channel(string id, const char* filename, bool include_meta) except+

View File

@@ -22,6 +22,14 @@ void tdm_reaper::submit_files(std::string tdmfile, std::string tdxfile, bool sho
tdmfile_ = tdmfile; tdmfile_ = tdmfile;
tdxfile_ = tdxfile; tdxfile_ = tdxfile;
// reset and clear all members
tdx_blocks_.clear();
tdmchannelgroups_.clear();
tdmchannels_.clear();
submatrices_.clear();
localcolumns_.clear();
tdxbuffer_.clear();
// start processing tdm data model // start processing tdm data model
this->process_tdm(showlog); this->process_tdm(showlog);
} }
@@ -690,7 +698,8 @@ void tdm_reaper::print_channel(std::string &id, const char* filename, bool inclu
} }
} }
void tdm_reaper::print_group(std::string &id, const char* filename, bool include_meta, char sep) void tdm_reaper::print_group(std::string &id, const char* filename, bool include_meta,
char sep, std::string column_header)
{ {
// check required path // check required path
this->check_filename_path(filename); this->check_filename_path(filename);
@@ -716,6 +725,7 @@ void tdm_reaper::print_group(std::string &id, const char* filename, bool include
int width = 25; int width = 25;
// file header
if ( include_meta ) if ( include_meta )
{ {
// group meta data // group meta data
@@ -773,6 +783,30 @@ void tdm_reaper::print_group(std::string &id, const char* filename, bool include
allchns.push_back(chndat); allchns.push_back(chndat);
} }
// provide column header (with channel ids)
if ( column_header.empty() )
{
for ( std::string chn: chngrp.channels_ )
{
// use given csv separator token
if ( sep == ' ' )
{
fou<<std::setw(width)<<std::left<<chn;
}
else
{
fou<<chn;
}
if ( chn != chngrp.channels_.back() && sep != ' ' ) fou<<sep;
}
}
else
{
fou<<column_header;
}
fou<<"\n";
// write data
for ( unsigned int row = 0; row < maxrows; row++ ) for ( unsigned int row = 0; row < maxrows; row++ )
{ {
for ( unsigned int chi = 0; chi < chngrp.channels_.size(); chi++ ) for ( unsigned int chi = 0; chi < chngrp.channels_.size(); chi++ )
@@ -789,19 +823,8 @@ void tdm_reaper::print_group(std::string &id, const char* filename, bool include
fou<<allchns.at(chi).at(row); fou<<allchns.at(chi).at(row);
} }
} }
else
{
if ( sep == ' ' )
{
fou<<std::setw(width)<<std::left<<"";
}
else
{
fou<<sep;
}
}
if ( chi+1 < chngrp.channels_.size() ) fou<<sep; if ( chi+1 < chngrp.channels_.size() && sep != ' ' ) fou<<sep;
} }
fou<<"\n"; fou<<"\n";
} }

View File

@@ -39,13 +39,13 @@ class tdm_reaper
// tdm meta-data // tdm meta-data
tdm_meta meta_data_; tdm_meta meta_data_;
// blocks of data in .tdx file
std::map<std::string,block> tdx_blocks_;
// resconstruct "tdm_datatype.hpp: tdm_datatypes" as map to quickly map // resconstruct "tdm_datatype.hpp: tdm_datatypes" as map to quickly map
// "valueType"/"channel_datatype" to full datatype // "valueType"/"channel_datatype" to full datatype
std::map<std::string,tdm_datatype> tdmdt_name_, tdmdt_chan_; std::map<std::string,tdm_datatype> tdmdt_name_, tdmdt_chan_;
// blocks of data in .tdx file
std::map<std::string,block> tdx_blocks_;
// tdm root // tdm root
tdm_root tdmroot_; tdm_root tdmroot_;
@@ -54,6 +54,7 @@ class tdm_reaper
// tdm channels // tdm channels
std::map<std::string,tdm_channel> tdmchannels_; std::map<std::string,tdm_channel> tdmchannels_;
std::map<std::string,std::vector<tdm_datatype>> tdmchannels_data_;
// submatrices and local_columns // submatrices and local_columns
std::map<std::string,submatrix> submatrices_; std::map<std::string,submatrix> submatrices_;
@@ -238,7 +239,8 @@ public:
// dump a single channel/entire group (identified by id) to file // dump a single channel/entire group (identified by id) to file
void print_channel(std::string &id, const char* filename, bool include_meta = true); void print_channel(std::string &id, const char* filename, bool include_meta = true);
void print_group(std::string &id, const char* filename, bool include_meta = true, char sep = ' '); void print_group(std::string &id, const char* filename, bool include_meta = true,
char sep = ' ', std::string column_header = std::string(""));
void check_filename_path(const char* filename); void check_filename_path(const char* filename);
// check machine's datatypes // check machine's datatypes

50
python/custom.py Normal file
View File

@@ -0,0 +1,50 @@
import tdm_reaper
import json
import re
# create 'tdm_reaper' instance object
try :
jack = tdm_reaper.tdmreaper(b'samples/SineData.tdm',b'samples/SineData.tdx')
except RuntimeError as e :
print("failed to load/decode TDM files: " + str(e))
# list ids of channelgroups
grpids = jack.get_channelgroup_ids()
# iterate through group-ids
for grp in grpids[0:2] :
# obtain meta data of channelgroups
grpinfo = jack.get_channelgroup_info(grp)
print( json.dumps(grpinfo,sort_keys=False,indent=4) )
# get channel meta-data and compose header
column_header = ""
chns = grpinfo['channels'].split(' ')
for chn in chns :
# obtain channel's meta-data as dictionary (JSON)
chninfo = jack.get_channel_info(chn.encode())
# print( json.dumps(chninfo,sort_keys=False,indent=4) )
# choose e.g. channel-id and name to compose column header
chnhead = ( str(chninfo['channel-id']) + "("
+ str(chninfo['name']).replace(',',' ') + ")" )
# append to full header
column_header = column_header + chnhead + ","
# remove last comma
column_header = column_header[0:-1]
print("column_header:\n"+column_header+"\n")
# write channelgroup to file
try :
grpname = re.sub('[^A-Za-z0-9]','',grpinfo['name'])
grpfile = str("./channelgroup_") + str(grp.decode()) + "_" + str(grpname) + str(".csv")
jack.print_channelgroup(grp, # id of group to be written
grpfile.encode(), # filename
False, # no meta-data header
ord(','), # csv separator character
column_header.encode() # provide column header
)
except RuntimeError as e :
print("failed to print channelgroup: " + str(grp) + " : " + str(e))

View File

@@ -10,6 +10,11 @@ try :
for grp in grpids : for grp in grpids :
# write channelgroup to file (prepend './' for local directory!!) # write channelgroup to file (prepend './' for local directory!!)
grpfile = "./channelgroup_" + str(grp.decode()) + ".csv" grpfile = "./channelgroup_" + str(grp.decode()) + ".csv"
jack.print_channelgroup(grp,grpfile.encode(),True,ord(' ')) jack.print_channelgroup(grp, # id of group to be written
grpfile.encode(), # filename
False, # include meta-data fileheader?
ord(','), # csv separator character
b"" # (empty=default) column header
)
except RuntimeError as e : except RuntimeError as e :
print("failed to load/decode/write TDM files: " + str(e)) print("failed to load/decode/write TDM files: " + str(e))

View File

@@ -24,8 +24,8 @@ for grp in grpids[0:2] :
# write channelgroup to file # write channelgroup to file
try : try :
grpname = re.sub('[^A-Za-z0-9]','',grpinfo['name']) grpname = re.sub('[^A-Za-z0-9]','',grpinfo['name'])
grpfile = "channelgroup_" + str(grp) + "_" + str(grpname) + ".csv" grpfile = "./channelgroup_" + str(grp) + "_" + str(grpname) + ".csv"
jack.print_channelgroup(grp.encode(),grpfile.encode(),True,ord(' ')) jack.print_channelgroup(grp.encode(),grpfile.encode(),True,ord(' '),b'')
except RuntimeError as e : except RuntimeError as e :
print("failed to print channelgroup: " + str(grp) + " : " + str(e)) print("failed to print channelgroup: " + str(grp) + " : " + str(e))
@@ -49,7 +49,7 @@ for chn in chnids[0:2] :
print(str(chndata[0:6]) + " ...") print(str(chndata[0:6]) + " ...")
# write channel to file # write channel to file
chnfile = "channel_" + str(chn) + ".csv" chnfile = "./channel_" + str(chn) + ".csv"
try : try :
jack.print_channel(chn.encode(),chnfile.encode(),True) jack.print_channel(chn.encode(),chnfile.encode(),True)
except RuntimeError as e : except RuntimeError as e :