FileMaker 系统内提供了大量的函数,其中有一大类称为 Design,顾名思义就是设计用函数。

1

官方的说法:
Design functions return information about the structure of open database files. For example, you could determine the names of all the layouts or fields in an open database file.

也就是说,Design funciton 是用于提取数据库设计信息的工具。这对于快速获取一个不熟悉的数据库非常有用。我们甚至可以使用数据库保存这些函数返回的信息,用于追踪数据库设计的变化或撰写开发日志,乃至开发完整的 FileMaker 开发日志系统。

我们先来看看这类函数都有哪些。
DatabaseNames: A list of the names of all files open on the computer.
FieldBounds: The location, in points, of each field boundary and the field’s rotation in degrees.
FieldComment: The specified field’s comment.
FieldIDs: A list of all field IDs in fileName and layoutName.
FieldNames: A list of the names of all fields on layoutName in fileName.
FieldRepetitions: The number and orientation of repetitions of a repeating field as formatted on a layout.
FieldStyle: The field formatting applied to fieldName on layoutName in fileName.
FieldType: Information about fieldName.
GetNextSerialValue: The next serial number of fieldName in fileName.
LayoutIDs: A list of all layout IDs in fileName.
LayoutNames: A list of the names of all layouts in fileName.
LayoutObjectNames: A list of the names of all named objects on layoutName in fileName.
RelationInfo: A list of four values for each relationship directly related to tableName.
ScriptIDs: A list of all script IDs in fileName.
ScriptNames: A list of the names of all scripts in fileName.
TableIDs: A list of all table IDs in fileName.
TableNames: A list of all table occurrences in the relationships graph for fileName.

Get(LayoutTableName)

1
2
3
4
/*  copyright Ulf Carlsson, ulf.carlsson@studentlitteratur.se, free to use if this row is here
copyright Dawei Huang, daweih@me.com, free to use if this row is here
在原作的基础上增加了对重复出现布局名称情况的处理,会返回错误值 (-1)
Use: Gets the Layout-ID of current layout if parameter layout="current" or of the layout which name is in parameter layout Function name: GetLayoutID Parameter: layout If layout="current" is current layout used, otherwise should "layout" contain the name of wich layout ID you want */ Let ( [ // use "current" layout or the layoutname that is coming from the "layout"-parameter theLayout = If ( layout ="current" ; Get ( LayoutName ) ; layout ); // Get all the layout names (is a list) theLayoutNames = LayoutNames ( Get ( FileName ) ); // realLayoutNames realLayoutNames = Substitute ( theLayoutNames; ["-";""] ; ["¶¶";"¶"] ); // Count all ¶ from the start to where the layout name are and add 1 currentLayoutPosition = PatternCount ( Middle ( theLayoutNames ; 1 ; Position ( theLayoutNames ; theLayout ; 1 ; 1 ) ) ; "¶" ) + 1 ; // Get all the layout IDs (is a list) layoutIDs = LayoutIDs ( Get ( FileName ) ) ; // Count how many layouts there is numberOfLayouts = Get ( LayoutCount ) ; // Get the the ID from the list layoutID = Case ( //ValueCount ( UniqueValues ( realLayoutNames ) ) ≠ ValueCount ( realLayoutNames ); ValueCount ( FilterValues ( theLayoutNames ; theLayout ) )>1; "-1"; // If first value in the list, do this currentLayoutPosition = 1 ; LeftWords ( layoutIDs ; 1 ) ; // if not first or last item in the list, do this currentLayoutPosition < numberOfLayouts ; Middle ( layoutIDs ; Position ( layoutIDs ; "¶" ; 1 ; currentLayoutPosition -1 ) ; Position ( layoutIDs ; "¶" ; 1 ; currentLayoutPosition ) - Position ( layoutIDs ; "¶" ; 1 ; currentLayoutPosition -1 ) ) ; // If last item in the list, do this Middle ( layoutIDs ; Position ( layoutIDs ; "¶" ; 1 ; currentLayoutPosition -1 ) ; Length ( layoutIDs ) ) ) ]; GetAsNumber ( layoutID ) )

Reference

  1. title



由于开发 FileMaker 系统下的脚本编辑和执行功能,需要让 FileMaker 内置更友好的代码编辑功能。因此调研了一番之后,发现在线支持语法高亮的代码编辑器 CodeMirror 适合,也方便移植,因此入坑(官方介绍)。

本项目有个简单的实现在这里

部署

部署其实很简单 (以下代码不是真实的 Code Mirror):

1
2
<link rel="stylesheet" href="codemirror.css">
<script src="codemirror.js"></script>

接着引用需要显示的代码语言对应的 JS 库:

1
<script src="javascript.js"></script>
In FileMaker

在 FileMaker 内部引用,直接将代码提取到字段内,然后引用该字段,写入 web viewer 的代码区域即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
"data:text/html,"
&"<!DOCTYPE html><html><head><meta charset='utf-8' />"
& "<script charset='utf-8'>"
& ExecuteSQL ( "SELECT "
& RightValues ( Substitute ( GetFieldName ( WebPackages::code ) ; "::" ; ¶ ) ; 1 ) & " FROM "
& LeftValues ( Substitute ( GetFieldName ( WebPackages::code ) ; "::" ; ¶ ) ; 1 ) & " WHERE "
& RightValues ( Substitute ( GetFieldName ( WebPackages::Filename ) ; "::" ; ¶ ) ; 1 ) & "='codemirror.js' "; "" ; "" )
& "</script>"
& "<style type='text/css'>¶"
& ExecuteSQL ( "SELECT "
& RightValues ( Substitute ( GetFieldName ( WebPackages::code ) ; "::" ; ¶ ) ; 1 ) & " FROM "
& LeftValues ( Substitute ( GetFieldName ( WebPackages::code ) ; "::" ; ¶ ) ; 1 ) & " WHERE "
& RightValues ( Substitute ( GetFieldName ( WebPackages::Filename ) ; "::" ; ¶ ) ; 1 ) & "='codemirror.css' "; "" ; "" )
& "</style>"
& "<script charset='utf-8'>"
& ExecuteSQL ( "SELECT "
& RightValues ( Substitute ( GetFieldName ( WebPackages::code ) ; "::" ; ¶ ) ; 1 ) & " FROM "
& LeftValues ( Substitute ( GetFieldName ( WebPackages::code ) ; "::" ; ¶ ) ; 1 ) & " WHERE "
& RightValues ( Substitute ( GetFieldName ( WebPackages::Filename ) ; "::" ; ¶ ) ; 1 ) & "='"
& Case ( Script Editor » Scripts::dtLanguage="Perl Moudle" ; "perl" ; Lower ( Script Editor » Scripts::dtLanguage ) )
& ".js' "; "" ; "" )
& "</script>"

注意,这里采用了 SQL 语句调用存储在表 WebPackages 中的代码,为了保证代码的鲁棒性,中间的 SQL 语句嵌套了很多 FileMaker 函数,如果简单写,则是这样:

1
2
3
4
5
6
7
8
9
10
11
"data:text/html,"
& "<!DOCTYPE html><html><meta charset='utf-8' />"
& "<script charset='utf-8'>"
& ExecuteSQL ( "SELECT code FROM WebPackages WHERE Filename='codemirror.css' "; "" ; "" )
& "</script>"
& "<style type='text/css'>¶"
& ExecuteSQL ( "SELECT code FROM WebPackages WHERE Filename='codemirror.css' "; "" ; "" )
& "</style>"
& "<script charset='utf-8'>"
& ExecuteSQL ( "SELECT code FROM WebPackages WHERE Filename='perl.js' "; "" ; "" )
& "</script>"

将环境部署好之后,就可以调试功能了。加载脚本编辑器:

1
2
3
4
5
6
7
8
var editor = CodeMirror.fromTextArea(document.getElementById('code'), {
//options
lineNumbers: true,
matchBrackets: true,
lineWrapping: true,
indentUnit: 4
});
editor.setSize('auto', 'auto');

添加行号,折行(因为我们不希望 FileMaker 用户频繁地左右拖动,那个动作太反人类),让代码区域根据长度自动调整尺寸。

这个项目中采用了直接加载 DOM 中文本的模式加载数据,又有其他方法,比如使用上个语句块中 options 区域中的参数 value 传递。

更多参数
indentUnit

integer. 定义锁进的单位。个人比较喜欢制表符大小的锁进,4个空格。

theme

string. 配置编辑器的主题样式。个人感觉 ambiance 这个主题还是很好看的,如图:

1

smartIndent

boolean. 自动缩进: 是否根据上下文自动缩进,默认true。

lineNumbers

boolean. 是否在编辑器左侧显示行号。

undoDepth

integer. 最大撤消次数,默认为200。

Reference

  1. Code Mirror



似乎每次版本更新,FileMaker 都会给开发者带来一些“早就该有的”新功能。然而和 Apple Inc. 出 iPhone 的习惯一样,FileMaker 也不爱啰嗦把每次更新的内容说清楚,于是有了 Base64Decode 这个坑。

1

在开发解决方案时,常常需要将数据库内的数据导出。除了常用的导出通道(Export)之外,FileMaker 14 支持将数据保存为容器中的文件。导出容器中的文件是 FileMaker 已经支持的功能,也可以用脚本执行。这里有一个示例,演示在 13,14,15 上此功能的差别。采用的代码如下:

1
2
$ Set Field [ container::container ; Base64Decode ( Base64Encode ( GetAsText ( container::text ) );"demo.txt" ) ] 
$ Set Field [ container::File2Text ; Base64Decode ( Base64Encode ( container::container ) ) ]

可以看出,将字段内的数据直接导出为文件或从文件导入到字段,一个命令搞定,非常方便。下一步就可以用这个文件调用外部程序处理了,比如用插件 ScriptMaster 的运行脚本功能使用 perl 语言处理文本,会比 FileMaker 自带的脚本强大得多。基于这个设计,我做了 FileMakerScriptEditor 这个项目,可以在 FileMaker 内编辑脚本,运行脚本处理 FileMaker 内存储的数据。

2

目前,FileMaker 最新的发行版是 15。在这个平台下开发出来的解决方案常常遇到需要对旧版本适配的问题。比如我供职的公司,就有大量的用户还在使用 FileMaker 13。比如上述功能,就产生了不兼容。于是免不了到处搜寻bug……最终,针对 FileMakerScriptEditor,采用了先计算客户端版本,在判断为 13 后,选择用 ScriptMaster 替代 Base64Decode 实现了此功能。

此外,从文件导入内容到字段的功能,最常用的另一个方面是库内置包的更新。我们知道,FileMaker 在 14 及以后的版本中,对 javascript 的支持越来越好。我们常用的 JS 包如果内置在库内部,直接调用,会比调用外部的包稳定很多。采用对拖入容器(container)的包直接提取代码,可以简单地实现拖入包文件即升级系统 JS 的包代码。此外,拖入文本文件直接导入其中的数据也是很便捷的一个应用。

Reference

  1. Base64Decode
  2. FileMakerScriptEditor
  3. ScriptMaster




第一次看到 FileMaker 是在三里屯的苹果零售店里。当时中国刚开了第一家零售店。在货架上看到了 FileMaker 的盒装版。

当时已经是资深的 Mac 用户,对苹果的软件总喜欢研究以下。看到 Apple Inc. 自己子公司的产品,自然想尝试一番。不过在试用的一个月内,并没有产生太好的印象,现在想来,可能是因为当时做生物信息用脚本语言太过于随意,对这种刻板的商业化软件,是在是体会不不到好处。

后来再深入接触已经是博士毕业以后了,开始做一些面向多用户的产品,数据库和网站也做了一些,逐渐开始体会到数据整合、标准格式、协作的优势。

现在做 FileMaker 开发也有 3 年多,可以算得心应手吧。过去学的很多语言和技术也都逐渐在这个平台上应用起来。总体上,FileMaker 确实是上手容易的数据库平台,有着 Apple 一贯易用的特色。单进阶还是比较难的。而且中文的教材也很缺乏。在国内想成为 FileMaker 高手,英语水平是硬性的指标。

不过由于部署容易,有商业化系统的安全性,授权费用也不高,FileMaker 还是很适合开发中小型企业的信息化的解决方案。对于中小型企业,本身 IT 团队就小。特别是一些非 IT 类的研发型公司,如农业公司、销售公司、试剂公司,本身公司结构就比较扁平,用户群体庞大,开发者遇到的问题比较稀碎,但却有数据集中化的需求。其数据库的维护本身就是个难题。FileMaker 的服务器端部署非常容易,解决方案文件也很容易部署。从而可以让开发者专注于如何将工作流程转化为解决方案。

此外,由于开发便捷,FileMaker 也适合快速将研究型流程转化为标准化的高通量流程。比如在生物信息分析中,常遇到的一个问题就是各自为战的研究者的脚本如何整合,实验室的研究如何延续。通过 FileMaker 的脚本编辑和执行功能,就可以很好地解决这个问题;同时 FileMaker 也可以调用存储的脚本在服务器端执行。同一个数据库实现了数据的存储、流程的整合、实验日志的收集和数据的分析等多项功能。很适合作为分子生物学实验室的核心过程管理+数据管理系统。

Reference

  1. FileMaker Inc.
  2. 我写的一个 FileMaker 脚本编辑和执行工具



第一次去北海,还是 2007 年,我刚到帝都某研究生院就读。阴差阳错,换了个象牙塔,彼时,我的学术理想树立起来,只是还没有血肉。



记得是在和同学共游北海之前,第一次去挨着北海的中国美术馆看夕阳画展,当时纤细纯良,还没有感觉长发的邋遢和不整齐,尚尊敬自然如我师。第一次看高迪展,也是在那年夏天。

然后,8 年过去了。



第一次去看白塔,觉得无甚趣味,皇家园林看过许多,白塔都排不上号;此时依旧排不上,好在可以拍照发朋友圈。



荷花年年盛开,人的心态却不断变化。过去无所畏惧,现在更是;咽回那些并不怕说出口的话的原因,现在变成了懒得去絮叨。



颜值涨了一点点,对自拍的热爱增长了许多。



蓝天的日子变得屈指可数了(虽然并不记得 2007 年有多少天有蓝天,而且附近最近刚发生爆炸)。



花谢了结莲蓬,也好。



第一次出远门,家里只剩下一个人和两只鼠。被从实验室解救后,它们可还觉得滋润?

为了在 Hexo 系统的 markdown 正文中测试 D3 的可用性,移植了一个咖啡风味轮的可视化,如下:

Coffee Flavour Wheel

1
2
3
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<div align=center id="vis" style="font-size:13pt;font-family:helvetica;zoom:0.4;"></div>
<script src="http://daweih.github.io/js/coffee_flavour_wheel.js" charset="utf-8"></script>

代码注释:

  • 第一行装载 D3 包。
  • 第二行,插入绘图区域,这里的绘图区域是用 div#viz 来定位并操作
  • 第三行,引用绘图用代码,保存在 Hexo 博客系统的 js 文件夹下,会被同步到 github。当然你也可以通过用 <script></script> 直接嵌入本页。个人更推荐单独存放,避免 markdown 页面太长。

编写小贴士

  • 改动 md 文件后直接看效果:对 DOM 的 attrstyle 编写,更改无需 hexo d, hexo d,就可以在 hexo s 开启状态的浏览器中查看。写可视化代码时候,需要经常看改动带来的变化,此时可以省去前述的两步。
  • 在 md 文件中编写并测试 js 代码:使用 hexo s 测试中,代码需要写在页面内测试。测试完毕后再移动到独立文件。因为 gihub 处的代码改动需要 git commit, git push 之后才会生效。如果每次改动后都进行前面 2 项操作,则无妨。这里的问题在于,hexo s 状态下,无法引用本地的文件。这个问题在图片的引用代码中,也是让人不爽。
  • 模块化:重复使用的 js 代码,尽量放在一处,引用到每个页面,减少维护的复杂度。

目前,文章页面的 CSS 还是无法通过嵌入正文生效。需要 D3 直接写入 DOM 的属性。

D3 在本站嵌入成功后,我就可以做一些可视化的学习笔记。这样,在笔记里面,就可以添加实时的演示了。

本次嵌入的可视化来自这里

其他相关博文






本书的好处,不再多说。可以看这里这里

作为一个重度强迫症患者和整理狂人,读书要做的第一件事不言自明。

优化博客的笔记系统

本书是我第一本认真去读的管理类书籍。本着不作就不会死的精神,配置个让自己舒坦的笔记系统。

植入目录

使用了 OmniOutliner 来整理笔记,所以想直接嵌入到博客系统里。于是采用了 iframe



1
2
3
<div align=center>
<iframe scrolling="value" src="http://daweih.github.io/js/becoming_a_technical_leader.html/index.html" width=90% height=450px frameborder="0" scrolling="yes"></iframe>
</div>
  • 第 1 行:目录块在页面居中对齐
  • 第 2 行:目录文件采用嵌入方式进入博客文章,其文件是 OmniOutliner 生成的动态 html。

优化效果

为了让目录的效果在不同设备上达到一样的水准,以便长期使用,做了一些优化,有以下几点:

  1. width 采用了 90%是为了在 iPadiPhone 和电脑上都有比较好的显示效果;height 采用固定高度,为了避免页面过长。
  2. 为了缩放之后,iframe 内容依然可以居中,在 oo3 转化的网页中 table 根处添加属性:

    1
    <table align="center"
  3. 为了改进缩放,强制 oo3 转化的网页宽度为 310px,修改代码为:

    1
    2
    3
    4
    table.row {
    width: 310px;

    }

得到的目录效果如下。

本书目录



本周进度

周四、五非常忙,以至于周二拿到的书,只两天拿出时间来看。

本书在前言中说:

如果你真的希望提升行动力,应该首先制订计划,制订好计划之后应该按时执行……想要有时间做自己的事情,应当把一切事情保持在井然有序的状态……

我的评论:

  • 阅读的质量还在其次,目前的要务还是要提高计划的执行度。
  • 之前了解过的法国厨房标准操作流程,其原则的目的和“保持一切井然有序”的目的是一致的。

读后,思考本周五的工作中,SOP 的问题也在于,流程繁琐,没有模块化,导致“保持一切井然有序”的操作步骤过多,时间成本升高。SOP 的文档写作不够清晰。对细节的记述不够详细。所以会依赖员工的经验

经验之类,如果没有记录在案,就不能流传。所以员工的遗忘,会造成额外的时间成本(二次培训、操作错误等)。解决方法无外乎:

  • 去掉需要经验的部分,将流程封装为黑匣子,减少可能出错的步骤。
  • 将经验写入标准操作流程。

显然后者,会给 SOP 的作者和读者都带来更多成本(写作、阅读、操作)。依据模块化的原则,第一种方法更可行。

实践出真知

工作的主要目标,还是要完成项目。但不改进流程,完成项目的水平难以提升,效率也难提高。

磨刀不误砍柴工的道理,看似浅显,但包含了短期效益和长期效益的博弈。从发展的视角看,打磨是长期规划中必不可少的部分。

井然有序,是控制狂人的标签。我被如此看待也是无奈。但对工作的优化与打磨还是要推行的。

Reference

  1. Becoming a Technical Leader by Gerald M. Weinberg
  2. 成为技术领导者 by Gerald M. Weinberg, 译者: 余晟

题外话:在 OmniOutliner 中使用正则表达式

犯懒了,如图:



周末去天津玩,按工作日通勤时间起床,一个小时的地铁,半个小时的火车,抵达。

上一次去还是去欣赏废 (háng) 铁 (mû),瞻仰先贤祠堂,间隔数年,心态大不同。

利兹卡尔顿,去临近的老利顺德玩,拍完照片自然要发 SNS,然后被评论“进入了游戏场景”。好吧,其实我还挺期待真正的“洋馆之旅”,全程小刀。

1
2
3
4

然后隔墙偷拍久负盛名,号称向高迪致敬,但我感觉阴气森森的瓷房子,主题自“Biohazard”换成“Thriller”,于是晚上回去复习了一下 MJ

5

当然,相声自然是不可错过的。来,爷们亮个相;舞台质量真不错,不仅结实,而且出的这响儿附赠您心跳的。

6

萌宠压轴,最后负责拉赞,黑猫警长,拜托了。

7
8

懒散二日游,慢慢走,休闲不累,周末该如此。

最近 2 年,NGS 的成本越来越低,让研究者可以产生大量的数据,其中有很多优秀的工作,发表了高水平文章。



主要的 NGS 原始数据库

按照学术期刊的要求(比如CNS),NGS 的原始数据,在发表前一般会被上传到几个主要的数据库,包括:

作为期刊的读者,我们需要下载某些数据,无非是基于以下一些原因:

  • 数据基于的物种 / 组织是研究对象。通过下载公共数据而非自产,来节约研究的开支
  • 对研究者发表的结果感兴趣,想进行重复或深入研究;认为发表数据的研究者有遗漏或忽略了重要的研究方向,想对其数据进入深入挖掘
  • 想用数据来练手(这个动机在学生中很普遍)

当然,还会有其它原因,欢迎补充。于是,如何下载呢?

通过文章正文内的线索来寻找

这种情况下,发表的文章会直接给出数据提交到的数据库,数据的 accession。比如:

DNA sequencing data are deposited in the European Nucleotide Archive (http://www.ebi.ac.uk/ena/) under accession numbers ERP001143, ERP000729 and ERP000106. De novo assembly and genome annotation of wild rice W1943, the genotype dataset of 1,529 rice accessions and the imputed dataset of 446 O. rufipogon accessions for GWAS are available at the Rice Haplotype Map Project database (http://www.ncgr.ac.cn/RiceHap3). [1]

再比如:

Accession codes. Raw sequences have been deposited in the EBI European Nucleotide Archive with accession number ERP000729 for worldwide rice germplasm (330 worldwide rice accessions: ERS037511–ERS037840) and with accession number ERP000106 for Chinese rice landraces (100 newly added Chinese rice landraces: ERS039279–ERS039378). [2]

通过数据库的分类系统来寻找,筛选

通过关键词系统、分类系统,你可以在一个数据库,整合所有符合你研究兴趣的数据。

通过其他信息定位

但很多时候,文章的作者并没有给出数据具体的存放位置,或者没有给出数据的ID。我们无法很简单地确定数据的位置,这样就要通过多方面的信息来判断。比如参考文献 [3] 就是如此。在这篇文献里,虽然没有给出具体的位置和数据的 accession,但可以参考的信息还有很多,比如:

  1. 物种是 Triticum aestivum L. cv Chinese Spring
  2. 发表日期:Published 18 July 2014
  3. 作者单位:Department of Plant Sciences/Centre for Integrative Genetics,The Norwegian University of Life Sciences (NMBU)
  4. Paired end (PE) sequencing libraries
  5. HiSeq2000 (Illumina, San Diego, USA)
  6. RNA was isolated and prepared for RNA-seq by using paired-end libraries with 200–base pair inserts for 30 samples with four biological replicates per cell type and time point (two replicates per room) and two additional technical replicates. Total RNA was extracted from frozen plant material using the RNeasy Lipid Tissue Mini kit (QIAGEN, Hilden, Germany; http://www.qiagen.com/applications/plant).

用文章的标题、物种名、技术和研究的关键词作为搜索条件,利用 google 的搜索和在数据库内的检索,定位到候选纪录。

通过和潜在的数据的基本信息的比较,发现支持此数据为文章的数据:

  1. Organism: Triticum aestivum, cultivar: Chinese Spring
  2. Registration date: 19-Jul-2014
  3. Submitted by: Department of Plant and Environmental Sciences/CIGENE, Norwegian University of Life Sciences
  4. Paired end (PE) sequencing libraries
  5. Illumina HiSeq 2000
  6. 30 samples. Total RNA was extracted from frozen plant material using the RNeasy Lipid Tissue Mini kit (QIAGEN, Hilden, Germany; http://www.qiagen.com/applications/plant). Illumina TruSeq RNA Sample Preparation Kits v2

上面的信息的排列,我按照一一对应做了总结。比对之后,确信这个数据和文章的对应关系。

之后就可以把每个 SRA 文件的取样和实验信息整理成表,和发表的文章的信息做对照(这里就开始细活了)。

下载方法

SRA 数据的下载方法,推荐使用 Aspera。用法请参考旧时博文。对于数据量较少的,也可以使用 wget 等命令下载,但耗时较长。

Reference

  1. Huang, X. et al. A map of rice genome variation reveals the origin of cultivated rice. Nature 490, 497–501 (2012).
  2. Huang, X. et al. Genome-wide association studies of 14 agronomic traits in rice landraces. Nat. Genet. 42, 961–967 (2010).
  3. Pfeifer, M. et al. Genome interplay in the grain transcriptome of hexaploid bread wheat. Science 345, 1250091–1250091 (2014).