从脚本中读取TDM(Diadem)文件

时间:2010-07-13 06:38:49

标签: file matlab file-conversion

我的客户正在发送在National Instruments Diadem中捕获的TDM / TDX文件,这是我没有得到的。我正在寻找一种方法将文件转换为.CSV,XLS或.MAT文件,以便在Matlab中进行分析(不使用Diadem或Diadem DLL!)

格式由结构良好的XML文件(.TDM)和二进制(.TDX)组成,.TDM定义如何将字段打包为二进制TDX中的位。我想阅读这些文件(用于Matlab和其他环境)。有没有人在例如Python或Perl(不使用NI DLL)或直接在Matlab中使用通用工具或转换脚本?

我已经考虑购买该工具,但除了一次性转换为兼容的文件格式之外,我不喜欢它。

谢谢!

3 个答案:

答案 0 :(得分:5)

我知道这有点晚了,但我有一个简单的库来读取Python中的TDM / TDX文件。它的工作原理是解析TDM文件以找出数据类型,然后使用NumPy.memmap打开TDX文件。然后它可以像标准的NumPy数组一样使用。代码非常简单,所以你可以在Matlab中实现类似的东西。

以下是链接:https://bitbucket.org/joshayers/tdm_loader

希望有所帮助。

答案 1 :(得分:2)

可能有点太晚了,但我认为有一种简单的方法可以从TDM文件中获取数据:NI提供了将TDM文件读入Excel和OpenOffice Calc的插件。拥有其中一个程序中的数据,您可以使用CSV导出。在谷歌搜索“tdm excel”或“tdm openoffice”。

希望这会有所帮助...... Gemue

答案 2 :(得分:0)

以下脚本可以将所有变量转换为“变量”结构。

    CurrDirectory = '...//';  % Path to current directory
    fileNametdx = '.../utility/';  % Path to TDX file
    %%
    % Data type conversion 
    Dtype.eInt8Usi='int8';
    Dtype.eInt16Usi='int16';
    Dtype.eInt32Usi='int32';
    Dtype.eInt64Usi='int64';
    Dtype.eUInt8Usi='uint8';
    Dtype.eUInt16Usi='uint16';
    Dtype.eUInt32Usi='uint32';
    Dtype.eUInt64Usi='uint64';
    Dtype.eFloat32Usi='single';
    Dtype.eFloat64Usi='double';

    %% Read .tdx file Name
    wb=waitbar(0,'Reading *.tdx Files');
    fileNameTDM = strrep(fileNametdx,'.tdx','.TDM');

    %% Read .TDM
    tdm=xml2struct(fileNameTDM);

    for i=1:numel(tdm.usi_colon_tdm.usi_colon_data.tdm_channel)

        waitbar((1/numel(tdm.usi_colon_tdm.usi_colon_data.tdm_channel))*i,wb,['File ' fileNametdx ' conversion started']);
    s1=strsplit(string(tdm.usi_colon_tdm.usi_colon_data.tdm_channel{1, i}.local_columns.Text),'"');
    usi1=s1(2);

    % if condition match untill we get usi2
    for j=1:numel(tdm.usi_colon_tdm.usi_colon_data.localcolumn)
    usi2=string(tdm.usi_colon_tdm.usi_colon_data.localcolumn{1, j}.Attributes.id);
    if usi1==usi2
        %take new usi
        s2=strsplit(string(tdm.usi_colon_tdm.usi_colon_data.localcolumn{1, j}.values.Text),'"');
        new_usi1=s2(2);


        w1=strsplit(string(tdm.usi_colon_tdm.usi_colon_data.tdm_channel{1, i}.datatype.Text),'_');
        str_1=char(strcat('tdm.usi_colon_tdm.usi_colon_data.',lower(w1(2)),'_sequence'));
        str_2=char(strcat('tdm.usi_colon_tdm.usi_colon_data.',lower(w1(2)),'_sequence{1, k}.Attributes.id'));
        str_3=char(strcat('tdm.usi_colon_tdm.usi_colon_data.',lower(w1(2)),'_sequence{1, k}.values.Attributes.external'));
        str_4=char(strcat('tdm.usi_colon_tdm.usi_colon_data.',lower(w1(2)),'_sequence{1, k}.values'));
        for k=1:numel(eval(str_1))
        new_usi2=string(eval(str_2));
         if new_usi1==new_usi2
             if isfield(eval(str_4), 'Attributes')

             inc_value1=string(eval(str_3));

                    for m=1:numel(tdm.usi_colon_tdm.usi_colon_include.file.block)
                        inc_value2=string(tdm.usi_colon_tdm.usi_colon_include.file.block{1, m}.Attributes.id);
                        if inc_value1==inc_value2

        %                 offset=round(str2num(tdm.usi_colon_tdm.usi_colon_include.file.block{1, m}.Attributes.byteOffset)/8);
                        length = round(str2num(tdm.usi_colon_tdm.usi_colon_include.file.block{1, m}.Attributes.length));
                        offset1=round(str2num(tdm.usi_colon_tdm.usi_colon_include.file.block{1, m}.Attributes.byteOffset));
                        value_type = tdm.usi_colon_tdm.usi_colon_include.file.block{1, m}.Attributes.valueType;

                        m = memmapfile(fullfile(CurrDirectory,fileNametdx),'Offset',offset1,'Format',{Dtype.(value_type) [length 1] 'dat'},'Writable',true,'Repeat',1);
                        dat=m.Data.dat  ;

                        end
                    end
             else

                 str_5=char(strcat('tdm.usi_colon_tdm.usi_colon_data.',lower(w1(2)),'_sequence{1, k}.values.',char(fieldnames(tdm.usi_colon_tdm.usi_colon_data.string_sequence{1, k}.values))));
                 dat=eval(str_5)';
             end
                    name_variable = string(tdm.usi_colon_tdm.usi_colon_data.tdm_channel{1, i}.name.Text);
                    varname = genvarname(char(name_variable));
                    variable.(varname) = dat;
         end
        end
    end
    end
    end

    waitbar(1,wb,[fileNametdx ' conversion completed']);
    pause(1)
    close(wb)
    delete(fullfile(CurrDirectory,fileNametdx),fullfile(CurrDirectory,fileNameTDM));
    %Output Variable is Struct 
    clearvars -except variable

此脚本需要以下 XML 解析器

function [ s ] = xml2struct( file )
    %Convert xml file into a MATLAB structure
    % [ s ] = xml2struct( file )
    %
    % A file containing:
    % <XMLname attrib1="Some value">
    %   <Element>Some text</Element>
    %   <DifferentElement attrib2="2">Some more text</Element>
    %   <DifferentElement attrib3="2" attrib4="1">Even more text</DifferentElement>
    % </XMLname>
    %
    % Will produce:
    % s.XMLname.Attributes.attrib1 = "Some value";
    % s.XMLname.Element.Text = "Some text";
    % s.XMLname.DifferentElement{1}.Attributes.attrib2 = "2";
    % s.XMLname.DifferentElement{1}.Text = "Some more text";
    % s.XMLname.DifferentElement{2}.Attributes.attrib3 = "2";
    % s.XMLname.DifferentElement{2}.Attributes.attrib4 = "1";
    % s.XMLname.DifferentElement{2}.Text = "Even more text";
    %
    % Please note that the following characters are substituted
    % '-' by '_dash_', ':' by '_colon_' and '.' by '_dot_'
    %
    % Written by W. Falkena, ASTI, TUDelft, 21-08-2010
    % Attribute parsing speed increased by 40% by A. Wanner, 14-6-2011
    % Added CDATA support by I. Smirnov, 20-3-2012
    %
    % Modified by X. Mo, University of Wisconsin, 12-5-2012

        if (nargin < 1)
            clc;
            help xml2struct
            return
        end

        if isa(file, 'org.apache.xerces.dom.DeferredDocumentImpl') || isa(file, 'org.apache.xerces.dom.DeferredElementImpl')
            % input is a java xml object
            xDoc = file;
        else
            %check for existance
            if (exist(file,'file') == 0)
                %Perhaps the xml extension was omitted from the file name. Add the
                %extension and try again.
                if (isempty(strfind(file,'.xml')))
                    file = [file '.xml'];
                end

                if (exist(file,'file') == 0)
                    error(['The file ' file ' could not be found']);
                end
            end
            %read the xml file
            xDoc = xmlread(file);
        end

        %parse xDoc into a MATLAB structure
        s = parseChildNodes(xDoc);

    end

    % ----- Subfunction parseChildNodes -----
    function [children,ptext,textflag] = parseChildNodes(theNode)
        % Recurse over node children.
        children = struct;
        ptext = struct; textflag = 'Text';
        if hasChildNodes(theNode)
            childNodes = getChildNodes(theNode);
            numChildNodes = getLength(childNodes);

            for count = 1:numChildNodes
                theChild = item(childNodes,count-1);
                [text,name,attr,childs,textflag] = getNodeData(theChild);

                if (~strcmp(name,'#text') && ~strcmp(name,'#comment') && ~strcmp(name,'#cdata_dash_section'))
                    %XML allows the same elements to be defined multiple times,
                    %put each in a different cell
                    if (isfield(children,name))
                        if (~iscell(children.(name)))
                            %put existsing element into cell format
                            children.(name) = {children.(name)};
                        end
                        index = length(children.(name))+1;
                        %add new element
                        children.(name){index} = childs;
                        if(~isempty(fieldnames(text)))
                            children.(name){index} = text; 
                        end
                        if(~isempty(attr)) 
                            children.(name){index}.('Attributes') = attr; 
                        end
                    else
                        %add previously unknown (new) element to the structure
                        children.(name) = childs;
                        if(~isempty(text) && ~isempty(fieldnames(text)))
                            children.(name) = text; 
                        end
                        if(~isempty(attr)) 
                            children.(name).('Attributes') = attr; 
                        end
                    end
                else
                    ptextflag = 'Text';
                    if (strcmp(name, '#cdata_dash_section'))
                        ptextflag = 'CDATA';
                    elseif (strcmp(name, '#comment'))
                        ptextflag = 'Comment';
                    end

                    %this is the text in an element (i.e., the parentNode) 
                    if (~isempty(regexprep(text.(textflag),'[\s]*','')))
                        if (~isfield(ptext,ptextflag) || isempty(ptext.(ptextflag)))
                            ptext.(ptextflag) = text.(textflag);
                        else
                            %what to do when element data is as follows:
                            %<element>Text <!--Comment--> More text</element>

                            %put the text in different cells:
                            % if (~iscell(ptext)) ptext = {ptext}; end
                            % ptext{length(ptext)+1} = text;

                            %just append the text
                            ptext.(ptextflag) = [ptext.(ptextflag) text.(textflag)];
                        end
                    end
                end

            end
        end
    end

    % ----- Subfunction getNodeData -----
    function [text,name,attr,childs,textflag] = getNodeData(theNode)
        % Create structure of node info.

        %make sure name is allowed as structure name
        name = toCharArray(getNodeName(theNode))';
        name = strrep(name, '-', '_dash_');
        name = strrep(name, ':', '_colon_');
        name = strrep(name, '.', '_dot_');

        attr = parseAttributes(theNode);
        if (isempty(fieldnames(attr))) 
            attr = []; 
        end

        %parse child nodes
        [childs,text,textflag] = parseChildNodes(theNode);

        if (isempty(fieldnames(childs)) && isempty(fieldnames(text)))
            %get the data of any childless nodes
            % faster than if any(strcmp(methods(theNode), 'getData'))
            % no need to try-catch (?)
            % faster than text = char(getData(theNode));
            text.(textflag) = toCharArray(getTextContent(theNode))';
        end

    end

    % ----- Subfunction parseAttributes -----
    function attributes = parseAttributes(theNode)
        % Create attributes structure.

        attributes = struct;
        if hasAttributes(theNode)
           theAttributes = getAttributes(theNode);
           numAttributes = getLength(theAttributes);

           for count = 1:numAttributes
                %attrib = item(theAttributes,count-1);
                %attr_name = regexprep(char(getName(attrib)),'[-:.]','_');
                %attributes.(attr_name) = char(getValue(attrib));

                %Suggestion of Adrian Wanner
                str = toCharArray(toString(item(theAttributes,count-1)))';
                k = strfind(str,'='); 
                attr_name = str(1:(k(1)-1));
                attr_name = strrep(attr_name, '-', '_dash_');
                attr_name = strrep(attr_name, ':', '_colon_');
                attr_name = strrep(attr_name, '.', '_dot_');
                attributes.(attr_name) = str((k(1)+2):(end-1));
           end
        end
    end