関数

関数は、ほとんどのプログラミング言語の中核的なものです。以下は、LabTalkでの関数のシンタックスと用法についての説明です。

組み込み関数

LabTalkは、 組み込み関数を使って、多くの操作をサポートしています。関数の一覧およびそれぞれの説明は、関数リファレンスにあります。 関数は、次のようなシンタックスで呼ばれます。

outputVariable = FunctionName(Arg1, Arg2, ..., Arg N);

以下は、組み込み関数の使用例です。

Count (関数) は、ベクターデータ内の要素の数を整数で返します。

// アクティブなワークシートの列Aにある要素の数を返す
int cc = count(col(A));

Ave (関数) は、データセットのグループの平均を計算し、range変数で結果を返します。

range ra = [Book1]Sheet1!Col(A);
range rb = [Book1]Sheet1!Col(B);
// グループの平均値を返す
rb = ave(ra, 5);    // 5 = グループサイズ

Sin (関数) は、入力角度のsinをdouble型で返します。(入力角度の単位は、system.math.angularunitsの値で決まります。)

system.math.angularunits=1;  // 1 = 度数で入力
double dd = sin(45);         // ANS: DD = 0.7071

ユーザ定義関数

複数の引数を持つユーザ定義関数がOrigin8.1からサポートされました。ユーザ定義関数のシンタックスは次の通りです。

function dataType funcName(Arg1, Arg2, ..., ArgN) {script;}

必要なOriginのバージョン:8.6 SR0

Note:

  1. 関数名は42文字以下の必要があります。
  2. 引数と戻り値は、string, double, int, dataset, tree のデータ型をサポートしています。引数のデフォルトデータ型はdoubleです。戻り値のデフォルトデータ型は intです。
  3. デフォルトでユーザ定義関数の引数は値で渡され、関数内のその引数の値は、関数の外部では利用できません。  しかし、リファレンスで渡す引数は、関数内部で引数の値に変わり、関数の外部でも利用できます。外部で利用するにはREFというキーワードを使います。

数値関数を使った簡単なサンプルがあります。

// この関数は数値の3乗根を計算する
function double dCubeRoot(double dVal)
{
    double xVal;
    if(dVal<0) xVal = -exp(ln(-dVal)/3);
    else xVal = exp(ln(dVal)/3);
    return xVal;
}
// 次のようになる
dcuberoot(-8)=;

以下の関数は、データセットの幾何平均を計算します。

function double dGeoMean(dataset ds)
{
    double dG = ds[1]; 
    for(int ii = 2 ; ii <= ds.GetSize() ; ii++)
        dG *= ds[ii]; // データセット内の全ての値が掛け算される
    return exp(ln(dG)/ds.GetSize());
}
// 引数はデータセットを返すもの
dGeoMean(col("Raw Data"))=;

この例は、範囲を引数で受け付けて、その範囲内のデータの平均を返す関数を定義します。

//  範囲の平均を計算
function double dsmean(range ra)
{
   stats ra;
   return stats.mean;
}
// アクティブブックの最初のシートの
// すべての列を指定する範囲を渡す
range rAll = 1!(1:end);
dsMean(rAll)=;

この例は、日付データセット内の特定の曜日の出現を数える関数を定義します。

function int iCountDays(dataset ds, int iDay)
{
    int iCount = 0;
    for(int ii = 1 ; ii <= ds.GetSize() ; ii++)
    {
        if(weekday(ds[ii], 1) == iDay) iCount++;
    }
    return iCount;
}
// ここでは、金曜日を数える
iVal = iCountDays(col(1),6); // weekday(data, 1)で6は金曜日
iVal=;

関数は、データセットを返すこともできます。

// データセットから負の値のみ取得
function dataset dsSub(dataset ds1)
{
    dataset ds2;
    int iRow = 1;
    for(int ii = 1 ; ii <= ds1.GetSize() ; ii++)
    {
        if(ds1[ii] < 0)
        {
            ds2[iRow] = ds1[ii];
            iRow++;
        }
    }
    return ds2;
}
// 列1の負の値すべてを列2に割り当て
col(2) = dsSub(col(1));

または文字列を返します。

// サブ文字列が現れるデータセット内のすべての値を取得
function string strFind(dataset ds, string strVal)
{
    string strTest, strResult;
    for( int ii = 1 ; ii <= ds.GetSize() ; ii++ )
    {
        strTest$ = ds[ii]$;
        if( strTest.Find(strVal$) > 0 )
        {
            strResult$ = %(strResult$)%(CRLF)%(strTest$);
        }
    }
    return strResult$;
}
// "hadron"が現れる列3のすべてのインスタンスを取得
string MyResults$ = strFind(col(3),"hadron")$; //「$」記号で終わる事に注意
MyResults$=;

リファレンスで引数を渡す

この例は、tree ノードの値を整数(int)(tree変数の1要素)として返す関数を示します。 さらに、リファレンスで渡すことは、REFキーワードを使って示しています。

// 関数定義
Function int GetMinMax(range rr, ref double min, ref double max) {
  stats rr;
  //stats Xファンクションを実行した後、同じ名前を持つ
  //LabTalkのtree変数を作成/更新
  min = stats.min;
  max = stats.max;
  return stats.N;
}
 
// GetMinMax関数を呼び、ワークシート全体に対する最小値と最大値を探す
double y1,y2;
int nn = getminmax(1:end,y1, y2);
type "Worksheet has $(nn) points, min=$(y1), max=$(y2)";

LabTalk関数でのツリー変数の使用と参照による変数渡しに関する詳細なサンプルを参照して下さい。

リファレンスで文字列の引数を渡す別のサンプルが以下にあり、これは関数呼び出しで、変数の最後に$を付けません。

//最初のシートの範囲文字列を返す
//実際の新しいブックのショートネームがName$で返される
Function string GetNewBook(int nSheets, ref string Name$)
{
        newbook sheet:= nSheets result:=Name$; 
        string strRange$ = "[%(Name$)]1!";     
        return strRange$;
}

上記関数を呼び出すとき、Name$引数が次に示すように、$記号を付けないことが重要です。

string strName$;
string strR$ = GetNewBook(1, strName)$;
strName$=;
strR$=;

データセット関数

Originは、double型の引数を受け付け、double型で返す数学関数もサポートしています。このような関数の一般的なシンタックスは次の通りです。

funcName(X) = expressionInvolvingX.

これらのデータセット関数が定義されるとき、これらを呼び出し、名前でデータセットが作成されます。 このデータセットは、関数と結びつき、Originプロジェクトの一部として保存されます。 一度定義したら、データセット関数は、名前で参照され、組み込み関数のように使用することができます。

例えば、スクリプトウィンドウに次のスクリプトを入力して、Salaryという関数を定義します。

Salary(x) = 52 * x

一度定義したら、この関数は次のような形式で呼び出すことができます。

Salary(100)=

これは、Salary(100)=5200のような結果となります。 この場合には、結果のデータセットは1つの要素のみを持ちます。 しかし、ベクターデータ(またはデータセット)が入力引数として渡されると、出力は入力時と同じ数の要素のデータセットとなります。

他のデータセットと同様、ユーザ定義のデータセット関数は、作図のセットアップのようなダイアログやレイヤnのようなダイアログ内の利用可能なデータ内に表示されます(そして、他のデータセットのようにプロットできます)。

関数が定義されたとき、2Dグラフレイヤがアクティブレイヤの場合、100ポイントのデータセットがX軸スケールを使って、X範囲として作成され、関数データセットが自動的にプロットレイヤに追加されます。

関数グラフテンプレート(FUNCTION.OTP, 標準ツールバーまたはファイル:新規作成からアクセス可能) も作成され、データセット関数をプロットします。

Originの関数グラフの機能は、新しいデータセット関数に組み込みおよびユーザ定義関数の組合せから簡単に作成できます。 さらに、新しく作成した関数はリファレンスに対してすぐにプロットされます。

この機能には2つのどちらかの方法でアクセスできます。

  1. 標準ツールバーの新しい関数ウィンドウボタンをクリックします。 Button New Function.png
  2. Originのドロップダウンメニューからファイル: 新規作成を選び、リストから関数を選び、OKをクリックします。

開いた作図の詳細ダイアログの関数タブに、F1(x) = 5*sin(x)+1 のように関数定義を入力し、OKをクリックします。関数がグラフにプロットされます。

グラフの新しい関数ボタンをクリックして、作図の詳細に別の関数を追加すれば、別の関数を定義できます。 OKを押すと、新しい関数プロットがグラフに追加されます。 他の関数に対しても行う場合には繰り返します。

フィット関数

多くの一般的な関数をサポートするだけでなく、Originは非線形曲線フィットで使用できる自分のフィット関数を作成することができます。 ユーザ定義のフィット関数は、新しいデータセットを生成するのに使われますが、それらを呼び出すのは、特別なシンタックスが必要です。

nlf_FitFuncName(ds, p1, p2, ..., pn)

ここで、フィット関数はFitFuncNameという名前で、dsは独立変数として使われるデータセット、p1--pn はフィット関数のパラメータです。

単純な例として、y切片と勾配が入力パラメータとなるMyLineという単純な直線のフィット関数を定義する場合、アクティブワークシートの列Cを独立変数、列Dを関数出力に使うには、次のように入力します。

// 切片 = 0, 傾き = 4
Col(D) = nlf_MyLine(Col(C), 0, 4)

関数のスコープ

ユーザー定義変数と同様に、ユーザ定義関数は制御可能なスコープを持ちます。ユーザ定義関数は、LabTalkスクリプトをサポートしている場所ならOriginプロジェクトのどこからでもアクセスでき、定義のスコープはこのような使用に適用できます。例えば、double型またはデータセットを返す@glob=1で定義された関数は、値の設定ダイアログの列の条件式で使うことができます。スコープについては、データ型と変数をご覧下さい。

  • プロジェクトのProjectEvents.OGS ファイルの中で、関数を定義することで、関数とプロジェクトを結びつけることができます。@glob=1を使用すると、プロジェクトを開くたびに関数が使用可能になります(このサンプル参照)。
  • 関数のスコープは、@glob=1を使用して関数を定義し、User FilesフォルダUFFの.ogsファイルに関数を保存して、ここで説明しているように、Origin.ini(UFF内)の[Startup]セクションから.ogsファイルを呼び出すことで、Originを実行するときにいつでも使用できるように拡張できます。

サンプル: 関数のスコープ

@glob=1を使用して、どこでも関数を呼び出せます。

[Main]
        @glob=1;  // 次の関数をセッションレベルとして定義
        function double dGeoMean(dataset ds)
        {
            double dG = ds[1]; 
            for(int ii = 2 ; ii <= ds.GetSize() ; ii++)
                dG *= ds[ii]; // データセット内の全ての値は全て掛け算する
            return exp(ln(dG)/ds.GetSize());
        }
        // [main]セクション内の関数を呼び出す
        dGeoMean(col(1))=;
[section1]
        // 関数はこのセクションでも呼び出せる
        dGeoMean(col(1))=;

関数が @glob=1なしで *.ogs ファイルに定義されている場合、そのセクション内でのみ呼び出せます。

[Main]
        function double dGeoMean(dataset ds)
        {
            double dG = ds[1]; 
            for(int ii = 2 ; ii <= ds.GetSize() ; ii++)
                dG *= ds[ii]; // データセット内の全ての値は全て掛け算する
            return exp(ln(dG)/ds.GetSize());
        }
        // [main]セクション内の関数を呼び出す
        dGeoMean(col(1))=;
[section1]
        // 関数はこのセクションでは呼び出せない
        dGeoMean(col(1))=;  // an error: 未特定の関数

@glob=1を使用しないでブロック内で定義されると、そのブロックの外では呼び出せません。

[Main]
{  // 括弧内の関数を定義
        function double dGeoMean(dataset ds)
        {
            double dG = ds[1]; 
            for(int ii = 2 ; ii <= ds.GetSize() ; ii++)
                dG *= ds[ii]; // データセット内の全ての値は全て掛け算する
            return exp(ln(dG)/ds.GetSize());
        }
}
        // 括弧の外では関数を呼び出すことはできない
        dGeoMean(col(1))=;  // エラー:  未特定の関数

チュートリアル: 複数の関数機能を使う

次のミニチュートリアルは、Originのプロジェクトレベルにユーザ定義関数を追加し、その関数を使って関数グラフを作成する方法を示しています。

  1. 新しいプロジェクトを開始し、表示:コードビルダメニューから、コードビルダを開きす。
  2. 左側のツリーパネルのProjectブランチを開き、ProjectEvents.OGS ファイルをダブルクリックして開きます。このファイルはデフォルトで新しいプロジェクトに存在しています。
  3. [AfterOpenDoc] セクションの下に次のコード行を追加します。
    @glob=1;
    Function double myPeak(double x, double x0)
    {
    double y = 10*exp(-(x-x0)^2/4);
    return y;
    }
  4. ファイルを保存し、コードビルダを閉じます。
  5. Originで、プロジェクトを希望の場所に保存します。OGSファイルがプロジェクトと一緒に保存され、ユーザ定義関数がプロジェクト内で利用できるようになります。
  6. 保存したプロジェクトを再び開きます。これがきっかけとなり、[AfterOpenDoc] セクションが実行され、myPeak 関数が定義されます。
  7. 標準ツールバーの新しい関数ウィンドウボタンをクリックします。
  8. 開いた作図の詳細ダイアログの関数タブに、
    F1(x) = myPeak(x, 3)
    のように関数定義を入力し、OKをクリックします。関数がグラフにプロットされます。
  9. グラフの新しい関数ボタンをクリックして、
    F2(x) = myPeak(x, 4)
    のような式を使って、作図の詳細に別の関数を追加して、OKをクリックします。
  10. 2番目の関数プロットがグラフに追加されます。
  11. 再びプロジェクトを保存し、再度開きます。2つの関数プロットは、プロジェクトと一緒に保存されたユーザ定義関数を参照しているので、これらは利用可能になっています。
  12. 一度Originを終了してから、再びOriginを起動します。プロジェクトを再び実行し、myPeak 関数がプロジェクトをロードしたときに定義されることをチェックすることで、本当に上記の動作が行われるかを自分で確認することができます。