LabTalk的介绍

1. 什么是LabTalk?

LabTalk 是 OriginPro 原生脚本语言。

2. LabTalk能干什么?

通过 LabTalk, 可以方便地进行自定义操作, 例如列值计算, 自定义拟合函数, 批量处理等。

3. 如何运行LabTalk?

  • 脚本窗口(窗口: 脚本窗口)

  • 命令窗口(窗口: 命令窗口)

  • 代码编译器(Code Builder,自定义程序按钮,查看: 代码编译器)

  • 设置列值对话框

  • 自定义拟合函数

  • 等等

例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 运行文件中的Main节
run.section(Custom, Main); // Custom.ogs在用户文件夹下,不用指定路径,也不需要文件后续(.ogs)
run.section(%YCustom.ogs, Main); // 也可以指定文件的全路径,%Y为用户文件夹的字符串存储器
// 运行文件
run.file(MyLabTalk);
run.file(%YMyLabTalk.ogs);

//第一个例子代码:

// 激活窗口中的book1
window -a book1; // 命令语句
newsheet name:=shifted cols:=11; // X-function
colcopy irng:=1!1:2 orng:=2!1:2; // X-function

for (int i = 3; i <= 11; i++)
{
range r1 = 2!2, r1i = 1!$(i), r2i = 2!$(i); // 命名范围,替换记法,对象
int id1 = list(max(r1), r1); // LabTalk 函数
int idi = list(max(r1i), r1i); // LabTalk 函数
int offset = idi - id1 + 1;
range rresult = 1![];
r2i = rresult;
r2i.lname$ = r1i.lname$; // 对象属性
r2i.unit$ = r1i.unit$; // 对象属性
r2i.comment$ = r1i.comment$; // 对象属性
}

基本特性

1. 数据类型与变量

有九种数据类型:

double, int, constant, dataset, string, stringarray, range, tree, Graphic Object等

Numeric

  • int在LabTalk中是按double类型存储的
  • constant一旦声明,就会保存在System Variable中,新的session也可以调用它
    • 想要在新的session中使用constant,需要在CONST.CNF文件下定义这个constant
  • 没有复数形式,如需要可以使用Origin C
  • 0,NANUM, -1.0E-290到1.0E-290之间的值会在逻辑上判定为False
1
2
type $(-1e-290?1:0); // Returns 0 (False)
type $(1/0?1:0); // Returns 0 (False), where 1/0 == NANUM

Dataset

  • 该类型存储数字类型的array

2. 字符串变量

定义:双引号不是必须的

1
string s = hello world; 

美元符号($)在定义时可有可无,在赋值时是必须的

1
2
3
4
5
6
7
string str1$ = "hello world";
string str2 = str1;
str2$ = ;
// str1
string str3 = str1$;
str3$ = ;
// hello world
  • 赋值给另外一个变量时,在后面加上$,如str1 = s$
  • 调用字符串时,需要在后面加上$

字符串寄存器:

%H --> 当前处于活动状态的窗口名称

%X --> 当前项目所在目录

%Y --> 用户文件夹

3. 语法

赋值语句,宏语句,命令语句,运算语句,函数语句

分号的使用:;

注释://, /* */

操作符:运算操作符,字符串连接,赋值操作符,逻辑关系操作符,条件操作符

条件语句:if, if else, switch, break, exit, continue

循环语句:repeat, loop, doc -e, for

对象

语法:

对象名.属性

对象名.方法(参数列表)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
page.= // 查看对象的属性 

// 层级包含关系
// page -> worksheet -> column

page.active = // 当前窗口处于活动状态的表,可以查看,也可以设置
page.nlayers = // 有几个工作表

wks.ncols = // 工作表有几列
wks.addcol() // 调用对象的方法,工作表中添加列
wks.name$ = // 工作表的名称

wks.col2.lname$ = // 工作表第二列的长名称
wks.col2.unit$ = // 工作表第二列的单位

// 对当前工作簿窗口的所有工作表执行相应的代码
doc -e LW {
wks.ncols = 4; // 每个工作表都设置成4列
}

// 对当前图形窗口的所有图层执行相应的代码
doc -e LW {
layer.y.from = -1; // y轴刻度从-1开始
layer.y.to = 48; // y轴刻度结束于48
}

命令

语法:

命令 [-选项] [参数列表]

1
2
3
4
5
6
7
8
9
10
11
12
newbook; // X-Function,新建工作簿 
string FileString$ = system.path.program$ + "Samples\Curve Fitting\Linear Fit.dat";
open -a %(FileString$); // 打开数据,-a为选项,%(FileString$)为参数

// 运行Python命令
run -py print("Hello Origin");

// 对特定的对象群体执行给定的脚本
// document -e object { script }
doc -e W { // doc与document一样, W是项目里的所有工作表
type %H; // 打印工作表的名称
}

命名范围

语法:

range [-选项] RangeName = RangeString

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
range rb = [Book2]; // 命名范围为Book2这个工作簿 
range rs = [Book2]Sheet1!; // 命名范围为Book2这个工作簿下的Sheet1工作表
range rc1 = [Book2]Sheet1!col(1); // 工作表下的第一列
range rc2 = [Book2]Sheet1![]; // 工作表下A列的1至5行
range rc3 = [Book2]1![]; // 同上,这里用了索引的方式,第一个工作表的第一列

// 复制整列数据到另一个工作表
range r1 = [Book3]Sheet1!col(1);
range r2 = [Book4]Sheet1!col(2);
r2 = r1;

// 循环每列,复制数据和长名称
win -a Book2; // 激活Book2为当前窗口
newsheet; // 当前工作簿里新建一个工作表
for (i = 1; i <= 5; i++) { // 从1循环到5
range r1 = Sheet1![],第一列的第一行到最后一行
range r2 = Sheet2!$(i); // 第二个工作表的第i列
r2 = r1; // 复制数据
r2.lname$ = r1.lname$; // 复制长名称
}

替换记法

%A-%Z

字符串寄存器是最简单的替换,在脚本执行过程中,寄存器被产生的内容替换。

1
2
3
4
FDLOG.open(A);  // 打开的文件名存于%A
%A = ;
%B = FDLOG.path$; // 文件所在目录存于%B
%B = ;

%( )

用于解析出%(str$),%(range),工作表信息,列名,单元格,图例等。

1
2
3
4
5
6
string str$ = Book5; 
range r1 = [%(str$)]1![]1!1;
type %(r1); // 解析出r1

%([Book5]Sheet1, 3, 2) = ; // 解析出Book5里的Sheet1工作表中的第三列第二行
%([Book5]Sheet1, 5, 1) = %([Book5]Sheet1, 3, 2) * 2;

$( )

用于把数字表达式替换为相应的数字字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
dataset ds1 = {1, 3, 5, 7}; // 定义数据集 
type $(ds1); // 打印
type $(ds1, *2); // 两位有效数字

loop (ii, 1, 4) { // 循环从1到4
wks.col$(ii).lname$ = col$(ii); // 设置当前工作表的1到4列的长名称
}

// 历遍项目里的所有工作簿和矩阵簿里的所有工作表和矩阵表
doc -e LB {
loop (var, 1, [%H]!wks.ncols) { // 当前历遍表中的所有列循环
type "此列为:[%H]%(page.active$)!%(wks.col$(var).name$)";
}
}
/*
此列为:[Book5]Sheet1!A
此列为:[Book5]Sheet1!B
此列为:[Book5]Sheet1!C
此列为:[Book5]Sheet1!D
此列为:[Book5]Sheet1!E
此列为:[Book5]Sheet2!A
此列为:[Book5]Sheet2!B
*/

%n

用于给宏和脚本传递参数,n为整数,为1-5,即最多可传递5个参数。

1
2
3
4
def my_add {type -b "(%1 + %2) = $(%1 + %2)"}  // 定义一个宏
my_add 100 11; // 调用宏,并传递两个参数,100由%1处理,11由%2处理

run.section(Custom, Main, 100 11); // 注意传递的参数是空格分隔,不是逗号

X-Function

X-Function 是 Origin 里的一个框架,可以用于创建执行特定任务的工具。大部分 X-Function 都可以通过 LabTalk 脚本来运行。

Origin 里很多分析工具都是通过 X-Function 来实现的,包括在学习中心里的很多APP,也是由 X-Function 来做的。

1
2
3
4
5
6
win -a Book6; // 先把Book6设置为当前活动窗口 
// 平滑
for (int ii = 2; ii <= 4; ii++) { // 从2到4历遍
range rr = $(ii); // 定义命名范围为当前工作表的第ii列,这里用到了$( )的替换法来定义
smooth -r 2 iy:=rr; // 调用smooth这个X-Function,-r 2是选项,iy:=rr是参数
}

如何生成脚本?

1
2
newsheet -d; // -d选项可以打开对话框,然后在对话框里有相应的生成脚本的方式 
smooth -d;

注意:有些 X-Function 设计时并不允许打开对话框,此时使用-d会出错!

查找X-Function及帮助文档

1
2
3
lx *norm*; // 查找带norm这几个字符的X-Function 
help smooth; // 打开smooth的帮助文档,是打开chm还是在线文档,取决于 帮助: 使用在线帮助文档 是否选中
smooth -h; // 直接显示文档内容

宏和函数

宏的定义与调用

1
2
3
4
5
6
7
// 语法  
define macroName { script } // define可简写成def
// 例子
def helloOrigin { // 定义一个叫helloOrigin的宏
type -b "Hello Origin";
}
helloOrigin; // 调用宏

内置函数

1
2
3
4
5
6
7
8
9
10
11
// 数值类的函数 
win -a Book7; // 激活Book7工作簿
range ra = col(A);
range rb = col(B);
rb = ave(ra, 5); // 调用ave函数

// 字符串类的函数
win -a Book8; // 激活Book8工作簿
range ra = col(A);
range rb = col(B);
rb = token(ra, 1, ","); // 调用token函数

自定义函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 语法 
function dataType funcName(Arg1, Arg2, ..., ArgN) { script; }

// 例子
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;
}
win -a Book9; // 激活Book9工作簿
iVal = iCountDays(col(1), 6); // 调用
iVal = ;

实用例子

使用模板批量绘图

1
2
3
4
5
6
7
8
9
10
run.section(dofile.ogs, OnInstallTemplate, "%XTemplatForBatch.otpu");  // 安装模板
// run.section(dofile.ogs, OnUnInstallTemplate, "%XTemplatForBatch.otpu"); // 卸载模板
win -a Book10; // 激活Book10
string bookName$ = %H; // 保存好Book10的名称
for (int ii = 1; ii <= 3; ii++) { // 有三个工作表要历遍
string wksName$ = bookName$!layer$(ii).name$; // 拿到当前工作表的名字
plotxy iy:=[%(bookName$)]%(wksName$)![]; // 在模板的第一个图层画图
plotxy iy:=[%(bookName$)]%(wksName$)!(1,3) plot:=200 ogl:=2; // 在第二个图层画
plotxy iy:=[%(bookName$)]%(wksName$)!(1,4) plot:=200 ogl:=3; // 在第三个图层画
}

批量峰值分析

Book11的Sheet1工作表中的数据,从迷你图可以看到,C、E、F这三列Y数据,噪音比较多,不适合做峰值分析(会产生很多不准确的峰值),而现在又想对工作表中的Y数据进行峰值分析的批量处理,同时要把噪音过大的过滤掉,如何做?

1.生成主题

  1. 选中B列,然后点菜单 分析: 峰值及基线: 峰值分析。
  2. 目标为峰拟合,在寻峰步骤,点 查找,然后下一步,再保存主题,关闭。

2.通过主题批量峰值分析

  1. 点菜单 分析: 峰值及基线: 通过主题批量峰值分析。

  2. 输入选择所有列,主题为刚保存的主题,结果表为峰属性。

  3. 在脚本的每次处理前运行脚本里输入改下脚本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    dataset dr; // 定义一个数据集变量 
    fft_filters iy:=_ry filter:=high oy:=dr; // FFT高通滤波,可以获得噪音分量,_ry对应批处理时当前处理的y数据,输出结果噪音放到dr
    stats dr sd:=nSD; // 对噪音进行统计分析,并取得噪音的标准差放到变量nSD
    stats _ry sd:=sSD; // 对信号进行统计分析,并取得标准差放到变量sSD
    if (nSD^2 > sSD^2 * 0.3) { // 对比噪音的方差与信号的方差,如果噪音的方差大于信号方差的0.3倍,则认为此信号噪音太大,不适合做峰分析,跳过此信号
    _skip=1; // _skip此变量标志是否要跳过当前的数据不处理
    } else {
    _skip=0; // _skip为0,则表示当前数据不跳过,会被处理
    }
  4. 点确定按钮。

工作本脚本

1.工作表脚本

  1. 新建一个工作簿。

  2. 点菜单 工作表: 工作表脚本,打开工作表属性对话框。

  3. 在脚本选项卡下,在脚本触发条件框中,勾上两个复选框,并在第二个复选框下填上:1:end,表示任意数据的变动都触发。

  4. 脚本则使用下面的脚本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    wks.userParam1 = 1; // 显示第一个用户自定义参数行 
    wks.userParam2 = 1; // 显示第二个用户自定义参数行
    wks.userParam1$ = "均值"; // 设置第一个用户自定义参数行为均值
    wks.userParam2$ = "标准差"; // 设置第二个用户自定义参数行为标准差
    for (int ii = 2; ii <= wks.ncols; ii++) { // 第二列开始历遍工作表中的所有列
    range rr = $(ii); // 取得第ii列的命名范围
    col($(ii))[D1]$ = $(mean(rr), .2*); // 计算第ii列的均值,并把值取小数后两位放到自定义参数均值行
    col($(ii))[D2]$ = $(stddev(rr), .2*); // 计算第ii列的标准差,并把值取小数后两位放到自定义参数标准差行
    }
  5. 导入一个数据看结果。

2.导入多个ASCII文件

  1. 打开导入多个ASCII文件对话框,选择多个要导入的ASCII文件。
  2. 在脚本分支下,把上面用过的同样的脚本复制粘贴到每个文件导入后运行脚本的文本框中。
  3. 点确定按钮。