動高效出圖實(shí)踐)
簡介plotIt-master是一個面向C研究人員與開發(fā)者的ROOT直方圖繪制工具源碼包通過簡潔API自動完成直方圖創(chuàng)建、填充與繪圖幫助用戶避開繁瑣的底層代碼更專注于數(shù)據(jù)分析本身。資源共17個文件主要包括6個C頭文件與3個源文件分別承擔(dān)接口定義與核心實(shí)現(xiàn)另有Shell環(huán)境配置腳本、Python輔助腳本、Makefile構(gòu)建文件及YAML示例配置壓縮包整體僅22KB。已有256人學(xué)習(xí)下載。解壓后即可查看README與示例通過makefile編譯集成快速生成支持自定義分箱、誤差棒、軸標(biāo)簽與圖例的單維/多維直方圖配套的example.yml與構(gòu)建腳本能顯著降低環(huán)境配置門檻適合高能物理、數(shù)據(jù)科學(xué)等領(lǐng)域需要頻繁繪制ROOT直方圖的初學(xué)者與資深用戶。1. plotIt 是什么在 ROOT 繪圖這條路上把重復(fù)勞動交給配置文件如果你用 ROOT 畫過上百張直方圖應(yīng)該記得那種改一個變量就要改一遍宏的滋味。真正花時間的不是畫圖而是讓每張圖都符合統(tǒng)一規(guī)范字體、坐標(biāo)軸、圖例、logY、比值面板。plotIt 就是把這一層重復(fù)勞動抽出來的實(shí)用程序它讀取 ROOT 文件里已經(jīng)填好的 TH1按一份 YAML 配置決定畫什么、怎么疊、開不開 logY、帶不帶比值面板一條命令批量輸出 PDF/PNG。適合正在做粒子物理數(shù)據(jù)分析的人也適合被批量出圖拖后腿的團(tuán)隊(duì)。注意這里說的直方圖是 ROOT 框架的統(tǒng)計(jì)分布 TH1不是圖像處理里做直方圖均衡化的那個直方圖root 是 CERN 的軟件框架不是 Linux root 賬號。2. 從源碼裝好并用最小配置跑出第一張圖依賴、demo 數(shù)據(jù)與第一份 YAML2.1 依賴檢查和編譯ROOT 6 環(huán)境先就位再談其他先把話說清楚plotIt 不是獨(dú)立畫圖軟件它要騎在 ROOT 肩膀上畫布、直方圖、字體、PDF 輸出全走 ROOT 的 C 核心庫。所以第一步不是急著下源碼而是確認(rèn) ROOT 環(huán)境能用。source /opt/root/bin/thisroot.sh root-config --version which cmake第二行會打印 ROOT 版本比如 6.24.06。后面接 CMake。thisroot.sh的路徑取決于你裝 ROOT 的方式可能不在/opt/root下面。只要root-config能被 which 找到編譯時就能正確拿到 ROOT 的頭文件和庫文件。如果前兩行就卡住先回去折騰 ROOT 安裝別急著編譯 plotIt——我見過最長的一次編譯翻車現(xiàn)場最后發(fā)現(xiàn)只是 ROOT 沒 source。源碼拿到本地后我習(xí)慣用 CMake 編譯因?yàn)榭梢皂樖种付ò惭b前綴把工具裝進(jìn)用戶目錄不污染系統(tǒng)。cd plotIt mkdir -p build cd build cmake -DCMAKE_INSTALL_PREFIX$HOME/local .. make -j$(nproc) make install hash -r which plotIt第一行進(jìn)入源碼目錄第二行新建獨(dú)立構(gòu)建目錄這是 CMake 的常規(guī)用法避免源碼目錄里堆滿中間文件。-DCMAKE_INSTALL_PREFIX讓 make install 把可執(zhí)行文件放到$HOME/local/bin以后卸載直接刪目錄就行。make -j$(nproc)用滿 CPU 核心對這種小工具基本半分鐘就編完。如果 cmake 報(bào) yaml-cpp 找不到說明系統(tǒng)缺 C 的 YAML 解析庫Debian/Ubuntu 上裝libyaml-cpp-dev即可。有些版本還依賴 boost 的 filesystem 庫報(bào)錯信息會寫清楚按包名補(bǔ)上就行。裝完用which plotIt確認(rèn)可執(zhí)行文件已經(jīng)出現(xiàn)如果 which 沒找到檢查$HOME/local/bin是否在 PATH 里或者直接用全路徑調(diào)用。提示不同發(fā)行版本的 plotIt 編譯流程有細(xì)微差別有的源碼里干脆只帶 Makefile。動手前先看倉庫 README確認(rèn)該用 CMake 還是直接 make能省掉無謂的折騰。2.2 準(zhǔn)備一棵最小輸入直方圖用 PyROOT 生成 demo ROOT 文件plotIt 只畫“已經(jīng)存在”的直方圖它不負(fù)責(zé)填數(shù)。真實(shí)工作流里這些直方圖是分析作業(yè)跑完寫進(jìn) ROOT 文件的為了練習(xí)可以用 PyROOT 造兩個假的——一個代表數(shù)據(jù)一個代表 MC 本底。import ROOT f ROOT.TFile(data.root, RECREATE) h ROOT.TH1F(MET, MET, 20, 0, 200) h.FillRandom(gaus, 10000) h.Write() f.Close()TH1F五個參數(shù)依次是直方圖名字、標(biāo)題、分箱數(shù)、下界、上界。真正分析里這一句會被事件選擇代碼替代但名字這個參數(shù)要特別在意plotIt 靠它去 ROOT 文件里定位直方圖起名時最好帶完整語義比如jet1_pt、muon_eta而不是h1。FillRandom(gaus, 10000)是偷懶式填數(shù)讓直方圖有個高斯形狀Write()把它寫進(jìn) TFileClose()落盤。MC 那邊稍微多兩步假裝做過一次歸一化import ROOT f ROOT.TFile(mc.root, RECREATE) h ROOT.TH1F(MET, MET, 20, 0, 200) h.FillRandom(gaus, 12000) h.Scale(0.8) h.Write() f.Close()Scale(0.8)相當(dāng)于給 MC 乘以權(quán)重讓它的積分和 Data 大致匹配。真實(shí)分析里這個權(quán)重來自截面、亮度、篩選效率的乘積不會在繪圖工具里手動亂乘我這里只是讓兩張圖疊在一起時不至于比例離譜。注意直方圖名字是“MET”后面配置文件里的 histo 字段就要寫“MET”對不上會直接報(bào)找不到對象。2.3 第一個真配置文件與第一條命令數(shù)據(jù)和一個 MC 文件都備齊后寫第一份配置。文件名叫first.ymldatasets: - name: Data file: data.root histo: MET color: 1 marker: 20 - name: MC file: mc.root histo: MET color: 2 stack: 1 layout: title: MET spectrum lumi: 35.9 energy: 13 logY: false ratio: false format: PDF結(jié)構(gòu)上配置分成datasets和layout兩段。datasets 里每一行描述一個要畫的直方圖name 是顯示在圖例上的名字file 是 ROOT 文件路徑histo 是文件里的直方圖名字color 是 ROOT 調(diào)色板索引1 黑、2 紅、3 綠這樣排stack: 1 表示參與堆疊。layout 段控制整個畫布title 出現(xiàn)在圖頂lumi 和 energy 會渲染成35.9 fb^{-1}, 13 TeV的標(biāo)頭logY 控制縱軸是否對數(shù)ratio 控制要不要數(shù)據(jù)/MC 比值面板format 指定輸出格式。運(yùn)行命令只有一行plotIt -u first.yml ls -la-u在我用的版本里是更新模式作用是允許重復(fù)運(yùn)行覆蓋已有輸出而不是每跑一次就在文件名后面加序號。跑完ls看當(dāng)前目錄應(yīng)該多出一個 PDF。如果報(bào)error while loading shared libraries: libCore.so不是 plotIt 的問題而是當(dāng)前 shell 沒 source ROOT 環(huán)境回到 2.1 第一行即可。這張圖通常不會好看但沒關(guān)系。plotIt 的價值不是讓單張圖更美而是讓你把這份 YAML 當(dāng)作模板換變量名、換文件路徑批量產(chǎn)出統(tǒng)一規(guī)范的圖。它對標(biāo)的是手寫TCanvas、Draw、SaveAs那一堆樣板代碼贏在批量不贏在單張。不同版本對 YAML 字段的支持有差異有的版本叫l(wèi)ogY有的叫l(wèi)og寫配置前打開倉庫自帶 example 看一眼字段以它為準(zhǔn)。3. 把配置文件寫厚datasets、layout 與輸出組織3.1 datasets 塊數(shù)據(jù)、本底、信號的身份要分清楚只有兩個 dataset 的配置太單薄。真實(shí)分析里至少有 Data、數(shù)個本底、可能還有信號顏色、堆疊行為、分組方式都不一樣。把 datasets 段展開datasets: - name: Data file: data.root histo: MET color: 1 marker: 20 group: data - name: QCD file: qcd.root histo: MET color: 2 stack: 1 group: bkg - name: Wjets file: wjets.root histo: MET color: 3 stack: 1 group: bkg比 2.3 多出來的關(guān)鍵字段是group。它把多個 dataset 劃進(jìn)同一個集合后續(xù)想整組歸一化、整組隱藏時不用一個個列名字。我的習(xí)慣是數(shù)據(jù)歸data本底歸bkg有信號樣本就單獨(dú)開sig組??磁渲脮r哪一堆是數(shù)據(jù)、哪一堆是陪跑本底一眼讀出來。stack: 1決定這個 dataset 是否參與堆疊。數(shù)據(jù)不堆疊用 marker 畫點(diǎn)MC 本底堆疊成色塊彼此累加。堆疊順序一般按配置文件里的出現(xiàn)順序第一個寫在最底層。如果某個本底橫跨整個能譜且量級很大放在最底層是好習(xí)慣否則后面的信號容易被壓住。一個細(xì)節(jié)dataset 的 name 直接進(jìn)圖例。Wjets這種帶加號的字符串YAML 里最好加引號包住部分解析器會把它當(dāng)成特殊 tag 而出錯。組里的規(guī)矩是所有 name 一律加引號。dataset 字段名也有版本差異我用的版本file是單個路徑有的工具用files接列表并自動相加。如果支持列表同本底拆成多個跑批文件時就不用先合并直方圖直接列出來由程序加總。3.2 layout 塊坐標(biāo)軸、標(biāo)題、logY 一個都不能少datasets 決定“畫什么”layout 決定“畫在什么樣的畫布上”。這一塊我通常按下面的表逐項(xiàng)核對字段作用常用值title圖頂大標(biāo)題Inclusive jet p_{T}xLabel橫軸標(biāo)簽p_{T} [GeV]yLabel縱軸標(biāo)簽常含分箱寬度Events / GeVlumi亮度值顯示在圖例上方35.9energy對撞能量13logY縱軸是否對數(shù)坐標(biāo)false / truexRange橫軸顯示范圍[0, 200]yRange縱軸顯示范圍留給自動ratio是否需要比值面板false / truegrid畫布網(wǎng)格線falseformat輸出格式PDFwatermark圖角水印Internallayout 段示例layout: title: MET spectrum xLabel: E_{T}^{miss} [GeV] yLabel: Events / 10 GeV lumi: 35.9 energy: 13 logY: true xRange: [0, 200] ratio: false grid: false format: PDFlogY 的經(jīng)驗(yàn)法則縱軸數(shù)據(jù)跨幾個量級就開最多和最少差不到一個數(shù)量級就別開。開 logY 后 yRange 仍是線性坐標(biāo)里的數(shù)值范圍但視覺被對數(shù)壓縮新手常在這里翻車把 yRange 下界設(shè)成 0對數(shù)軸直接畫不出來。yLabel 里的分箱寬度是粒子物理出圖的禮貌問題寫成Events / 10 GeV代表每分箱寬度歸一評審看著更順眼。plotIt 不會幫你自動算要在 yLabel 里手寫清楚。xLabel 里的E_{T}^{miss}是 ROOT 的數(shù)學(xué)文本語法能渲染上標(biāo)注意字符串里的反斜杠轉(zhuǎn)義。watermark 字段平時不顯眼但內(nèi)部評審時非常有用。同一張圖帶 Internal 水印的發(fā)組會材料不帶水印的進(jìn)論文同一個配置只改一個字段。這個習(xí)慣幫我擋了不少次“這張圖能不能外發(fā)”的追問。3.3 一份配置產(chǎn)出多種格式輸出目錄與命名管理layout 里的format多數(shù)版本支持一次輸出多個格式寫法有的用逗號有的用列表。我常用layout: format: [PDF, PNG] outputDir: plots_v1一次跑完P(guān)DF 寫論文插 LaTeXPNG 貼聊天記錄和會議紀(jì)要。outputDir如果版本支持所有產(chǎn)物集中在目錄里清理備份都方便不支持的版本我用 shell 重定向一樣能達(dá)到目的。真正值得提前想清楚的是輸出文件命名。常見邏輯是把 name 和 histo 拼一下比如Data_MET.pdf、QCD_MET.pdf。如果兩個配置文件畫同一個直方圖、同一個數(shù)據(jù)集名字后跑的會覆蓋先跑的——這是最安靜的坑不報(bào)錯文件悄悄變舊。我的做法是每個物理分析建獨(dú)立輸出目錄目錄名帶日期和版本比如plots_v1、plots_v2_fixBinning。目錄一多誰哪天跑過哪版圖翻名字就知道。輸出命名還有一個實(shí)踐直方圖名字盡量全局唯一。同一個 ROOT 文件里同時存在MET和h_MET配置里寫錯名不會報(bào)重名而是畫錯對象。我在分析框架里填直方圖時就統(tǒng)一用varname_region_suffix格式把命名習(xí)慣前置到填數(shù)階段比在繪圖階段補(bǔ)救便宜得多。4. 畫出版級效果比值面板、誤差帶與多變量循環(huán)出圖4.1 打開 ratio 面板數(shù)據(jù)/MC 比值的兩級臺階粒子物理內(nèi)部評審有個潛規(guī)則光看堆疊圖不算數(shù)底下必須掛一條數(shù)據(jù)/MC 比值線。堆疊圖里的差距會被顏色和對數(shù)軸掩蓋比值面板能直接暴露哪個 bin 偏離模型。很多工具不幫你做這一步plotIt 這類程序通常是一個開關(guān)的事。datasets: - name: Data file: data.root histo: MET color: 1 marker: 20 - name: QCD file: qcd.root histo: MET color: 2 stack: 1 - name: Wjets file: wjets.root histo: MET color: 3 stack: 1 layout: title: MET spectrum lumi: 35.9 energy: 13 ratio: true ratioRange: [0.9, 1.1] yLabel: Events format: PDFratio: true會把畫布切成上下兩個 TPad上 pad 畫堆疊與數(shù)據(jù)下 pad 畫比值。第二級臺階是下 pad 的縱軸范圍。我用的版本支持ratioRange直接寫范圍如果字段不識別去倉庫 README 里搜 ratio看它實(shí)際叫什么。下 pad 用自動范圍時比值圖的零點(diǎn)會被拉得很低看起來到處都是偏差其實(shí)只是顯示問題。范圍鎖在 0.9 到 1.1 是常見做法統(tǒng)計(jì)量小就放寬到 0.8 到 1.2不丟人。ratio 面板有個前提MC 必須先歸一化到數(shù)據(jù)。如果 MC 積分只有數(shù)據(jù)六成比值面板整體漂在 0.6 附近看不出任何 bin 的欠擬合。開 ratio 之前第一件事是把 MC 權(quán)重流程檢查一遍。4.2 系統(tǒng)誤差帶誤差要提前算好畫圖只是最后一步系統(tǒng)誤差帶是出圖寫論文繞不開的一環(huán)。先說原理繪圖程序里的誤差帶本質(zhì)是一條帶上下界的曲線它不負(fù)責(zé)計(jì)算誤差從哪來。真實(shí)流程是在分析框架里對每個系統(tǒng)源做一次重填直方圖累加得到每個 bin 的總上下偏差存成 TH1 或 TGraphAsymmErrors繪圖時貼到對應(yīng)的 MC 直方圖上。我用的版本在 dataset 上支持這樣的寫法- name: QCD file: mc.root histo: MET stack: 1 errorBandUp: MET_sys_up errorBandDown: MET_sys_downerrorBandUp和errorBandDown指到 ROOT 文件里的另外兩條直方圖繪圖時在堆疊圖上畫一個淡色帶子。不同版本的字段名可能不同有的叫errorBand有的要求先把上下界合成 TGraphAsymmErrors 再指過去。動手前翻倉庫 example把字段認(rèn)準(zhǔn)這是我被各種版本差異坑過之后的固定動作。用 PyROOT 造誤差帶示意文件import ROOT f ROOT.TFile(mc.root, UPDATE) h f.Get(MET) h.Sumw2() sig_up h.Clone(MET_sys_up) sig_down h.Clone(MET_sys_down) for b in range(1, sig_up.GetNbinsX() 1): sig_up.SetBinContent(b, h.GetBinContent(b) * 1.05) sig_down.SetBinContent(b, h.GetBinContent(b) * 0.95) sig_up.Write() sig_down.Write() f.Close()關(guān)鍵在Sumw2()。它讓 ROOT 給直方圖維護(hù)誤差平方和數(shù)組之后的統(tǒng)計(jì)誤差才有意義。很多人畫誤差帶發(fā)現(xiàn)帶子是零絕大多數(shù)就是忘了 Sumw2。Clone復(fù)制直方圖再逐 bin 改 content 作為上下界。真實(shí)分析里誤差源有十幾二十個逐源掃完再累加這里用 5% 只是演示“直方圖可以作為誤差帶輸入”。誤差帶的質(zhì)量取決于輸入不取決于畫法別在繪圖階段臨時補(bǔ)誤差。4.3 多變量批量繪制一套 datasets 配多個 histo前面所有例子都只畫一個變量實(shí)際分析要出的是成批的圖。多數(shù)版本的 plotItdataset 里的 histo 字段是單數(shù)形式不支持?jǐn)?shù)組。我應(yīng)對的辦法是datasets 和 layout 寫成模板變量名用占位符外面套 shell 循環(huán)。模板template.ymldatasets: - name: Data file: data.root histo: HISTONAME color: 1 marker: 20 - name: QCD file: qcd.root histo: HISTONAME color: 2 stack: 1 layout: title: HISTONAME distribution lumi: 35.9 energy: 13 ratio: true format: PDF循環(huán)腳本for var in MET pt_jet n_jet; do sed s/HISTONAME/$var/g template.yml /tmp/cfg_${var}.yml plotIt -u /tmp/cfg_${var}.yml donesed 把模板里所有HISTONAME替換成當(dāng)前變量名生成臨時配置再調(diào) plotIt。這里有個細(xì)節(jié)直方圖名字不帶擴(kuò)展名如果同名直方圖在 Data 和 MC 文件里都存在替換一次全部命中輸出 PDF 文件名帶上變量名不會互相覆蓋。這套循環(huán)看起來簡單但從“手動改一個變量畫一張”升級到“一個循環(huán)畫完關(guān)鍵變量”是工作方式的分水嶺。我后來封裝成腳本入?yún)⑹亲兞苛斜沓鰠⑹且慌?PDF/PNG。新增變量時只要保證分析代碼真的把直方圖 Fill 進(jìn)去其余全自動。循環(huán)能跑通的前提是直方圖命名規(guī)整。如果變量叫bkg_pt但配置里寫pt循環(huán)會安靜地跳過直到查圖時才發(fā)現(xiàn)少一張。所以占位符最好帶路徑前綴比如jets/HISTONAME與 ROOT 文件內(nèi)部目錄嚴(yán)格一致。5. 避坑五類最常見的崩潰與錯圖陷阱5.1 ROOT 版本不一致本地能編服務(wù)器上崩現(xiàn)象同一份配置在實(shí)驗(yàn)室服務(wù)器畫圖正常在自己筆記本上一跑就 segmentation fault或者圖能出圖例里的希臘字母全變方框。原因ROOT 版本跨度大時繪圖后端 API 有破壞性變更編譯期和運(yùn)行期版本不一致就翻車系統(tǒng)缺字體是方框的元兇。另一個高頻現(xiàn)場是 Python 側(cè)包裝的 plotIt 與 PyROOT 綁定版本不匹配加載時就崩。解決把服務(wù)器root-config --version記下來本地裝同一個大版本6.24 對 6.24 絕大多數(shù)情況下沒大礙。字體問題優(yōu)先用 ROOT 內(nèi)置編號字體配置里把 font 設(shè)成 42即 Helvetica 內(nèi)置編號不依賴系統(tǒng)字體環(huán)境。我之后固定了一套環(huán)境清單ROOT 版本、編譯器版本、yaml-cpp 版本寫成一行的記錄換機(jī)器先對齊再跑圖。5.2 YAML 縮進(jìn)錯誤四個空格引發(fā)的數(shù)據(jù)失蹤現(xiàn)象plotIt 能啟動但圖里少了一個 dataset或者所有 MC 顏色一樣堆疊沒生效。原因YAML 列表項(xiàng)的屬性沒有對齊。最常見的是stack或group寫到 dataset 的同級而不是縮進(jìn)的子級解析器把它當(dāng)成另一條記錄。Tab 和空格混用是同族問題YAML 里 Tab 是非法字符很多編輯器默認(rèn)縮進(jìn)用 Tab復(fù)制進(jìn)配置就出鬼。解決統(tǒng)一用兩個空格縮進(jìn)編輯器開啟顯示空白字符。不確定層級時對著 example 逐行數(shù)空格。壞例子- name: QCD file: qcd.root histo: MET color: 2 stack: 1stack: 1少兩格QCD 的 stack 沒生效。和 file、histo 對齊就好了- name: QCD file: qcd.root histo: MET color: 2 stack: 1畫完圖發(fā)現(xiàn)某條 MC 沒參與堆疊第一眼看縮進(jìn)而不是懷疑解析器。5.3 直方圖路徑?jīng)]寫對文件里明明有程序說找不到現(xiàn)象plotIt 報(bào)找不到直方圖打開 ROOT 文件瀏覽器里一眼看到名字和配置里一模一樣。原因直方圖在文件里的真實(shí)路徑是jet1/MET配置里只寫MET或者名字旁邊帶空格。ROOT 文件的內(nèi)部目錄結(jié)構(gòu)很少顯示在文件名里瀏覽器里看到的是完整路徑但容易看漏前綴。還有一類是文件路徑帶中文目錄名部分版本 ROOT 的文件 IO 對非 ASCII 路徑支持不穩(wěn)定。解決寫配置前先打印文件里的對象路徑import ROOT f ROOT.TFile.Open(mc.root) for k in f.GetListOfKeys(): print(k.GetName(), k.GetClassName())如果返回jets/MET配置里的 histo 就寫jets/MET。文件路徑和輸出目錄盡量純 ASCII。這條花不到兩分鐘能避掉大量“配置沒問題但就是畫不出來”的玄學(xué)。還有人把.root寫進(jìn) histo 字段這是把文件路徑和文件內(nèi)部路徑混了。5.4 重跑之后輸出不更新舊 PDF 比新代碼活得久現(xiàn)象改完 YAML 重跑 plotIt打開 PDF 和上次一模一樣再改一次還是老樣子。原因最常見三種。一是忘了更新模式參數(shù)工具為了省時跳過已有輸出二是輸出路徑變了新 PDF 寫在plots_v1打開的是plots_v2里的舊文件三是 PDF 查看器緩存頁面沒刷新。解決先ls -lt看輸出目錄的時間戳確認(rèn)剛生成的到底是哪個文件。命令行顯式重跑加更新模式。我的固定動作是每次重跑終端打印輸出文件路徑然后直接復(fù)制路徑去打開不靠猜。ls -lt能救掉一半“怎么沒生效”。5.5 堆疊數(shù)量被重復(fù)歸一化疊出來的總形狀莫名其妙現(xiàn)象開 ratio 面板后比值整體漂在 0.5 或 1.5 附近或者 QCD 和 Wjets 各自正常疊起來總形狀對不上 Data。原因上游 ROOT 文件里的 MC 已經(jīng)乘過權(quán)重配置的歸一化又整組歸一了一次或者每個 MC 都開了單獨(dú)歸一化疊完后每一份都變成單位面積堆疊總形狀自然是錯的。解決歸一化邏輯只留一層。是“MC 總積分對齊 Data 總積分”還是“每類 MC 單獨(dú)歸一化到 1”二選一不要混。我的習(xí)慣是上游分析代碼已經(jīng)做絕對歸一化繪圖配置里不再開歸一化需要做形狀對比時才臨時開。這個坑的詭異之處在于它不報(bào)錯只在數(shù)值關(guān)系上露餡所以每次畫完堆疊圖先看總積分再看比值面板基準(zhǔn)線是否貼 1。6. 進(jìn)階把二十張圖的迭代速度壓到一分鐘以內(nèi)配置和模板循環(huán)穩(wěn)定后整個出圖流程就變成一套可重復(fù)的流水線。最后補(bǔ)三個讓效率再高一截的小習(xí)慣。第一個是把循環(huán)腳本改成“失敗繼續(xù)”模式for f in configs/*.yml; do echo $f plotIt -u $f || echo FAILED: $f done常規(guī)腳本遇到一次失敗會中斷剩下十幾張全停。加|| echo FAILED: $f后單張失敗只打一行字整個循環(huán)跑完回頭統(tǒng)一看哪些失敗。做變量掃描時這個習(xí)慣把出圖從“等著中斷”變成“等著結(jié)果報(bào)告”。第二個是驗(yàn)證輸出不只是文件存在而是內(nèi)容可讀。批量出圖后順手pdftotext plots_v1/Data_MET.pdf - | grep MET能 grep 到標(biāo)題文本說明 PDF 不是空白頁字體也沒崩成亂碼。配合ls -lt plots_v1/幾分鐘內(nèi)完成“所有圖都畫了、內(nèi)容都對了”的雙重確認(rèn)。這個習(xí)慣幫我抓住過一次字體雪崩——文件生成了二十個每個都是空白 PDF就是被這條命令攔下來的。第三個是把配置納入版本管理。datasets 和 layout 都是純文本 YAML跟著代碼進(jìn)倉庫直方圖 ROOT 文件體積太大不進(jìn)。這樣每次出圖都能追溯“當(dāng)時的配置是哪一次提交”。評審問某張圖的歸一化是誰加的git log 一查清清楚楚。我現(xiàn)在的新變量出圖流程是在分析代碼里加一行 Fill跑完作業(yè)把 template.yml 里的 HISTONAME 改掉執(zhí)行循環(huán)腳本打開 PDF 掃一眼全套一分鐘以內(nèi)。宏文件里挪圖例、調(diào)坐標(biāo)軸的苦基本告別了。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取