Compose-3015:テキストファイルからのデータの読み取り

Tutorial Level: Beginner

このチュートリアルでは、LS-DYNAの入力ファイルtruck.keyからノード位置を抽出する方法を紹介します。このファイルは<install>/tutorials/にあります。

OMLには、文字列データ型を操作する各種コマンドが用意されています。文字列ツールとファイル読み取りコマンドを組み合わせることで、あらゆるテキストファイルからデータを読み取ることができます。

目的の変数の定義

  1. Composeを開始します。
  2. 新規スクリプトに次のコマンドを入力します。ファイルパスは、ファイルの実際の保存場所に応じて調整します。ベクトルnodeListには、x座標、y座標、z座標を読み取るノードのIDが記述されています。このIDのリストが数値の昇順で並べ替えられます。要求したすべてのデータを収めるうえで適切なサイズになるように、行列nodesInfoが初期化されます。
    fileName=‘<INSERT_PATH>/truck.key’;
    nodeList = [1, 211, 57, 5];
    nodeList = sort(nodeList);
    nodeInfo = zeros(length(nodeList),3);

ファイルを読み取るための一般的な構造の作成

次のコードでは、読み取り対象のファイルを開き、一度に1行ずつすべての行をファイルの最後まで読み取った後、ファイルを閉じます。whileループ本体には、行ごとに実行するコマンド群が記述されています。現在のところ、このコマンドはファイルにある次の行を読み取る命令のみです。追加するコマンドを次のステップで紹介しますが、ここに示したコードだけでも、あらゆるファイルを十分に読み取ることができます。これらの行をスクリプトに追加して、そのスクリプトファイルを実行し、正常に実行されたことを示すメッセージが表示されることを確認します。
[fid, message] = fopen(fileName, 'r');
line = fgetl(fid);
while ~feof(fid)
  line = fgetl(fid);
end
disp('Finished reading the file')

データ行を解析する制御構造の追加

  1. 入力ファイルの構造には、いわゆるブロック形式でノードデータが記述されています。データのブロックは固有のキーワードで示され(LS-DYNAでは先頭の文字が‘*’)、別のキーワードが現れるまで、以降の行にデータが記述されます。ノードデータの先頭にはキーワード*NODEが記述されています。ノードデータブロックの中では、行ごとに所定のノードの情報が記述されます。行の先頭8文字はノードIDで、次に続く3つの16文字は、それぞれx座標値、y座標値、z座標値を表して1つのグループを形成します。最初に追加する論理制御は、現在、コードの読み手が*NODEブロックを扱っているかどうかの判断です。この目的で、直近で読み取られたキーワードが*NODEであるかどうかをテストするためにブール変数nodeOnを作成します。最初は、この変数にデフォルト値のfalseを定義します。while制御ブロックの前に次のコマンドを入力します。
    nodeOn = false;
  2. whileブロックの中で、このブール変数の状態をテストするための制御を読み取りコマンドの前に追加します。最初は、nodeOnの値はfalseです。現在の行にテキスト*NODEが使用されていると、この状態がtrueに変化します。文字列検索コマンドの詳細については、リファレンスガイドでstrfindに関するトピックをご参照ください。この例では、検索との一致が見つからなかった場合に、このコマンドから空の値が返されることがわかれば十分です。
    if nodeOn == true
        %process node data line
    else
        search = strfind(line,'*NODE')
        if ~isempty(search)
            nodeOn = true;
        end
    end

要求されたノードデータの処理と保存

  1. ノードブロックにあるデータ行を処理する際に、取り扱う必要がある状況として(1)‘$’で示されたコメント行をスキップする、(2)新しいブロックの開始を示すキーワードが行データにある場合、その前のブロックが終了することを識別する、(3)ノードデータを処理する、の3種類が考えられます。(1)にも(2)にも該当しない状況では(3)の処理が必要です。nodeOn == trueブロックに次のコードを配置することで、これら3種類の状況が適切に取り扱われます。
    search=strfind(line,’$’);
    if ~isempty(search)
            line = fgetl(fid);
            continue;
    end
    search = strfind(line,'*');
    if ~isempty(search)
        nodeOn = false;
    else
        %proper node line
    End
  2. ノード行の処理で最初に必要な手順はノードIDの判断です。この情報は行の先頭8文字に記述されているので、loopコマンドを使用して抽出できます。このコマンドからは値が文字列として返されるので、str2num関数を使用してデータ型を数値に変換する必要があります。このノードIDを、ベクトルnodeListにリストで記述されたIDと比較します。この比較にはeq functionコマンドを使用し、1のベクトル(true)が返されればIDの各エントリが一致しています。0のベクトル(false)が返されれば、IDは一致していません。このベクトルに1があれば(この1は迅速に合算できます)、現在のノードIDが要求されたIDであることを示しています。次のコードを入力して、スクリプトにこの論理を追加します。
    node = str2num(line(1:8));
    boolean = eq(nodeList,node);
    if sum(boolean)  > 0
         %store this node’s data
    end
  3. 最後に、要求されたIDがノードにあれば、次のコードを使用して、x座標、y座標、z座標の各フィールドからデータを抽出し、行列nodeInfoに保存できます。次の行を追加してスクリプトを保存し、実行します。nodeInfoに保存された値をテキストファイルのデータと比較します。
    x = str2num(line(9:24));
    y = str2num(line(25:40));
    z = str2num(line(41:56));
    for ix = 1:length(nodeList) 
       if boolean(ix) == 1
             nodeInfo(ix,:) = [ x, y, z];
       end
    end
  4. スクリプト全体については<installation folder>/tutorials/にあるread_txt.txtをご参照ください。