譜圖峰拾取與積分
在從 JCAMP-DX 或 mzML 檔案讀取的 NMR、IR 和質譜譜圖上拾取峰並積分,可接受或拒絕建議峰,每個峰匯出為一行 CSV。
v2.13.0 新增
spectrum 顯示類型在瀏覽器中為每個條目繪製一張譜圖,peak_picking 方案記錄標註者拾取的峰、積分的區域,以及標註者接受或拒絕的建議峰。化學家和波譜學研究者把這兩者配合起來構建帶標籤的譜圖資料集,例如核磁共振(NMR)波譜的峰列表、紅外光譜(IR)中的譜帶歸屬,以及質譜(MS)中的峰標註。教師收集每名學生對同一張譜圖給出的峰列表,在匯出後為這些列表評分。執行自動峰拾取程式的研究組把程式給出的峰作為建議載入,標註者逐一接受或拒絕每個建議峰。
峰拾取列出譜圖中每個峰的位置和強度。在 1H NMR 譜圖中,一個多重峰的積分與產生該多重峰的質子數成正比,標註者在多重峰上拖動即可對它積分。
JCAMP-DX 是由 IUPAC 維護的波譜資料文本格式。mzML 是 HUPO 蛋白質組學標準倡議(Proteomics Standards Initiative)制定的質譜資料 XML 格式,一個 mzML 檔案存放一次執行的全部譜圖。
- 引擎: Plotly 2.27.0(MIT),隨 Potato 一起提交,只在含有譜圖的頁面上載入。Plotly 繪製 SVG,這個顯示類型不需要 WebGL。
- 格式: JCAMP-DX(
.jdx、.dx、.jcamp)、mzML(.mzML)以及兩列文本(.csv、.tsv、.txt、.xy)。譜圖也可以寫成兩個列表,直接放在條目裡。 - 長譜圖: 檔案在伺服器上解析,瀏覽器最多收到
max_points個點(預設 4,000)。原始譜圖的每個分桶保留其最低點和最高點,因此窄的 NMR 譜線仍保持完整高度。放大時會獲取可見範圍內的原始點,只有當該範圍內的點數超過max_points時,伺服器才會再次降取樣。 - 座標軸約定: 化學位移軸和波數軸從左到右由高到低。以 Hz 儲存的 NMR 譜圖會用檔案中的
.OBSERVE FREQUENCY換算為 ppm。 - 離線: 譜圖檔案由 Potato 伺服器從媒體目錄中讀取。以 URL 指定的譜圖會被拒絕,Potato 不下載任何譜圖。
JCAMP-DX 和 CSV 檔案不需要額外安裝,峰檢測使用核心依賴 scipy。只有 mzML 需要 spectra 可選依賴(pyteomics、psims 和 lxml):
pip install 'potato-annotation[spectra]'配置
下面的配置用於 1H NMR 峰拾取。顯示類型給出自動檢測到的建議峰,標註者逐一接受或拒絕建議,為每個峰填寫歸屬和多重性,並對每個多重峰積分:
annotation_task_name: "1H NMR peak picking"
task_dir: .
media_directory: media
output_annotation_dir: annotation_output
data_files: [data/spectra.json]
item_properties: {id_key: id, text_key: note}
instance_display:
fields:
- key: spectrum # item field naming the spectrum file
type: spectrum
label: "1H NMR"
display_options:
prepick: # suggested peaks, off unless set
method: detect
prominence: 0.05
max_peaks: 30
user_config:
allow_all_users: true
annotation_schemes:
- annotation_type: peak_picking
name: peaks
description: "Pick the peaks, assign each one, and integrate each multiplet"
viewer_field: spectrum
peak_fields:
- name: assignment
placeholder: "e.g. OCH2"
- name: multiplicity
options: [s, d, t, q, m, br]
region_fields:
- name: protons
label: "nH"
min_peaks: 1
require_review: true # every suggestion accepted or rejected
label_requirement: {required: true}帶 options 的欄位是選擇欄位,不帶 options 的欄位是文本框。對於 NMR 線狀譜,顯示類型會自動開啟 Integrate 模式。min_peaks、require_review 與 label_requirement 同時設定時,標註者至少拾取一個峰並接受或拒絕了每個建議之前,Next 一直不可用。方案的 viewer_field 必須等於某個 spectrum 欄位的 key,兩者不一致時伺服器拒絕啟動。
每個條目給出相對於 media_directory 的譜圖檔案路徑:
{"id": "ethyl_acetate", "note": "1H NMR, 400 MHz, CDCl3.", "spectrum": "spectra/ethyl_acetate_1h.jdx"}稽核自動峰拾取程式的結果
稽核峰拾取程式的輸出時,把程式給出的峰放進每個條目,標註者只能逐一接受或拒絕建議峰:
annotation_task_name: "Peak picker review"
task_dir: .
media_directory: media
output_annotation_dir: annotation_output
data_files: [data/review.json]
item_properties: {id_key: id, text_key: note}
instance_display:
fields:
- key: spectrum
type: spectrum
display_options:
prepick: {method: item} # the peaks listed in each item
user_config:
allow_all_users: true
annotation_schemes:
- annotation_type: peak_picking
name: review
description: "Accept the real peaks and reject the rest"
viewer_field: spectrum
peak_fields: []
region_fields: []
require_review: true
allow_manual: false
label_requirement: {required: true}{"id": "ethanol", "note": "Peaks from the automatic picker.",
"spectrum": {"file": "spectra/ethanol_1h.jdx", "peaks": [3.69, 2.61, 1.22, {"x": 7.26, "label": "CHCl3"}]}}建議峰是條目 peaks 列表中的一個數字或一個 {x, y, label} 對映。缺少 y 時從譜圖在 x 處讀取;標註者接受建議時,label 會儲存為該峰的 label 欄位。設定 allow_manual: false 後,在建議峰以外的地方點選不會拾取任何峰,“Add a peak at”輸入框也會被移除。設定 peak_fields: [] 和 region_fields: [] 後,方案不要求在每個峰旁填寫任何文本。
質譜與紅外光譜
質心化(centroided)的 mzML 掃描繪製為棒狀圖,點選會拾取最近的譜線棒。只含峰表的 JCAMP-DX 檔案也繪製為棒狀圖,大多數 JCAMP-DX 質譜都屬於這類檔案。下面這段部分配置展示質譜的顯示選項,把檔案自帶的峰表作為建議,只給出最高的 20 個峰:
instance_display:
fields:
- key: spectrum
type: spectrum
display_options:
prepick: {method: file, max_peaks: 20}mzML 條目指定掃描,JCAMP-DX 複合檔案指定資料塊:
{"id": "r7", "spectrum": {"file": "runs/sample1.mzML", "scan": 1043}}
{"id": "c2", "spectrum": {"file": "spectra/compound.jdx", "block": 1}}對於以透射率或反射率表示的紅外光譜,顯示類型拾取極小值。噪聲較大的紅外光譜需要更高的 prominence,例如 0.1。
譜圖資料
條目欄位存放媒體目錄中的檔名,或一個包含下表中各鍵的對映:
| 鍵 | 含義 |
|---|---|
file 或 path | 譜圖檔案,相對於 media_directory |
scan、index | 顯示 mzML 執行中的哪一張譜圖。index 是在執行中從 0 開始的位置,scan 是原生 ID(native ID)中 scan=N 的部分。兩者都不給時顯示第一張譜圖 |
block | 顯示 JCAMP-DX 複合檔案中的哪個資料塊,從 0 開始,只計含有資料的塊 |
peaks | 供 prepick 方法 item 使用的建議峰,寫成數字或 {x, y, label} 對映 |
x、y | 以兩個等長列表表示的內聯譜圖 |
x_units、y_units、kind、title、sticks | 內聯譜圖的單位、譜圖類型、標題和棒狀繪製 |
其他任何鍵都會被拒絕,提示資訊會列出可用的鍵。內聯 NMR 譜圖如下所示:
{"id": "s1", "spectrum": {"x": [0.5, 1.0, 1.5], "y": [3, 40, 2], "x_units": "PPM", "kind": "nmr"}}Potato 自行讀取 JCAMP-DX,支援所有 ASDF 壓縮形式的 ##XYDATA(並校驗 DIF Y 值檢查)、##XYPOINTS、##PEAK TABLE、Bruker 和 MestReNova 寫出的 ##NTUPLES 形式,以及帶 ##BLOCKS 的複合檔案。與 XYDATA 並存的峰表就是檔案自帶的峰列表,prepick 方法 file 會把這個列表作為建議給出。沒有橫座標的 FID、二維 NMR 和 JCAMP-CS 結構不會被讀取。
CSV 檔案有兩列,先 x 後 y,以逗號、製表符、分號或空格分隔。以 # 開頭的行是註釋,可選的表頭行用括號中的文字設定單位,例如 shift (ppm)、wavenumber (cm-1) 或 transmittance (%T)。聲明瞭 DOCTYPE 或實體的 mzML 檔案在解析前就會被拒絕,因為 mzML 兩者都不使用。
選項
spectrum 顯示選項 | 預設值 | 含義 |
|---|---|---|
spectrum_type | auto | nmr、ir、raman、uv、ms 或 other。auto 讀取 JCAMP-DX 的 DATA TYPE,或根據 x 單位推斷譜圖類型 |
x_reversed | auto | true 讓 x 軸由高到低繪製。auto 會反轉 NMR(ppm 或 Hz)和 IR(cm⁻¹)座標軸 |
x_label、y_label | 由單位決定 | 座標軸標題,例如“Chemical shift (ppm)”或“Wavenumber (cm⁻¹)” |
mode | auto | line 或 sticks。auto 把峰表或質心化的 mzML 掃描繪製為棒狀圖 |
peak_direction | auto | max 或 min。auto 對透射率和反射率使用 min |
integrate | auto | 提供 Integrate 模式。auto 只對 NMR 線狀譜開啟 Integrate 模式 |
prepick | 關閉 | 建議峰。true,或包含下一張表中各鍵的對映 |
snap | true | 點選時拾取指標 9 畫素範圍內的區域性極大值(或極小值),而不是指標的確切位置 |
max_points | 4000 | 傳送到瀏覽器的點數,取值 200 到 100,000 |
max_file_mb | 50 | 更大的譜圖檔案會被拒絕。最大為 500 |
scan、index | 無 | 為每個條目顯示的 mzML 譜圖。條目自身的 scan 或 index 優先。兩者給出其一 |
block | 無 | 為每個條目顯示的 JCAMP-DX 資料塊 |
height | 380 | 圖的高度,以畫素或 CSS 長度表示 |
engine | plotly | 唯一的引擎 |
allow_remote | false | true 會被拒絕,因為譜圖在伺服器上讀取 |
prepick 鍵 | 預設值 | 含義 |
|---|---|---|
method | auto | detect 執行峰檢測,file 使用 JCAMP-DX 峰表,item 使用條目的 peaks 列表。auto 依次嘗試 item、file、detect,使用第一個可用的 |
prominence | 0.05 | 用於 detect,表示峰必須比周圍高出多少,以 y 範圍的比例表示,大於 0 且小於 1。對於棒狀譜,表示相對於最高譜線棒的最小高度比例 |
max_peaks | 40 | 建議數量上限,取值 1 到 500,保留最顯著的峰 |
min_distance | 無 | 用於 detect,建議峰之間的最小間距,以 x 單位表示 |
檢測在全解析度譜圖上以顯著性(prominence)閾值執行 scipy.signal.find_peaks。建議峰預設關閉,因為建議峰可能對標註者產生錨定效應。若研究要測量標註者接受峰拾取程式結果的頻率,就需要開啟建議。
peak_picking 選項 | 預設值 | 含義 |
|---|---|---|
viewer_field | 必填 | instance_display 中 spectrum 欄位的 key |
peak_fields | 一個文本欄位 label | 每個峰旁邊的輸入項,寫成 {name, type, options, required, placeholder, label} 的列表。[] 表示不設輸入項 |
region_fields | 一個文本欄位 label | 同上,用於每個積分割槽域 |
min_peaks | 無 | 方案為必填時,拾取的峰達到這個數量之前,條目保持未完成 |
max_peaks | 無 | 超過這個數量的峰會被拒絕,並給出提示 |
require_review | false | 方案為必填時,每個建議都被接受或拒絕之前,條目保持未完成 |
allow_manual | true | false 讓峰只能來自建議,並移除“Add a peak at” |
instructions | 無 | 顯示在問題下方的文本 |
label_requirement | 無 | {required: true} 使方案成為必填 |
| 欄位鍵 | 預設值 | 含義 |
|---|---|---|
name | 必填 | 由字母、數字、_ 或 - 組成的簡短識別符號。列表中的單獨字串會被讀作名稱 |
type | text,給出 options 時為 choice | text 或 choice |
options | 無 | choice 欄位的選項。yes、no、on 和 off 要加引號,否則 YAML 會把這四個詞讀作布林值 |
required | false | 方案為必填時,每個峰(或區域)都必須填寫這個欄位 |
placeholder | 無 | 空文本框中的提示文字 |
label | 首字母大寫的名稱 | 圖下方表格中的列標題 |
拾取峰與積分
圖上方的工具欄有三種模式:
| 模式 | 點選 | 拖動 |
|---|---|---|
| Pick(預設) | 拾取指標下的峰。點選已拾取的峰會移除它,點選建議峰會接受這個建議 | 縮放到拖出的框 |
| Pan | 無操作 | 沿譜圖移動 |
Integrate(integrate 開啟時) | 移除指標下的區域 | 對拖出的 x 範圍積分 |
在圖上雙擊或點選 Reset view 按鈕會縮放回原狀。在觸控式螢幕上,輕觸的作用等同於點選。
開啟 snap 時,在譜線附近點選會拾取該譜線的頂點;標註者需要先放大,把多重峰的各條譜線分開,再逐條拾取。建議峰畫成空心橙色三角形,已拾取的峰畫成實心三角形,並標註該峰的欄位值。每個區域都帶陰影,並標註其相對於第一個區域的積分,第一個區域顯示為 1.00。
伺服器把每個積分計算為區域兩端之間所有原始點上的梯形積分,不做基線校正。因此,畫得比多重峰更寬的區域讀數會偏高;當相對積分需要固定的參照時,說明中應寫明先對哪個訊號積分。對於設定了 integrate: true 的棒狀譜,積分是區域內譜線棒強度之和。
方案在圖下方列出建議峰,每個都帶 Accept 和 Reject 按鈕,另有 Accept all 和 Reject all。被拒絕的建議顯示為一個小按鈕,按下即可恢復該建議。Peaks 表每個峰一行,包含峰的位置、強度、來源和欄位,以及一個 Remove 按鈕。Integrals 表每個區域一行,包含區域的範圍、積分、相對積分和欄位。在“Add a peak at”輸入框中,標註者鍵入一個位置後按 Enter;如果這個位置與某個建議峰一致,就會接受該建議。每個控制元件都是按鈕或表單欄位,標註者只用鍵盤就能審閱一張譜圖。
儲存的答案
peak_picking 方案為每個條目儲存一個 JSON 物件:
{"viewer": "spectrum",
"items": [{"kind": "peak", "x": 2.0399, "y": 3003, "source": "auto", "width": 0.0031,
"fields": {"assignment": "CH3CO", "multiplicity": "s"}},
{"kind": "peak", "x": 7.26, "y": 132, "source": "manual"},
{"kind": "region", "from": 1.969, "to": 2.120, "integral": 15.77,
"fields": {"protons": "3"}}],
"rejected": [4.1464]}source 對接受的建議為 auto,對標註者新增的峰為 manual。width 是檢測到的峰在半顯著性處的全寬,以 x 單位表示。rejected 列出標註者拒絕的建議的位置。既未接受也未拒絕的建議不會被儲存;在必填方案中,require_review 確保每個建議最終都進入這兩個列表之一。
匯出
peak_table 匯出為每個峰、每個區域和每個被拒絕的建議各寫一行:
python -m potato.export --config config.yaml --format peak_table --output out/匯出寫出 peaks.csv 和 peaks.jsonl,--option format=csv 或 --option format=jsonl 只寫其中一個。JSONL 行省略空列。
| 列 | 內容 |
|---|---|
user_id、instance_id、schema | 標註者、條目和方案 |
kind | peak、region 或 rejected |
x、y、width | 峰的位置、強度和寬度(僅限檢測到的峰)。rejected 行只有 x |
from、to、integral、relative | 區域範圍、積分,以及相對於同一答案中第一個區域的積分 |
source | 峰為 auto 或 manual。區域為 manual,被拒絕的建議為 auto |
label | 該行的欄位值,以“ / ”連線 |
| 每個欄位一列 | 例如 assignment 和 multiplicity;欄位名與上面某列同名時加字首 field_ |
多名標註者可以在同一張譜圖上拾取峰,人數由 num_annotators_per_item 設定。通用的 CSV 和 JSONL 匯出也包含答案,每個方案佔一個 JSON 單元格。Potato 的一致性指標不覆蓋 peak_picking 方案。請在匯出後用 peaks.csv 比較標註者的峰列表,例如在 ppm 或 cm⁻¹ 的容差範圍內匹配同一條目的峰。對於峰拾取程式的稽核,source: auto 峰行和 rejected 行的數量給出每名標註者的接受率。
示例
python potato/flask_server.py start examples/advanced/spectrum-peak-picking/config.yaml -p 8000這個示例包含兩張合成的 1H NMR 譜圖,分別是乙酸乙酯和乙醇的譜圖,以 Hz 為單位、採用 DIFDUP 壓縮的 JCAMP-DX 格式;另有一張以 CSV 儲存的合成紅外透射譜。示例開啟了檢測建議和 require_review。同一目錄下的 generate_spectra.py 會重新生成這三個檔案,資料是虛構的。
用程式設計智慧體搭建研究
potato-skill 1.2.0 面向 Potato 2.13.1,認得 peak_picking 和 spectrum 這兩個名稱,並指導研究設計這一側,例如向標註者問什麼、每張譜圖由幾名標註者拾取峰、培訓和注意力檢查,以及匯出。這個技能目前還沒有記錄譜圖檔案格式、顯示選項和 spectra 可選依賴。安裝 potato-skill,把研究描述給你的智慧體,再讓智慧體參考本頁的 Markdown 副本 https://www.potatoannotator.com/docs/annotation-types/spectra.md,以瞭解格式和選項。
延伸閱讀
- 化學結構 - 分子上的結構編輯與原子選擇
- 實例顯示 - 如何配置顯示欄位
- 匯出格式 - Potato 的匯出格式和匯出命令
- 你需要多少位標註者? - 為每個條目選擇標註者人數
- 生命科學 - 用 Potato 做生命科學與生物資訊審編
有關實現細節,請參閱源文件。