<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Yorksite</title><description>All those moments will be lost in time, like tears in rain.</description><link>https://blog.yorks0n.com/</link><item><title>Plog004：好吃好吃</title><link>https://blog.yorks0n.com/plog/plog004/</link><guid isPermaLink="true">https://blog.yorks0n.com/plog/plog004/</guid><description>最近吃了好多东西，根本停不下来。</description><pubDate>Mon, 04 May 2026 14:45:00 GMT</pubDate><content:encoded>趁着五一开始前错峰去了大连玩了两天。几年前四月底去青岛就发现，似乎和江浙沪这边的春天有半个多月的延迟，这次去大连也正好迎上春天，各种樱花丁香桃花梨花开得不亦乐乎，又赶上了好天气，20出头的温度很舒服，虽然晒得热烘烘的，海边凉爽的海风又弥补了这一点。现在出去玩就主打一个吃，其他在各种景点间穿梭、城市漫步，都为了消食更好地吃下一顿。

大连的小海鲜也非常好吃，正巧四月底禁渔，赶着最后一波去吃了个爽。因为blog目前对多图的处理不是很好，选几张堆在这意思一下。

![大连](images/IMG_7357.jpg)

## 最近玩了啥

**[A short hike](https://store.steampowered.com/app/1055540/A_Short_Hike/)**，流程不长但发现steam上好评率高到离谱，尝试了下确实是个轻松休闲的解密游戏，正如游戏名称那样，整体气质非常悠闲惬意。游戏流程不长，几个小时就能打完，虽然没有官方中文，但能找到很精良的中文翻译，翻译使用起来也很方便，把翻译文件放到游戏目录中，就能在设置中选择了。

还尝试了最近新出的 **[吸血鬼爬行者](https://store.steampowered.com/app/3265700/_/?l=schinese)**，复古的地牢爬行游戏，最初感觉平平无奇，但随着越来越多内容的解锁，发现也是像吸血鬼幸存者那样的纯爽游来的。

因为五一出游的缘故，拿起来了之前只是浅浅玩了一点的 **[小丑牌](https://store.steampowered.com/app/2379780/Balatro/?l=schinese)**，也是之前没玩明白，这次多尝试了一下，发现要点不是各种牌型，而是小丑牌的特效组合。在第一次用那个每次余下出牌弃牌次数都能赚钱，但不吃利息的牌组通关后，体会到了乐趣和玩法，再尝试其他牌组，想通关也就顺畅多了。发现自己玩游戏还是不想怎么动脑子，之前感觉算各种出牌点数多少多少的很麻烦才没有深入玩，发现玩法爽点后根本停不下来。

还跟风玩了最近刚出的 **[梦幻魔法公主](https://store.steampowered.com/app/3562120/_/?l=schinese)**，这游戏热度这么高，其超精良的制作，带有全语音的对话和精致的live2D，配上其国区只要38的超绝的售价，主打一个买了不吃亏买了不上当。第一次尝试这种类型的游戏，说实话对这个主题本身兴趣不大，也没玩过之前火山的女儿等一些养成游戏，不过这个游戏里融合的各种玩法，玩起来还是非常上头的。前两天一口气把两个周目打完了，还是不错的，哐哐哐跳steam成就的感觉也不错，感觉也是玩法的一部分了。

## 最近读了啥

前些天刷xhs看到一个早年讲绘画构图的书，1982年高宗英著《谈绘画构图》，里面的概念都是非常直白的大白话，虽然本意是讲绘画的，但感觉也可以拿来当摄影教材看，很神奇。

![谈绘画构图](images/longshot20260504144233.png)

**[AI makes you boring](https://www.marginalia.nu/log/a_132_ai_bores/)** 又一篇提醒大家 AI 虽好但不能过度依赖的文章，感觉最近越来越多看到类似的讨论，自己也有相似的体验，用AI写代码的时候把很多可以选择关注的细节交给AI来实现，于是一方面AI倾向于用非常详细（甚至冗余）的代码和输出进行工作；另一方面实际用在思考项目上的时间其实是变少了的，因为在等待AI吐出字节时，通常会切到另一个项目或是看些不相关的内容。和上周读到的那篇有关AI影响研究生培养的文章有些呼应，AI也在影响每个人学习和思考的过程。虽然目前状态下感觉AI还不能完全独立进行探索和创新性的工作，但应该在将来的某个时候也会到来吧。

## 最近吃了啥

要说最近吃了啥那可太能吃了。因为怀念过年那阵出去玩吃到的一个紫苏梅子卷，找不到于是准备自己做，买了寿司醋尝试搞了紫菜卷，加了虾仁、梅子、紫苏，因为买金枪鱼不方便，用牛油果增加细腻的口感，又加了点黄瓜条增加脆口。不得不说，梅子配紫苏的味道超绝，哪怕不吃这么麻烦的紫菜卷，也要尝试一下紫苏叶包着梅肉吃。就是这样搞一次各种东西都要一点，吃完啥都剩不少，这次做完剩下的牛油果蘸酱油吃完了，黄瓜也蘸着黄豆酱啃了。

![自制紫菜卷](images/photo_20260504_juan.jpeg)

又过了两天，为了消耗前两天剩下的紫苏，买了宜家那个不锈钢平底锅来烤（煎）肉，锅很好使，煎牛肉的时候牛油的香味非常浓郁，很满足。再做个枸杞叶猪肝汤，大学时候食堂老喝，不过后来毕业就没再喝过了。

![烤肉](images/photo_2026-05-04_14.49.18.jpeg)

结果继前紫苏梅子卷、紫苏包烤肉之后，买来的一盒紫苏叶还只是受了点皮外伤，终于找到个可以用紫苏炒玄米茶的做法，就尝试了一下。拿大米开小火慢慢炒，中间加入紫苏再慢慢炒干，花了快一个小时。过程中确实很香，感觉自己都腌入紫苏味儿了。

![紫苏玄米茶](images/longshot20260504145111.png)</content:encoded></item><item><title>Plog003：Until Then</title><link>https://blog.yorks0n.com/plog/plog003/</link><guid isPermaLink="true">https://blog.yorks0n.com/plog/plog003/</guid><description>直到那时啊……直到那时</description><pubDate>Fri, 17 Apr 2026 13:40:00 GMT</pubDate><content:encoded>## 最近玩了啥

昨天打完了 **[直到那时 Until Then](https://store.steampowered.com/app/1574820/Until_Then/)** ，前一阵Steam在打折，本月也进了HB的慈善包，找一找可以买到非常便宜的。

很久没有遇到如此有冲击力的作品了，玩的时候总会忍不住列举优点，诸如绝美的像素美术，非常之好的中文翻译，青春到令人嗷嗷叫的剧情，但是直到通关的那一刻，能想到的只有忍不住一句句感叹天呐。
这部游戏带给人的也是一种非常私人的感触，甚至会到犹豫是否要和人推荐的程度，因为每个人玩过后的体会肯定会截然不同——通关后搜了一下果然如此。

我一直认为，好的剧情之所以吸引人，是因为它给了人们体验一种与自己生活完全不同经历的机会，而游玩 Until Then 的过程，真的仿佛在其中生活了一阵。

通关后有好多想说的，但是不能说，这是一部你玩之前对它了解越少，体验就越独特的作品。
如果你在犹豫要不要玩，玩就是了，这也是那种一生仅有第一遍能给人如此体验的游戏。说起来，近些年好几个玩过之后体验非常好的游戏，都是在下决心去玩之后，就一点相关信息都不看专心去玩，才能有最好的沉浸感。


## 最近读了啥

之前大火的Sora也停了。之前总讲互联网时代边际成本非常低，所以用户越多成本越低利润越高，然而到目前各种工具全面拥抱AI功能后，由于每个用户都需要自己的AI算力，每个增加的新用户都会增加相当一定量的算力消耗，导致边际成本出现一个始终无法降低的最低值。由此扩展一下，可能到某个时候开始，盲目增加用户数量不再可取，而是尽量争取少量（或稳定数量）的长期优质客户，兴许更能保持长期稳定的盈利。

![](images/photo_2026-04-17_13.38.29.jpeg)

**[机器没问题，我担心的是我们自己。](https://ergosphere.blog/posts/the-machines-are-fine/)** 读到一篇对学生培养过程中使用AI的探讨，最近时不时也会想到，低年级的同学们在AI的帮助下，各种报告写起来那都不费事，不知道若干年后会怎样？可能会想文章说的那样，由于把思考外包了出去，最终并没有多少提升；也可能因为AI愈发成为一种基础设施，获得熟练与AI合作的能力。Who knows？

&gt; 科学的伟大之处在于其中的人。一个困惑的学生逐渐成长为独立思考者的过程，缓慢、执着，有时甚至充满痛苦。

&gt;你每困惑一小时，就是在头脑中构建一小时内能让你最终完成原创工作的基础架构。这个过程没有捷径可走，任何试图走捷径的行为都会让你在另一端变得逊色。

&gt;高校都要求博士生发表论文，至于你写什么、怎么写的、内容与研究方向有没有关系，系里其实都不在意。系里需要论文，因为论文能证明经费的合理性，而经费又能证明系的存在价值。学生只不过是达成这个目标的生产资料。

## 好看的设计

看到了两个好看的设计，**[sunlit](https://www.sunlit.place/)** ，我们日常常见的都是亮色模式和暗色模式，这个网站是一种更美观的样式，大概能称得上“午间/傍晚”模式？最近又有不少类似的风格出来。

以及这个，**[bflycomputer](https://www.butterfly.so/)** ，旨在做一个更加美观易用的Linux，还没做出来，但这个官网太好看了。


## 出门走走
最近一直阴雨连绵，终于短暂地出了点太阳，春天好短暂，许多花都谢了，夏天也不远了。

![](images/IMG_6889.jpg)</content:encoded></item><item><title>Plog002：春天花会开</title><link>https://blog.yorks0n.com/plog/plog002/</link><guid isPermaLink="true">https://blog.yorks0n.com/plog/plog002/</guid><description>这周樱花开了，春天了多出门走走。</description><pubDate>Fri, 03 Apr 2026 00:00:00 GMT</pubDate><content:encoded>上周六去Let&apos;s Vision逛了一圈，蹭的票所以没去听报告主要是各种小的展位。感觉大部分人都是来摊位集章打卡抽奖的。
就摊位而言，大部分是独立App开发者的小摊，类型各种各样不过还是更偏生活类，或是一些降低门槛的开发类小工具。少量硬件例如可以接入ai的开发板，或是人体工学椅之类。
也有少量大厂的展位，例如内容平台的b站（一些开发类up的交流）、小红书，或是传统些的智能硬件aqua、tomtoc，也有WPS在推广iPad版WPS。

![Let&apos;s Vision](./images/IMAGE2.jpg)

## 一个人带着一组AI开公司？
尝试了下这组名为[gstack](https://github.com/garrytan/gstack?tab=readme-ov-file)的skill，号称把给agen提的一项需求按照公司不同职位审核的过程，拆分成不同的skill一步步执行，通过反复交叉确认来修改编辑计划，最终再执行。

让它给我做的工具修了个bug，倒是修好了，但是真的非常非常非常费token。也不知道是不是凑上了最近cc的token不耐用的问题，这个skill运行个不到一小时就能把Pro一个时间段的额度跑完，因此按照这组skill的顺序运行一遍花了两天时间。当然运行过程中的上下文也巨大，基本每走一两步就快到触发上下文压缩了，大概这种skill都是给那些开着200刀额度的人用的吧。

## 本周看了啥

这周Cloudflare推出了[EmDash](https://blog.cloudflare.com/emdash-wordpress/)，一个内容管理系统，底层是用Astro写的，旨在成为WordPress的开源替代。目前还是早期预览版，但也许将来的某天会把blog迁移到这个上面试试。目前还是纯本地管理blog文件，每次新建文章的时候要手动创建文件夹，写那些日期时间之类的，还是有点麻烦的。


## 最近玩了啥

这周在玩[灰烬之国](https://store.steampowered.com/app/3214610/_Cinderia/?l=schinese)，最开始demo的时候就玩了好一会，前些天开EA就买了个继续玩。整体是主打爽快的类似哈迪斯1的动作肉鸽，技能和天赋数值也给得很爽快，不都是那种抠抠搜搜加一点点数值的升级。不过中后期怪物设计的平衡性有些问题，比如有些小怪即使一下能秒掉，也带一个继续存活好几秒能放技能的亡语状态，甚至这个亡语不吃控制不吃伤害，加上技能范围特别大同时又会有好多只，希望将来能再调整一下平衡性设计吧。

## 出门走走

这几周外面的花开得越来越多了，趁着没下雨前去看了下滨江的樱花，开得正好，这周末估计会有茫茫多的人聚在这里吧。

![](images/1775103681000_R0007344.JPG)</content:encoded></item><item><title>Plog001：让人疲惫的AI与在战锤世界中仰泳，赞美欧姆尼赛亚？</title><link>https://blog.yorks0n.com/plog/plog001/</link><guid isPermaLink="true">https://blog.yorks0n.com/plog/plog001/</guid><description>一些最近读到玩到的，玩了不少战锤游戏，看了不少AI有关的文章。</description><pubDate>Thu, 26 Mar 2026 00:00:00 GMT</pubDate><content:encoded>大概是前一阵的临时起意，准备每隔一阵把一些零零碎碎的见闻和念头整理一下写成Plog。这些内容各个都不长，内容又极其散漫杂乱，都不适合单独作为文章来写。以往就任由这些东西随时间消散了，但现在愈发感到记忆力和精力开始逐渐衰退，记录一下也让它们有些归宿，若是五年十年后回过头来看，说不定还能回想起写下它们时的心境。

## 最近读到的
**[Filesystems are having a moment](https://madalitso.me/notes/why-everyone-is-talking-about-filesystems/)**，一篇讨论cc与codex这类能直接访问本地本件工具的文章，在当下各种软件功能越来越复杂，数据格式越来越封闭独立的情况下，本地文件，尤其是纯文本的易于访问和通用性，使得不同的封闭工具间，可以通过读取相同的规则文本来沟通，有点像把文本作为一种API，不是直接传递数据，而是传递数据的理解方式。同时各种工具的Skill，也继续反映了那个主题：你不需要记住所有东西，你只需要记住去哪里能找到它们。

**[新闻实验室会员通讯（914）为什么AI让你的工作更累了](https://newsletter.newslab.info/ai-overwork-brain-fry/)**，新闻实验室的一篇Newsletter，主要内容就像标题所讲的那样，虽然AI让我们的能力与生产力提高了不少，但是似乎并没有变得更轻松。这里摘录几个片段：
&gt; 他总结出一个悖论：你拥有的能力越强，你越觉得必须使用它；你越频繁地使用它，你的注意力就越碎片化；你的注意力越碎片化，你真正交付的东西就越少。

&gt; AI时代的新型工作日常应该是三到四个小时的高强度认知劳动，而不是八小时对着屏幕做这种吸血鬼式的工作。

&gt; 她深入研究了行为科学文献，发现AI互动的成瘾机制与老虎机如出一辙——心理学家 B.F. Skinner 在上世纪五十年代就发现，不可预测的奖励间隔是最强大的行为强化模式。

结合最近的个人体验，感到自己能做的更多，但每天的工作强度明显提高，于是每天更疲惫，以及前一阵看到的一个结论，“如果同时使用超过三个AI工具，效率会开始下降”，果然我们还是在摸索和AI合作的过程中。

## 最近玩到的
前一阵和朋友们联机在玩 **[战锤40K：行商浪人](https://store.steampowered.com/app/2186680/Warhammer_40000_Rogue_Trader/?l=schinese)**，是一款战锤世界观下的crpg游戏。这是我第一次接触战锤IP的内容，总计耗时100h出头，打通了不含DLC的教条主义剧情线。走格子海战从头无聊到尾，纯纯折磨；后期战斗数值崩坏，最后一章将难度开到最高，再用辅助小工具将敌人血量再额外乘15倍，才勉强够打个两三回合；BUG奇多无比，后期根本分不清各种战斗、道具、交互中BUG和机制的边界。纵使吐槽了这么多，但考虑到本游戏巨大到可怕的文本量，不太高的上手门槛，和对世界观的生动塑造，还是可以称之为瑕不掩瑜（7/10）。玩过游戏之后，才能懂那个比喻：战锤世界就是在粪海里游泳，信仰帝皇至少能让你脸朝上。游玩过程中时不时能看到《基地》或者《海伯利安》的影子，确实塑造出一个宏大的星河世界。

此外，在Steam上战锤IP各种游戏普遍好评率一般的情况下，行商浪人即使有这么多BUG还能维持在特别好评，也足以证明其剧情与人物塑造的质量优秀。

紧接着开始玩 **[战锤40K：暗潮](https://store.steampowered.com/app/1361210/40K/?l=schinese)**，玩起来像某种联机fps打僵尸游戏，主打高强度与爽快。
联机玩起来挺不错的，因为有强度所以需要队友配合分工，清理近战与远程，怪物潮与精英，倒地需要队友及时掩护与拉起。由于护盾的缓慢恢复需要队友在周围，也不鼓励单走。

然而单人游玩体验不会很好，虽然会填充bot队友到四个人，但是电脑队友几乎只有一个职业，也不会使用道具，比不同职业的玩家队友强度差太多了。要不就是匹配路人，低难度还好，高难度下不能顺畅交流还是不太方便。目前战役模式还没打完，以后再讲更多的游玩体验吧。

**[StS2 Launcher](https://github.com/Ekyso/StS2-Launcher)**，一个非官方的杀塔2安卓启动器，需要登录Steam，使用Steam下载游戏数据和云存档。
启动前需要在系统里把语言改为[英语-美国](https://github.com/Ekyso/StS2-Launcher/issues/11)，中文系统似乎有点BUG，得等修复，进入游戏后可以修改游戏中的语言，安卓也有安卓的好。

## 最近看了什么
上周六去电影院看了**挽救计划**的电影，作为没看过原著的人，电影开头节奏有点怪，云里雾里的，兴许是为了表现主人公突然醒来但完全懵住的状态？中后段剧情非常温情，但Rocky真的很像会3D打印的SC龙骑士。作为一个平时也要做实验的人，看到电影里表现做实验的过程，总是忍不住出戏到实际做实验的上班过程中，让人有些疲惫。以及好久没在科幻作品中看到如此不智能的飞船AI了，不知道是不是为了弱化AI营造孤独感而特意为之。

于是在之后的几天去看了原著的小说，今天凌晨快一点才看完。评价为一部可爱温柔的小说，从一个最简单的假设出发（嗜星体），有大量基于现实物理化学规律的详细描述，并延伸出一系列故事。果然小说里各种细节的塑造更多一些，是一部挑不出什么缺点非常好看且不太长的太空小说。

## 最近拍到的猫猫
蹲在机车上的优雅小猫
![](./images/IMG_6548.jpg)

猛虎下山
![](./images/IMG_6612.jpg)

脾气很好怼脸拍也不生气
![](./images/IMG_6622.jpg)

好像目前博客对于图片的显示处理还不是很好，改天优化优化，下次再见。</content:encoded></item><item><title>rhaeTree：一个基于 Rust 的进化树可视化编辑工具</title><link>https://blog.yorks0n.com/articles/rhaetree/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/rhaetree/</guid><description>长期以来，我做完进化树后都会使用Figtree进行一些细节的编辑，例如增加颜色注释、分支高亮等，我也曾把它推荐给许多人用来美化进化树。身边不少人都使用MEGA等...</description><pubDate>Tue, 10 Mar 2026 07:30:00 GMT</pubDate><content:encoded>长期以来，我做完进化树后都会使用[Figtree](https://github.com/rambaut/figtree)进行一些细节的编辑，例如增加颜色注释、分支高亮等，我也曾把它推荐给许多人用来美化进化树。身边不少人都使用MEGA等软件做进化树，然而MEGA内置的编辑功能之匮乏、软件之臃肿，实在让人喜爱不起来。

然而Figtree已经多年没有更新，其上一个大版本[v1.4.4](https://github.com/rambaut/figtree/releases/tag/v1.4.4)发布于2018年，随着系统更新的迭代，旧版软件的痛点逐渐出现：

- Mac版在OS26更新后完全不适配高分辨率屏幕
- 使用前需要额外安装JRE环境
- highlight功能不太好用
- 样式编辑后不能撤销
- 颜色选取较为麻烦
- etc

因此在去年上半年萌生了自己重写一个工具的念头，并使用Rust在与Codex的合作下完成了[rhaeTree](https://github.com/Yorks0n/rhaeTree)，补上了一些我比较常用的功能，并对一些原有功能进行了优化。目前仍有许多不足，还在积极更新中，希望能得到大家的试用与反馈。

---

接下来简单介绍一下rhaeTree的基本布局与常用功能，如果是用惯了Figtree的朋友应该会比较容易上手。

打开软件，主界面分为顶部功能栏、左侧功能栏与右侧的进化树显示界面。打开一个已有的进化树，可以使用顶部功能栏左上角的 `File - Open…`，选择nexus或newick格式的进化树文件并打开，此处以`examples/OsLDP.fasttree.nex`为例。

![image.png](images/image.png)

## 置根与调整布局

如图可见，该进化树目前显示得比较奇怪，原因之一是许多进化树构建软件输出时，对进化树的根节点进行自动判断是比较困难的，为了设置合适的根节点（或根分支），可以使用左侧`Trees - Root tree - Midpoint`，使用中点置根法自动生成一个根节点位置，这样能看到基因被分成了三组，明显是顺眼多了。

![image.png](images/image%201.png)

当然，如果你知道某个分支是明确的外类群，或是希望以某个离其他较远的分支作为根分支，也可以手动设置根节点。回到左侧`Layout`，将布局切换到`Radial`，也能看到有一支离其他枝明显较远，假如希望将其作为根分支，可以先在顶部选择模式中激活`Node`模式，点击进化树上对应的分支选中，最后点击左上角的`Reroot`，即可以这一分支作为进化树的根分支。

![image.png](images/image%202.png)

`Radial`布局中可能`Reroot`的影响不太明显，但如果切换到Rectanglar或是Circular布局中，就能明确看到进化树的布局发生了变化。

![image.png](images/image%203.png)

## 为文本添加标注

调整完布局，为了让进化树可读性更强，我们往往会将一些节点的标签从原本的基因编号改为已发表或是我们给予的命名。想实现这点有两种方式，第一种比较直接，在顶部选择模式中激活`Taxa`，直接点击想修改的`Tip Label`，再点顶部的`Annotate`即可为它添上你喜欢的名字。

![image.png](images/image%204.png)

第二种方式，则是利用右上角的标签过滤器，再其中输入你想修改的基因号，会自动选中对应的节点，再点击`Annotate`同样可以修改。

![image.png](images/image%205.png)

## 修改颜色

为不同物种的基因号添加不同颜色也是我们常用的功能。要想添加颜色，一个个选中去改固然可以，但更方面的则是使用过滤器功能。这里里水稻的基因号为例，它们都以`Os`开头，因此直接在右上角过滤器中输入`Os`即可选中全部水稻基因号，点击左侧的Color即可为它们统一修改颜色。

你可能注意到了，被我们修改过名字的基因（图中的GAPLESS1）也被选中了，这是因为过滤器会同时去筛选原有与修改过的全部标签字段，因此修改时也要注意是不是选中的都是你想修改的那些基因号。

![image.png](images/image%206.png)

同理，各个分支的颜色也是可以修改的，不过就需要先用`Node`或`Clade`模式选中想修改的分支，再用`Color`来修改颜色，这里不再赘述。

## 添加高亮

给特定分支添加高亮方便我们着重突出我们所关注的那一个分支，在`Node`或`Clade`模式下，点选想要高亮的分支，随后使用左上角的`Highlight`功能，选好颜色并确认，即可添加上高亮效果。我努力了一番，现在各个布局中都有不错的高亮显示效果。

![image.png](images/image%207.png)

## 导出

在对进化树样式进行一定编辑后，你可能会希望将编辑过的结果临时保存起来，供下次继续编辑，这可以使用`File - Save As..`功能，该方式会生成一个`.rtr`格式的文件，这是rhaeTree所使用的数据保存格式。

![image.png](images/image%208.png)

假如你已经完成了进化树编辑，希望导出进化树，则可以使用下面的导出功能，推荐导出为PDF或SVG的矢量格式，以供进一步在adobe illustrator等软件中进行后续的编辑。

## 已知问题

目前 macOS 版我用了开发者账号进行签名，但没有进行公证，因此首次打开需要去系统**设置-隐私与安全性**，翻到最底部并选择允许运行。Windows 版在启动时也可能会弹出警告。且 Windows 版本进行的测试不多，不确定各种功能是否都运行良好。

如果使用中遇到任何问题，欢迎到 GitHub 页面提出，或直接联系我（rhaetree@yorks0n.com）进行反馈。

## 相关链接

- https://github.com/Yorks0n/rhaeTree
- https://github.com/rambaut/figtree</content:encoded></item><item><title>我的键盘快捷键们</title><link>https://blog.yorks0n.com/articles/my_keyboard_shotcuts/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/my_keyboard_shotcuts/</guid><description>整理了下目前的键盘快捷键，趁着还没痴呆多用用吧。</description><pubDate>Thu, 29 Jan 2026 08:44:00 GMT</pubDate><content:encoded>前一阵才意识到，日常用到的键盘快捷键数量已经积累到了有些离谱的程度，趁着今天摸鱼不想干活，整理一下。

我主要通过 Karabiner-elements + Keyboard Maestro + Alfred 的组合触发各种效果。大致有如下一些：

利用 Karabiner 为键盘上的一些键添加了额外的效果，例如将右侧不常使用的 `Cmd` 映射为了`Hyper` 键（模拟`Ctrl + Option + Shift + Cmd`同时按下的效果），用于在一些软件中设置此快捷键。

## 剪贴板相关

- `Ctrl + V` 粘贴去除格式的文本，作为 Mac 默认 `Cmd + V` 粘贴的补充。这个功能很多工具都会提供，不过各自有不同的实现逻辑，比如 Alfred 中就会将剪贴板中的当前内容直接覆盖处理为纯文本，粘贴一次后剪贴板上就只剩下文字格式的内容，而非原本的文件或图片。因此使用 KM 实现将剪贴板内容缓存后再处理为纯文本，待粘贴完成后再恢复为先前的内容。
- `Hyper + C`，打开 Alfred 的历史剪贴板。
- `Hyper + V`，打开 Alfred 的 Snippets，里面是一些预先存好的文字片段，比如一些输入起来麻烦的符号、邮箱地址之类。

## 快速激活常用软件

使用 Karabiner 为左侧的大写锁定键 `CapsLock` 设置了额外的功能层，单独按下它是输入制表符 `Tab`（因为键盘太小没有独立的 `Tab` 按键），长按 `CapsLock` 则进入以下功能：

- `CapsLock + A`，快速打开（或将屏幕焦点切换到，若当前软件为激活状态则隐藏该软件）纯文本的编辑器 Drafts，用于快速记录文字或是临时编辑一段文字；
- `CapsLock + C`，快速打开浏览器 Chrome；
- `CapsLock + F`，快速打开文件管理器 Finder，最近换成 Bloom 了；
- `CapsLock + G`，快速打开命令行 Ghostty；
- `CapsLock + T`，快速打开文本编辑器 Sublime Text；
- `CapsLock + Z`，快速打开 Zotero；
- `CapsLock + X`，快速打开书签管理器 Anybox。

## 软件快捷功能

仍然依靠了上面的切层模式：

- `CapsLock + Q`，触发屏幕截图；
- `CapsLock + W`，触发屏幕贴图；
- `CapsLock + R`，触发屏幕录制；
- `CapsLock + S`，使用 Google 搜索选中的文本；
- `CapsLock + D`，使用 Bob 翻译选中的文本；
- `Ctrl + T`，打开 Alfred 的 Anybox 插件；
- `Option + S`，打开 Bob 的输入框，输入文本后回车进行翻译。
- `Hyper + G`，打开文件管理器 Bloom 的快速切换窗口，一键直达文件夹。

## 快捷文本输入

同样是使用 Karabiner 为句号键增加了一些额外输入效果，在单独按下时依然输入句号，但是在与以下按键异同按下时，则输入特定的内容：

- `Period + Z`，快速输入下划线 `_`，日常需要输入下划线的时候有点过多了，但是又不想来回切输入法。
- `Period + E/L/comma/i`，输入 `&lt;-` 、`library()`、`%&gt;%` 等写代码时常用到的符号。
- `Period + R`，输入一些常用的正则表达式写法，使用 Keyboard Maestro 并为不同的正则表达式设置同一个快捷键，可以让这样按下时打开一个窗口，选择具体输入哪个表达式。

## 系统功能

- `Hyper + P`，快速锁屏，并将这个快捷键设置给了键盘上的按下旋钮，一键锁屏下班。

最后是附上键盘的 Vial 设置，果然几年前年轻的脑子就是好。

![image.png](./images/image.png)

![image.png](./images/image1.png)

![image.png](./images/image2.png)

![image.png](./images/image3.png)</content:encoded></item><item><title>迟到的2025年度数码产品总结</title><link>https://blog.yorks0n.com/articles/buy_digital_2025/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/buy_digital_2025/</guid><description>没过春节就不算晚！</description><pubDate>Thu, 08 Jan 2026 02:25:00 GMT</pubDate><content:encoded>12月就想写25年的年度总结，年底忙加上一直在拖，终于拖到了26年。今年是猛猛消费的一年，感觉靠消费和摸鱼缓解工作焦虑有点太严重了。26年一定克制！之前写过一篇25年的[游戏盘点](https://blog.yorks0n.com/articles/my_goy_2025/)，这里从开年盘点一下25年买了什么有意思的数码产品和服务。

## 订阅服务

### iCloud

没错，直到2025年我才开始用iCloud的付费订阅。再之前可能十多年前开过iCloud相册，那时候还是用iPod touch连接手机热点，发现出去拍照完连着热点的iPod一鼓作气把相册都同步完，直接把那时候金贵的流量跑完了，遂关了iCloud相册并在这十年中都没用过。直到今年年初，128G的手机储存实在是不够用的，正巧那时候京东上买iCloud服务打折。哪怕开了iCloud，剩余空间还是经常在5~10G内徘徊，iOS26大版本更新前后还因为剩余空间不足需要手动清理各种应用的储存。不过云相册还是有些许不便的，最大的感受就是有时候在网不好的地方，翻相册照片玩需要再稍微加载一会儿才能显示出高清版本的照片。暗暗下定决心，下次如果换手机，一定要买256G起步的（估计要iPhone 18以后了）。

### ChatGPT Plus

之前本着划算的原则，大模型一直是用API的，对于非高强度使用的价格来说省得不止一点，一个月也就十几到小几十块。年中有一阵为了用ChatGPT的图片生成与Codex尝试了开它家的付费会员，发现网页版中能够在一个对话中联想到其他对话的内容非常有意思，比只有当前会话上下文记忆的API神奇多了，之后就每个月都在续费。同时，那一阵也在高强度用CLI的编程辅助工具，CC和Codex都尝试了，发现如果在命令行工具里用API，token用量如流水，一个下午就能用掉半个月的订阅费了。后来使用强度稍微下降，没有再续费CC，而是保留了GPT和Gemini（闲鱼买的）的订阅，完全够用了。当然，最近也发现了问题，网页版ChatGPT经常问啥它都要扯到之前会话中讨论到的内容，而且有点过于谄媚，经常会有「你有做过xxxx的经验，所以做xxx非常合适」，也开始有点不适了，希望后面能再有优化。

## 数码产品

先感叹，今年闲鱼买了好多东西，实在是神奇的闲鱼。

### 蓝白色 PSV2000

开年那一阵对掌机很上头，在PC上用模拟器玩了一阵胧村正后，终于去闲鱼收了台PSV，陆续打完了十多年前就想玩的胧村正、P4G等。作为一台十几年年纪的老机器，虽然按键不是那么丝滑，但是还是忍不住感慨当时索尼的工业设计真是非常无敌，机器轻便的同时，P4G许多过场动画即使现在看起来也毫不过时。于是深刻感受到，只有能揣进兜里的掌机才是好掌机！

![psv配图](images/psv配图.jpeg)

### NS Lite

大概是受此影响，在四月份又在闲鱼收了台二手的黄色NS Lite，在上面接连打完了浪漫沙加2重制、FSN重制、月姬R重制等，最近又开了FHA的坑。虽然体积和重量都比PSV重了一些，但不到300 g的机器和现在一众超大Win掌机比还是很苗条。在NS多年积累的游戏库加成下，确实对得上「适合当前入手的第一台掌机」的称呼。

### NS2

在多年的等待后，千呼万唤NS2终于发布。预订了首发，得益于京东的神奇首发服务（毕竟卖得更贵了），在发售日当天凌晨十二点半就拿到了机器。虽然连同首发的新马车、咚奇刚、空轨1st和丝之歌在内买了几个新游戏，但很惭愧都没打完，反倒是朋友借的密特罗德生存恐惧打完了。NS2那个体积和重量，端起来玩一会儿手就酸了，因此在体验了带出去出差都没高兴拆出来玩之后，现在出去假如带NS还是会带Lite。再次感叹，只有能揣进兜里的掌机才是好掌机！

### Ayaneo Pocket Fit

今年年中有一阵安卓掌机神仙打架，在类3DS的双屏与传统形态间纠结后，预订买了台国内小厂出的Pocket Fit，用来弥补iOS上很多Gal模拟器运行不了的困境。虽然屏幕不大体积较为紧凑，塞了大电池和散热的机器实际重量也和NS1差不多了，好在手柄握把的造型还比较舒适，端久了比NS1那是舒服太多了，和NS Lite不相上下。得益于SteamDeck带来的Linux兼容层，越来越多Steam游戏也能在安卓上比较不错地运行了，只是这个没有SteamDeck的官方兼容性检测，不少游戏要自己手调各种配置，所以实际能不能运行起来全凭运气。不过既然Steam又出了新的mini主机，希望将来安卓上能运行的游戏越来越多。

![ayaneo](images/ayaneo.JPG)

### AirPods Pro 3

讲完各种游戏机，实际日常用得最多的还是这个经过多年等待的APP3。买时还蹭上了上海国补，首发85折的苹果库克来了都得从这进货。虽然比APP2的升级不多，但从APP初代换代上来，不管是续航还是降噪能力真的是史诗级提升。已经成功加入除钥匙外的每天EDC行列，几乎日均使用都在一小时以上。如果要选一个年度最实用电子产品，一定就是它了。虽然只是一次常规的硬件升级，但目前配合苹果生态最好的耳机，还就得是AirPods Pro。

### 理光GR3

今年理光更新了GR产品线，目前GR4和GR4 HDF都出了，然而首发就9k+的官方定价有些让人望而却步。年底有一阵，就很心动这种能揣兜里带到各处，随时拿出来就能拍的小机器。手机拍照目前算法加得好猛，几乎关不掉的HDR效果下总是不太自然（新出的有个Moment相机应用不错）。相机的许多操控还是远超手机上各种拍照应用专业模式，之前去迪士尼玩，想拿手机在白天拍一个低快门速度低，倒腾了半天还是没拍成。可又下不去手直接买溢价的GR4，于是又去闲鱼上买了台二手GR3。之后出门出差、旅游都会给它揣包里。定焦镜头也没有任何不适，反而感到一种「经过考虑的克制」，或者说一种可靠踏实的感觉，这种感觉在用了pebble后更加明显。又重新爱上出门拍照了！

### Pebble Steel 与 Pebble Time Steel

25年三月，沉寂了多年的Pebble重启了！Pebble公司作为智能手表的早期入局者，由于经营不善很早就被收购并最终解散。我前几年都在用 Apple Watch S7，现在已经到了既不在意运动闭合圆环，也不留意睡眠指标统计的状态，手表剩下的只有看时间和消息通知的功能（手机常年静音）。苹果剩下的只有每天一充的麻烦。在家时还好，出差旅游还得给它专门带个线，很是麻烦，于是萌生了找个长续航能看时间的替代。以前用过手环，续航是肯定能满足，但做实验经常要开倒计时，还是不太方便。很怀念戴卡西欧的日子，但查了一圈目前的卡西欧也没有续航+通知提醒兼顾得很好的型号。闲鱼收了块佳明255，功能都有，但它设置倒计时比卡西欧还麻烦，加上佳明iOS应用堪称灾难的消息推送管理，用了俩月又出了它。

兜兜转转，终于在十一月忍不住去闲鱼[买了块二手初代pebble steel](https://blog.yorks0n.com/articles/buy_pebble_steel/)。买家给换了电池，一块十年多前的手表能有一周续航、即时通知+按来源的消息推送管理，还有什么好不满意的！同时，pebble多年积累下超多创意十足的表盘，自己也试着做了一些，在低分辨率的屏幕上也能有这么多可实现的，玩物属性max。下图中就是我自己做的一块表盘，能够根据手机获取到的定位，在手表上计算出本地的日出日落，并有模拟的太阳/月亮根据当前时间计算的升起落下动画。

![pebblesteel](images/pebblesteel.jpg)

于是，还有什么不满意的？有的有的。一个月后在闲鱼又刷到一块之前一直没能搜到的Pebble Time Steel，彩色屏幕的金属款，单表头状态很好，犹豫了一两周也拿下了。彩色屏幕的显示效果还是完全不一样，同时这块表还有十天出头的续航。由于找不到特别合适的中文语言包，开始了自己做翻译、打包语言包，开始狠狠折腾。

![IMG_5615](images/IMG_5615.jpg)

关于Pebble还有好多想说的，后面再专门写文章吧。作为打开了新世界大门的一次购物，堪称年度最佳乐趣！</content:encoded></item><item><title>关于我和这个博客</title><link>https://blog.yorks0n.com/info/about/</link><guid isPermaLink="true">https://blog.yorks0n.com/info/about/</guid><description>关于我和这个博客</description><pubDate>Fri, 19 Dec 2025 13:15:49 GMT</pubDate><content:encoded>Yorkson 是我从高中开始的英文名，源自早年一部很喜欢的热血国漫。从前几年开始，因为[各种机缘](https://blog.yorks0n.com/articles/hello-again/)开始以 *Yorks0n* 在网上写东西。

## 找到我的方式

- [Yokrshire](https://blog.yorks0n.com/) 缓慢更新的博客，会把写过的东西尽量都放在这里。
- [少数派](https://sspai.com/u/yvfkdpve/posts) 上也有一些我写过的文章。
- [Telegram](https://t.me/roam_around) 加入了与 [Dayu](https://anotherdayu.com/) 等一同运营的频道，分享一些比文章更零碎的内容。
- [Steam](https://steamcommunity.com/id/Yorks0n/) 能看到我最近在PC上玩的游戏。
- [NeoDB](https://neodb.social/users/yorks0n/) 今年开始逐渐将看过的书与玩过的游戏记录在上面。
- [GitHub](https://github.com/Yorks0n) 上存放着写过且能放出来的小代码。

推荐使用 RSS 订阅博客更新：`https://blog.yorks0n.com/rss.xml`</content:encoded></item><item><title>买了一只十多年前的老 Pebble</title><link>https://blog.yorks0n.com/articles/buy_pebble_steel/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/buy_pebble_steel/</guid><description>几年前把手表从卡西欧小方块换成了 Apple Watch...</description><pubDate>Thu, 27 Nov 2025 09:48:00 GMT</pubDate><content:encoded>几年前把手表从卡西欧小方块换成了 Apple Watch S7，当时坚持闭上运动圆环、每天早上看看自己睡眠质量如何。然而几年时间过去后，发现自己已经不太在意这些参数了。虽然天天充电早已经习惯了，但偶尔遇到出差还要专门给手表带充电线，总感觉不太爽利。愈发想念之前踏实可靠的卡西欧，但作为一个手机常年静音的人，非常需要手表/手环带来的来电和消息提醒。卡西欧虽然也有心率方块，但看网上的评价消息提醒不太及时，就作罢了。前一阵买了个佳明 255，用着也不错，续航也好，但佳明在 iOS 上的 App 完全不能进行精细一点的消息推送设置，只能跟随系统。我之前用苹果表时，手机上大部分应用的消息提醒是关闭的，少部分应用开提醒但不推送到手表，只有部分im和todo应用推送到手表提醒。然而佳明的 iOS 应用并不支持根据应用设置是否推送，消息震动也只能选开或者关，因为太烦关了震动后，提醒几乎处在一个不存在的状态。

今年三月，得知 Pebble 复活时，当即预订了明年年初的 Pebble Time 2。克制的功能+长续航+漂亮的表盘，真的是非常戳中我。然而因为一开始订的 Duo 2 退掉了，最近有些迫不及待，闲鱼上观望了一阵，收了台初代的 Pebble Steel。

虽然是十年前的设备，但闲鱼上的卖家帮我换了电池，在十年后的今天还能有一周左右的续航，再想想这几年连续挤牙膏 Apple Watch，真是不争气啊！前一阵和 Dayu 感慨，哪怕新的苹果表有更好的能效，更大的电池，估计也会被更强的系统动画效果给消耗掉，还是得一天一充。

不过这个老 Pebble Steel 自带的表带实在有些惨不忍睹了，想买条 22 mm 标准表带换上，发现表盘的接口不是普通的 22 mm，搜了一下说需要一个专门的表带连接器，这都2025年了，这东西上哪找去。

![image-20251127175031215](./images//image-20251127175031215.png)

还好在网上找到了有人做的 [Pebble Steel 22mm band adapter](https://www.printables.com/model/132671-pebble-steel-22mm-band-adapter-mkiv) 模型，可以装在原本的表盘上，再延伸出一个 22 mm 表带接口。感谢这位名为 Luno 网友在多年前的无私分享，下载模型去嘉立创打印了个接头，耗时三天连运费 12.94 元，装在表上严丝合缝。虽然表体变长了点，但总算是能方便地买到兼容的表带了。

![image-20251127175049592](./images//image-20251127175049592.png)

Pebble 有个好玩的点就是各种用户自制的表盘，我也自己做了俩，一个能够在手表内计算下次日出日落的时间并显示在上面，另一个是命运石之门主题的，咱就是说还得是二次元这块。

![image.png](./images/image.png)

另一个我手表用到比较多的功能就是计时器，做实验经常会要倒数个十分钟二十分钟的，苹果手表确实方便，佳明就不太行，要选半天才能找到计时器，再按半天才能设置好。Pebble 可以自己在社区应用商店里装 Timer 应用，并且支持把上/下键的长按设为快速启动，爽得很。

![IMG_4504.gif](./images/IMG_4504.gif)

总之目前一周多用下来非常满意，更加期待明年年初的 Pebble Time 2 了。</content:encoded></item><item><title>盘点一下今年让我上头的那些游戏</title><link>https://blog.yorks0n.com/articles/my_goy_2025/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/my_goy_2025/</guid><description>趁着 TGA 还没有开始，盘点一下今年让我玩得非常快乐的那些游戏。本文分成两部分，第一部分是今年发售的游戏，第二部分是往年发售但今年玩得非常快乐的游戏。...</description><pubDate>Sun, 23 Nov 2025 13:40:00 GMT</pubDate><content:encoded>趁着 TGA 还没有开始，盘点一下今年让我玩得非常快乐的那些游戏。本文分成两部分，第一部分是今年发售的游戏，第二部分是往年发售但今年玩得非常快乐的游戏。

## 吃饭要趁早

如果一款游戏趁刚发售就玩，讨论度和热度都足够高，那种仿佛全世界都在玩的热闹氛围让人着迷。

1. **双影奇境**，如果盘点有排名，我愿意把双影排第一，电影化演出+双人配合+不严格的死亡惩罚，虽然部分关卡对平时不玩游戏的人来说强度稍高，但不行还能换手嘛。能和平时不玩游戏的朋友一起体验游戏乐趣，就低门槛高体验而言，实在是玩一个少一个的佳作。
2. **非生物因素**，之前 EA 今年发售，也能算是今年的吧。独乐乐不如众乐乐，多人合作也让部分惊悚要素变得不那么吓人，游戏后期设计没有前期那么精巧，但还是让我能和朋友们度过足够快乐的几十小时。是EA玩通过正式版让人还能想玩的游戏，非常难得。
3. **33号远征队**，足够惊喜的游戏，在我这属于瑕不掩瑜那档，能让玩不来动作游戏的我体验到和怪一来一回过招的爽快感。剧情上面我倒觉得无功无过，前期谜语人最后把故事挑明，原来是家庭伦理剧。少数缺点大概就是地图设计和引导略微缺失，以及后期数值比较崩坏吧。
4. **哈迪斯2**，这就属于那种 EA 期间玩了二十多个小时，正式版出来至今还没有打开的动力。出于对 Supergiant Games 的喜爱，还是将它放在这里，估计将来某个时候会打开来仔细玩玩新增内容吧。
5. **空轨 1st**，不得不说，老游戏重制版要是都有这个质量，那每个都卖全新游戏的价格是一点没得挑。画面和战斗都很不错，唯一的缺点大概就是有老 JRPG 剧情的拖沓，不过也是瑕不掩瑜那档。
6. **咚奇刚**，人称小马里奥奥德赛，确实好玩但是非剧情驱动的游戏，总还是不太有继续玩下去的动力。玩得不多，希望某天能打完（说实话奥德赛至今也没打完。
7. **梦之形**，几年前 demo 就玩了十个小时，一直非常期待，经历了延期终于今年玩到了。轴侧视角类似 moba 的动作肉鸽，主打一个技能和强化宝石的自由组合，玩久了套路有点固定，但这时候也已经爽玩快四十个小时了，和朋友联机其乐无穷。
8. **鸭科夫**，年轻人的第一款搜打撤，确实能体会到塔科夫类型游戏的乐趣，门槛也不那么高，要是能联机就更快乐了。虽然有 mod 能用，但是还是希望哪天能出个官方联机，和朋友们再打一次。
9. **BALL x PIT**，弹珠台幸存者，玩 demo 就很喜欢，正式版一样也爽爽玩了快二十个小时一周目通关，纯爽快。

## 好饭不怕晚

虽然今年有很多好游戏，但是这两年发现经过时间积淀的老游戏才更好玩啊！

1. **神之天平**，玩了才知道那么多人说这个游戏被画面耽误了是一点不错，披着 JPRG 外皮的刷子游戏，十分上头，几十个小时转眼就过去了。剧情也还算是吸引人，属于是每个时代人都有属于自己的超时空之钥。
2. **魔法使之夜**，不像fsn宏大，不像月姬的纠葛，是玩着就会让人感觉内心平静的作品，很像读《雪国》时的感觉。最近忍不住又开始玩一遍，只要听着音乐就仿佛回到了那个平淡的冬日故事中。
3. **FSN**，今年体会到了型月的魅力，把几个经典作品都玩了一遍，都是纯粹靠剧情就能吸引人玩几十个小时的游戏。Fate 系列早有所耳闻，但一直以来对圣杯战争啊、圆桌骑士之类历史色彩很重的故事没什么兴趣，今年玩了就一口气打完，果然又是个少男遇到少女的故事，真好啊蘑菇真有你的。真好啊真好，几乎每个人物都得到了充分的塑造，要是只用一个词来形容，就是“华丽退场”吧。
4. **月姬 R**，公主线打完：居然是纯爱！很久没看过这么纯的纯爱了。打完学姐线：果然在极致的混乱和暴力间隙，才更能体现出温馨日常的美好。在人物间对话可以明显感觉到还有很多伏笔没有解释清楚，很多人物也还没有塑造完，不知道里线重制版什么时候出。
5. **P4G**，大概是 P 系列最平凡而温暖的校园生活了吧，队友不像 P5 都是些人中龙凤，反而更像是真正身边普通且有自己喜怒哀乐的同学，也会有喜欢和不喜欢的社群。就像生活不会完美，高中生活也肯定有遗憾，这也让 P4 的日常更加轻松真实。P4 的重制版也公布了消息，但那个宣传片实在是……希望到时候做出来能卖相好一点。
6. **逆转裁判 1**，久闻逆转裁判系列大名，今年因为 iOS 上的 Delta 模拟器尝试了 GBA 版本，让我这个对律政完全不感兴趣的人都玩进去了。剧本写得很有意思，人物刻画也足够有个性，不过后续作品还没开始玩。
7. **浪漫沙加 2 重制版**，各种引导都很优秀了，但当时刚玩完 33 号以至于觉得普通的回合制还是有些平淡。中后段重复性有点高，不过作为重制版游戏很精良了。
8. **密特罗德 生存恐惧**，玩的时候明显能感到不管是地图还是技能设计都非常老道，人物性能够强，地图连通性、每次获得新能力后到达下一个区域的隐形引导也非常好。包括地图中会有明显供老手在足够熟悉地图后能达成的速通/破序设计，速通应该也是观赏性极佳。各种boss设计，要用一个词来形容就是“礼貌”，初见会感觉有点难，但经历几次试错之后，大部分怪都能几乎无伤打过。总而言之，不愧是 Metroidvania 中最经典的 metroid 部分，多年过去依旧是标杆。
9. **胧村正**，是我十年前就想玩的游戏，借着上半年买了台二手 PSV 的机会给打通了。香草社的美术实在没的说，玩法是经典的清版过关，中后期重复度有点高，但这类型不就主打一个爽快。

改天再盘点一下今年买的满意的各种玩意，上班疲惫实在是让人老想消费。

最后，不知道风暴英雄啥时候能回国服啊！</content:encoded></item><item><title>【吃了啥】新利查西菜馆</title><link>https://blog.yorks0n.com/articles/food_xinlicha/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/food_xinlicha/</guid><description>新利查西菜馆，看名字就是那种老上海西餐。由于离得不远，在过去几年里曾天天路过这家店，感觉店里人一直不多，因此从来没想尝试过。今天心血来潮过来吃了个午饭，一进店发...</description><pubDate>Wed, 12 Nov 2025 09:31:00 GMT</pubDate><content:encoded>新利查西菜馆，看名字就是那种老上海西餐。由于离得不远，在过去几年里曾天天路过这家店，感觉店里人一直不多，因此从来没想尝试过。今天心血来潮过来吃了个午饭，一进店发现其他两桌平均年龄估计都得70+，很符合我对这店的印象。

**老克勒土豆沙拉**
土豆沙拉好像也算是这边比较经典的洋气菜，土豆泥+火腿+鸡蛋+青豆+玉米粒+苹果+千岛酱，吃起来就是看起来的味道。特点是苹果不是块，而是事先和沙拉酱、部分土豆、部分鸡蛋打成酱，再和各种其他组分拌起来，不会有明显的苹果脆口，让口感更加一致的同时又有苹果香来解腻。

![IMG_4035](./images/IMG_4035.jpg)

**金牌葡国鸡**
底下是奶油、鸡腿肉，上面是鸡蛋羹的质感，不知道是先蒸后烤，还是纯烤熟的，最顶上有一层烤过才有的鸡蛋外皮，很漂亮，吃起来也很浓郁，还能吃出奶油鸡腿肉里有黑胡椒香味。

![IMG_4036](./images/IMG_4036.jpg)

**吉利猪排**
猪排比较嫩，但整体就无功无过吧，调味偏淡需要蘸辣酱油吃，主要是吃到这有点吃不下了。

![IMG_4037](./images/IMG_4037.jpg)</content:encoded></item><item><title>根据Zotero数据库追踪新发表文献</title><link>https://blog.yorks0n.com/articles/zotwatcher/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/zotwatcher/</guid><description>很长时间里，我追踪新发表文章的方式是用RSS订阅几个感兴趣的期刊网站，每天午休的时候去翻一翻，看有没有感兴趣的，同时也订阅了一些公众号，遇到感兴趣的文章推送就丢...</description><pubDate>Thu, 30 Oct 2025 09:09:00 GMT</pubDate><content:encoded>很长时间里，我追踪新发表文章的方式是用RSS订阅几个感兴趣的期刊网站，每天午休的时候去翻一翻，看有没有感兴趣的，同时也订阅了一些公众号，遇到感兴趣的文章推送就丢进稍后读列表。然而这一流程有几个比较膈应的点，一方面，RSS订阅对于专业领域内的期刊，其中能遇到自己感兴趣文章的概率较高，但是对于综合类期刊（比如CNS），大部分文章跨专业太远了，订阅其RSS大部分推送都是自己不感兴趣的；另一方面，专业相关的大文章公众号一般会发，但有些非国内作者或是中小文章，则很难见到推送，并且公众号的推荐排序真的是一言难尽。

因此，很希望能有更加贴合我阅读兴趣的文章追踪方式。也曾经想过靠关键词过滤等方式筛选，但关键词硬性匹配很容易过于严格，并且维护一份关键词库也绝非易事。前几年LLM兴盛后，动过一些靠AI来追踪文献的念头，但也没想好怎么合适地告知AI我的兴趣所在，并且将大量文章直接丢给AI进行筛选，每天消耗的token估计也少不了。

前些天偶然想到，既然我这几年已经在文献管理工具Zotero里积累了大量阅读过的文献，实际就应该以这些文献为种子，生成一份我的兴趣画像，然后再用这份画像去追踪文献。于是在用codex捣鼓了几天后，做了个脚本，这里暂且将其命名为[ZotWatcher](https://github.com/Yorks0n/ZotWatch)。下图为其在News Explorer中的订阅效果。

![image.png](./images/image.png)

## 实现逻辑

**太长不看**：ZotWatcher会利用Zotero数据库中已有文章的信息，生成一份文献兴趣索引，再将每天运行时新发表的文章与索引进行比对，找到与已有兴趣打分较高的文章作为候选文章，生成RSS供我订阅。

**详细版本**

- **获取Zotero文献库**：首先通过Zotero API获取个人积累的文献数据库，只是标题、摘要等文献元数据的话，Zotero并不限制储存容量。
- **构建文献信息索引**：将读取到的文献元数据，通过TextVectorizer进行向量化，构建FAISS索引，同时生成一份概要统计文献，包含高频出现的期刊、作者等信息。
- **抓取候选文章**：目前启用了Crossref、arXiv、bioRxiv/medRxiv的API作为新发表文章的来源，同时会根据统计到的高频期刊进行补充抓取。后续可能会加上Altmetric的热门文献。
- **文献打分**：首先利用FAISS检索新获取文献与已有数据库的相似度，同时结合ScimagoJR的期刊SJR质量、时效性、作者等进行加权打分。
- **文献过滤**：根据打分和指定的输出文献数量（默认是20，避免overwhelming），同时筛选只保留近七天内的文章、限制预印本比例不超过30%，获得最终输出。
- **RSS生成**：将候选文章整理成RSS格式，使用GitHub Actions每天早上6点运行，并把运行结果以GitHub Pages形式发布方便使用其他软件订阅。

## 如果你也想试试

本仓库地址为：[ZotWatch](https://github.com/Yorks0n/ZotWatch)

可以Clone或Fork后，需要在设置中配置几项必要信息，例如自己的`ZOTERO_API_KEY`与`ZOTERO_USER_ID`等，这些信息的获取方式请见README页面，这里就不赘述了。

每次检测到`git push`行为或次日六点后该仓库会自动运行，并生成结果。需要留意直接给出的GitHub Pages地址如果打不开，需要在末尾加上`/feed.xml`（因为没有生成对应的index页面，直接访问可能打不开）。</content:encoded></item><item><title>解决远程服务器上Singularity联网问题</title><link>https://blog.yorks0n.com/articles/fix_singularity_connection_issue/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/fix_singularity_connection_issue/</guid><description>docker 系列的镜像国内直连不了，真是太费劲了。</description><pubDate>Wed, 15 Oct 2025 08:40:00 GMT</pubDate><content:encoded>这几天遇到个项目，需要在服务器上用到 Nextflow 流程运行一个Singularity镜像（`singleron-RD/wf-single-cell`）虽然服务器能联网，但因为某些众所周知的原因，Singularity（或 Apptainer）完全无法从 DockerHub 直接拉取所需镜像。倒腾了一下午，试了各种办法，终于搞定了，这里记录下最终可行的解决方案。

## 背景

在服务器上运行某Nextflow流程时，需要从以下两个镜像拉取容器：

- `docker://ontresearch/wf-single-cell:sha0fcdf10929fbef2d426bb985e16b81153a88c6f4`
- `docker://ontresearch/wf-common:sha91cd87900c86f05bf36d8c77b841b8fda5ecf3aa`

但由于某些原因，所有 docker 系列的网站直连都打不开，直接拉取失败。

## 方案一：Mac上下载好镜像包再传给服务器（不可行）

一开始想在 Mac 上直接下载好镜像包，但是发现 M 系列芯片的 Mac 由于架构原因，并不支持直接安装 Singularity 或是 Apptainer。于是尝试在本地通过 Docker 启动一个运行 Apptainer 的环境再进行下载。

```
docker run -it --privileged \
  -v $PWD:/data \
  ghcr.io/apptainer/apptainer:latest bash

cd /data

apptainer pull ontresearch-wf-single-cell.sif docker://ontresearch/wf-single-cell:sha0fcdf10929fbef2d426bb985e16b81153a88c6f4

apptainer pull ontresearch-wf-common.sif       docker://ontresearch/wf-common:sha91cd87900c86f05bf36d8c77b841b8fda5ecf3aa
```

然而问题在于，Mac（ARM 架构）上生成的 `.sif` 文件无法在服务器（x86 架构）上运行，会报出架构不匹配错误，因此此方法虽然能成功获得 sif 文件，但获取的文件在服务器上无法运行。。

------

## 方案二：通过 SSH 代理转发使用本地代理下载（可行）

因为不想在服务器上单独配置一套代理，发现可以通过 SSH 反向端口转发，让服务器直接使用 Mac 本地代理，从而顺利下载容器镜像，实现流程如下：

### 1. 建立 SSH 反向代理通道

假设本地代理端口为 `6152`，在连接服务器时建立反向映射：

```
ssh -p 22 -R 1080:127.0.0.1:6152 usr_name@remote_ip -t zsh
```

连接成功后，服务器可以通过 `127.0.0.1:1080` 访问外网。

### 2. 在服务器上设置代理环境变量

```
export https_proxy=http://127.0.0.1:1080
export http_proxy=http://127.0.0.1:1080
```

### 3. 在服务器上准备镜像存放目录

```
mkdir -p $HOME/containers &amp;&amp; cd $HOME/containers
```

### 4. 使用 Singularity 拉取镜像

```
singularity pull ontresearch-wf-single-cell.sif docker://ontresearch/wf-single-cell:sha0fcdf10929fbef2d426bb985e16b81153a88c6f4
singularity pull ontresearch-wf-common.sif       docker://ontresearch/wf-common:sha91cd87900c86f05bf36d8c77b841b8fda5ecf3aa
```

下载完成后，镜像文件保存在：

```
$HOME/containers/
```

### 5. 在 Nextflow 配置中使用本地 SIF 文件

为了避免 Nextflow 再次联网下载，可在 `nextflow.config` 中指定本地容器路径：

```
process {
  withLabel: singlecell {
    container = &quot;$HOME/containers/ontresearch-wf-single-cell.sif&quot;
  }
  withLabel: wf_common {
    container = &quot;$HOME/containers/ontresearch-wf-common.sif&quot;
  }
}
```

这样 Nextflow 会直接使用本地镜像文件，而不会再尝试从 DockerHub 获取。

------

## 五、总结

真是太费劲了！</content:encoded></item><item><title>又是一个Mac软件列表</title><link>https://blog.yorks0n.com/articles/another_mac_software_list/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/another_mac_software_list/</guid><description>整理了下Mac里常用的各种软件，发现乱七八糟还真不少。</description><pubDate>Wed, 16 Apr 2025 09:15:00 GMT</pubDate><content:encoded>摸鱼整理一下我在用的Mac软件列表，又有谁不爱List呢？

## 效率

- [**Things 3**](https://culturedcode.com/things/)（付费）：老牌GTD应用了，UI美观简洁又足够强大，3大版本更新时就买了，肯定算是用回本了。这些年还试过买了[Sorted](https://www.sortedapp.com/)，但性能一般，而且多年不更新了，还是Things功能又够用又克制。
- [**MailMate**](https://freron.com/)（免费版本）：一个持续更新了十多年的邮箱应用，UI就充满了可靠性，比各种加入乱七八糟AI功能的邮箱应用好多了。前一阵更改了付费模式，可以短期订阅，订阅过期后退回到免费版本，但与完全未付费的免费版还有所不同，详见「[MailMate can run in one of three different modes](https://freron.com/pricing/)」。
- [**Raycast**](https://www.raycast.com/)（免费版本）：曾经买过[Alfred](https://www.alfredapp.com/)，但是Raycast作为后起之秀，在免费版足够好用的同时支持各种插件，并且在持续开发。不过新出的功能基本都要求订阅，日常使用而言免费版足矣。
- [**Karabiner-Elements**](https://karabiner-elements.pqrs.org/)（免费）：免费但是无敌强大的一款键盘按键映射工具，可以让几乎每个按键都成为快捷键的组成部分。例如我就设置了Caps Lock+各种字母，配成快速将应用切换到最前台（需搭配Keyboard Maestro或是Alfred等应用）；以及句号+各种字母，设置成常用短语的快捷输入。由于觉得Karabiner-Elements本身的配置文件写起来过于复杂，我又使用[Goku](https://github.com/yqrashawn/GokuRakuJoudo)来为其写配置文件，之前还专门写过一篇介绍文章，见「[Karabiner 助力，让你的键盘操作快人一步](https://sspai.com/post/73827)」。
- [**Keyboard Maestro**](https://www.keyboardmaestro.com/main/)（付费）：超好用的自动化脚本App，有些功能与Alfred或是Raycast有重叠，但也有很多独到的功能。比方说我用它和Karabinder组合配置了很多应用切换、快捷输入的组合键，以及快速目录切换等功能，而其全部实力远不止于此，感兴趣可看Reddit上的这个帖子「[What are your favorite Keyboard Maestro automations/use cases?](https://www.reddit.com/r/macapps/comments/1gajv56/what_are_your_favorite_keyboard_maestro/)」。
- [**Numi**](https://numi.app/)（免费版本）：一个UI美观精致的计算器，免费版够用。


## 系统和菜单栏

- [**Amphetamine**](https://apps.apple.com/us/app/amphetamine/id937984704?mt=12)（免费）：用于阻止Mac进入休眠状态，功能强大UI简洁，并且还是免费软件。有时候在挂着下载或者后台运行程序时会用到它，预估一个结束时间，防止在此前进入休眠。实际软件还能根据多久没有下载流量、指定软件的运行状态保持唤醒，但我通常就直接设置个时间。
- [**Bartender 5**](https://www.macbartender.com/)（付费）：用于隐藏菜单栏应用图标。软件本身用着没什么问题，但每次Mac有大版本升级它都要重新购买，已经买了第三次了。前一阵有一些所属公司变动的风波，但想着买都买了，就继续用着，之后估计不会再买了，可能会转向用[Ice](https://github.com/jordanbaird/Ice)或是[Barbee](https://apps.apple.com/de/app/barbee-hide-menu-bar-items/id1548711022?l=en-GB&amp;mt=12)，到时候再说。
- [**BetterDisplay**](https://github.com/waydabber/BetterDisplay)（免费版本）：控制外接显示器亮度和分辨率，软件可付费解锁更多功能，但对我来说免费版本足够用了，一般就用它配合快捷键调整外接显示器亮度。之前也用过[Lunar](https://lunar.fyi/)，但不记得有啥小问题，反正改用BetterDisplay了。
- [**BetterMouse**](https://better-mouse.com/)（付费）：鼠标驱动程序+按键映射。用了罗技的Master 3很多年，苦option+久矣，怎么一个鼠标驱动能做那么多复杂的功能，甚至还带AI和语音识别。之前试用BetterMouse有的键识别不出来，最近发现都能识别了，就买来稍微配置了下，和官方驱动用起来差别不大。美中不足是切换滚轮滚动模式的键被我映射到了F1用于启动截图，但时不时会失灵，变回切换平滑滚动去，需要重启软件才能恢复。
- [**Bob**](https://github.com/ripperhe/Bob)（付费）：划词翻译+OCR。从它还是免费版时就开始用，上了付费版也第一时间买了，每天高强度使用，OCR也很方便。有很多模仿Bob的免费/付费软件，但我Bob用习惯了。
- [**Eye Monitor**](https://apps.apple.com/us/app/eye-monitor-break-reminders/id1527031341)（免费版本）：定时休息提醒。Eye Monitor会根据鼠标或键盘活跃的时间计时，连续活动一定时间后提醒进行休息，一段时间不用后计时归零，防止盯着屏幕太久不动。之前也试过番茄钟[Flow](https://apps.apple.com/hk/app/flow-focus-timer-%E5%B0%88%E6%B3%A8%E6%B8%85%E5%96%AE-%E7%95%AA%E8%8C%84%E9%90%98%E5%B7%A5%E4%BD%9C%E6%B3%95/id1423210932)，足够轻便好用，但要手动启动和停止还是麻烦了点。
- [**Itsycal**](https://www.mowglii.com/itsycal/)（免费）：菜单栏的日历软件，小巧精致，UI很圆润可爱。
- [**Keka**](https://www.keka.io/zh-cn/)（免费）：一个经典的Mac压缩解压缩应用，早年图标非常惊悚，现在已经很可爱了。Mac自带的压缩文件酷爱往压缩包里掺进奇怪的目录，发给别人在Win下打开经常会引起困惑。另有[The Unarchiver](https://theunarchiver.com/)也很好用。
- [**Rectangle Pro**](https://rectangleapp.com/)（付费）：窗口管理的免费付费应用真是太多了，最早用过[Magnet](https://magnet.crowdcafe.com/)，后来乱七八糟尝试过一些，后来连[Raycast](https://www.raycast.com/)里都窗口管理插件，但我最终选了Rectangle Pro。Rectangle免费版就有不错的功能，但我最终因为一个Window Throw功能选用了它的Pro版，简单来说就是个快捷键配合鼠标移动方向的鼠标手势，用来用去这个操作最顺手。
- [**Stats**](https://github.com/exelban/stats)（免费）：状态栏系统状态监控。最早买过[iStat Menu](https://bjango.com/mac/istatmenus/)，后来发现几乎只用得到里面的网络流量监控功能，就切到免费开源的Stats了，颜值够高，功能也足够用了。
- [**Syntax Highlight**](https://github.com/sbarex/SourceCodeSyntaxHighlight)（免费）：开源的Quick Look插件，为空格预览添加语法高亮。
- [**NeatDownloadManager**](https://www.neatdownloadmanager.com/index.php/en/)（免费）：在Win上最喜欢的下载工具是[IDM](https://www.internetdownloadmanager.com/)，Mac上没有，找来找去最好用的是这款NDM，安装包仅1.4 Mb，但功能足够强大，配合浏览器插件能让许多浏览器中只能单线程下载的文件变成多线程，快了不止一点。

## 隐私与安全

- [**1Password**](https://1password.com/)（订阅）：老牌密码管理软件，用了有快十年了，截至写稿子时存了594个条目。8.0大版本后转向了Electron，导致Mac上启动没有之前版本丝滑了，但似乎没有其他更好的选择。曾经短暂试过[Bitwarden](https://bitwarden.com/)和[KeePass](https://keepass.info/)等其他方案，但在尝试时都或多或少有些不趁手的小毛病。另外此类密码管理服务我不是很放心自己部署，一旦备份整不明白损失太大了，还不如花点钱来解决（大品牌出问题大家一起完）。Mac和iOS自带的密码也很方便，但是添加和编辑一些额外信息不太方便，比如存软件许可证和服务器信息时。

## 阅读

- [**Cubox**](https://cubox.pro/)（订阅）：稍后读工具。很早前就开始用，兜兜转转试了好多个，中间一度切到[Omnivore](https://docs.omnivore.app/zh/)，可惜后者被收购后停止运营了，又切换回来。[GoodLinks](https://goodlinks.app/)现在的版本也不错，不过Cubox能一起收Newsletter，读起来更方便些，价格又比[Readwise](https://readwise.io/)便宜，就用它了。
- [**News Explorer**](https://betamagic.nl/products/newsexplorer.html)（付费）：本地RSS应用，前一阵在Reddit上看到频繁有人提到，就买了个试试，现在已经完全用它读RSS了，本地使用iCloud同步信息，同时支持设置关键词过滤。之前用[Unread](https://www.goldenhillsoftware.com/unread/)登录[Inoreader](https://www.inoreader.com/)，也是免费版就足够用了。
- [**Zotero**](https://www.zotero.org/)（免费）：免费文献管理应用的翘楚了，随着版本更新也多了很多新功能，例如PDF阅读器等，但我总觉得内置的PDF阅读器性能很差，因此还是在用PDF Expert读。自带的免费同步空间很小，但支持设置第三方Webdav同步，我以前用[坚果云](https://www.jianguoyun.com/)，后来改用[InfiniCLOUD](https://infini-cloud.net/en/)，免费版的储存空间就足够了。
- [**Anybox**](https://anybox.app/zh-CN)（付费）：如其描述，确实是个接近完美的书签管理器，早期有许多小问题，例如不支持文件夹、标签不够智能等，但随着更新迭代已经具备了完备的功能，因此终于换掉了[Raindrop](https://raindrop.io/)，改为完全用Anybox管理书签，性能强了不是一点半点，详见「[从Raindrop迁移到了Anybox](https://blog.yorks0n.com/posts/change_to_anybox/)」。
- [**PDF Expert**](https://pdfexpert.com/)（付费）：老牌PDF阅读器，曾经进慈善包时候几十块买断的，大版本更新后加了很多AI功能，曾经的买断也只能用基础功能，但也足够用。相比于许多其他PDF阅读器UI更美观，同时有好用的分屏功能。

## 笔记

- [**Drafts**](https://getdrafts.com/)（免费版本）：纯文本临时笔记。有时复制了个大段文字，想选择其中一部分，或者想临时写一段东西发给别人，我都会在Draft中先编辑好再发送。有付费订阅，但免费版足够用，支持iCloud同步很方便。
- [**flomo**](https://flomoapp.com/)（免费版本）：卡片笔记。之前付费过一段时间，后来发现不算常用，免费版也够了，用于记一些图文都需要的临时笔记。像少楠曾经说的，能同步确实很好用，有网页版也真的很好用，经常在做旅游计划的时候，Win和Mac来回切，搜集到的信息就临时存在flomo里。
- [**Notion**](https://www.notion.com/)（付费）：现在也是有名的笔记应用了，用了好多年，几乎所有近些年的工作写作笔记都是记在Notion里的，教育版免费的政策太无敌了，一整个套牢。模仿者很多，笔记应用也层出不穷，但我一直在用Notion。
- [**Typora**](https://typoraio.cn/)（付费）：也是个很早就有的markdown编辑器，出正式版后收费了，就支持了一份，但日常很少用，宁可拿Sublime Text写，或者Notion里写完再导出。

## 开发与编码

- [**Ghostty**](https://ghostty.org/)（免费）：终端应用，之前一直用[iTerm2](https://iterm2.com/)，最近跟风试了试Ghostty，用着也挺顺手就切过来了。
- [**Sublime Text**](https://www.sublimetext.com/)（免费版本）：纯文本编辑器，用了很久很顺手，性能也很好。想找类似的也可以试试[CotEditor](https://coteditor.com/)，另一个免费原生纯文本编辑器。
- [**Rstudio**](https://posit.co/download/rstudio-desktop/)（免费）：日常写R比较多，所以没得选。

## 文件传输

- [**Blip**](https://blip.net/)（免费版本）：用于Mac向其他平台传输文件，类似于[LocalSend](https://localsend.org/zh-CN)，但可以不在同一局域网内，个人非商用免费，试了试速度还可以就用着了，不会像LocalSend那样，启动后要等一会儿才能加载出其他设备。
- [**Cyberduck**](https://cyberduck.io/)（免费）：老牌ftp工具，一般用于往服务器上传数据。

## 图像处理

- [**Affinity Designer 2**](https://affinity.serif.com/zh-cn/designer/)（付费）：一代就买了，二代出的时候趁着折扣买了Affinity系列几个软件的通用许可，但实际上在用的也只有Designer，主要用来画些模式图，或者处理R等各种软件导出的pdf格式图片。小问题还是有的，比如Designer中对位图的处理功能非常非常弱，但Photo中处理照片又很臃肿，因此要处理照片我更喜欢用：
- [**Pixelmator Pro**](https://www.pixelmator.com/pro/)（付费）：也是很早就买断的软件，里面的智能创建选区的功能非常非常好用，偶尔有编辑照片的活也都会拿它处理。前一阵被Apple收购了，希望至少能继续维护，维持现状不增加新功能也足够了。
- [**ImageOptim**](https://imageoptim.com/mac)（免费）：图像压缩。免费+本地，用了蛮久，没啥不满意的。
- [**LICEcap**](https://www.cockos.com/licecap/)（免费）：小巧精致的一个录屏应用，可以直接将录制片段保存为gif，偶尔做操作的小动画展示很合适，安装后仅有2.2 Mb。
- [**Longshot**](https://longshot.chitaner.com/)（付费）：截屏软件，功能类似另一个我用了非常久的截图应用[Snipaste](https://zh.snipaste.com/)，但是后者Mac上一直不太更新。Longshot相比之下多了二维码OCR和滚动截图等功能，操作逻辑又类似Snipaste（Update：截至目前Snipaste已经有了Mac 2.0正式版，支持二维码扫描但还没有滚动截图）。类似截图应用还推荐[Shottr](https://shottr.cc/)，轻量又良心，不过操作逻辑不是很习惯，就没有去用。
- [**Gifski**](https://gif.ski/)（免费）：小而美的视频转gif应用，不太常用。

## AI

- [**Cherry Studio**](https://cherry-ai.com/)（免费）：用于调用各种AI的API。之前用过[OpenCat](https://opencat.app/zh-Hans/)和ChatX，但前者有些代码框在复制时会多复制一些额外字符，后者某个时候突然下架了，那时候发现了Cherry Studio，把各种API配置完，现在专用这一个了，希望早日出iOS版。</content:encoded></item><item><title>Vita3K存档转移到PSV实机</title><link>https://blog.yorks0n.com/articles/vita3k_to_psv/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/vita3k_to_psv/</guid><description>模拟转转移到psv实机。</description><pubDate>Thu, 20 Mar 2025 04:13:11 GMT</pubDate><content:encoded>查到的存档转移方式都是从PSV实机转移到Vita3K模拟器中，但我最近整了台实机，准备把之前模拟器里胧村正的存档转移到PSV机器上，查了不少帖子才找到办法，在此记录一下转移过程。

1. 在实体PSV上，打开游戏并创建一个存档，到保存后退出游戏。
2. 在实体PSV上，利用存档管理器导出存档。导出后的**存档位置**位于`ux0://data/savegames/[游戏编号，胧村正为PCSG00150]/[存档栏位编号，例如第一个为SLOT0]`
3. Vita3K的存档位于`path_to_vita3k\portable\ux0\user\00\savedata\[游戏编号如PCSG00150]`，将此处的 `NinPri_PSV.dat` 复制到上面的**存档位置**并替换文件，不要动存档位置处的 `sce_sys` 文件夹。
4. 启动PSV上的存档管理器，将对应存档栏位的记录恢复到游戏。

这时进游戏就能看到PC上的存档了。</content:encoded></item><item><title>SnapGene创建多外显子基因结构</title><link>https://blog.yorks0n.com/articles/snapgene_create_structure/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/snapgene_create_structure/</guid><description>记录一下如何在SnapGene中为一段基因组序列，添加多个不同外显子/CDS的完整结构。...</description><pubDate>Thu, 20 Feb 2025 08:00:00 GMT</pubDate><content:encoded>记录一下如何在SnapGene中为一段基因组序列，添加多个不同外显子/CDS的完整结构。

这里以拟南芥的序列为例，比方说选择这个由三个外显子（三段CDS）组成的AT4G10310(HKT1)。

![image.png](./images/image.png)

首先下载该区域的全长基因组序列，这里简单起见就直接下载TAIR上的，也可以下载别处带有启动子等额外信息的序列，该序列在Sequences部分的full length genomic。

![image.png](./images/image%201.png)

点击进入后在序列底部有Copy Sequence按钮，点击复制序列。

![image.png](./images/image%202.png)

打开SnapGene，选择 New DNA or RNA File，贴入刚刚的序列，选择线性DNA并输入文件名，点击OK确认。

![image.png](./images/image%203.png)

接下来后退页面回到Sequences处，点击full length CDS，进入并复制全长的CDS序列（或者cDNA，按需要来），并到SnapGene中点击左侧的序列比对，将刚刚的CDS序列与基因组序列进行比对。

![image.png](./images/image%204.png)

此时在Map界面能看到CDS的部分比对到了基因组上，内含子区域显示为空缺。

![image.png](./images/image%205.png)

之后点击底部的Sequence，切换到序列面板，从第一个开始比对上的位置（ATG）开始选中序列，一直拖动直到选中最后一个比对上的位置（终止密码子TAA），在顶部点选Feature-Add Feature。

![image.png](./images/image%206.png)

在弹出窗口中随意输入Feature名称（这里我输入了CDS），并在Type处为序列类型选择为CDS，点击OK进行创建。

![image.png](./images/image%207.png)

这样得到的是没有区分出内含子区域的结构，接下来我们为其拆分出内含子。

在序列比对的Sequence界面，从第一个内含子的起始到第一个内含子结束选中序列，再去Feature菜单中选择Create Feature Segment，弹出界面中就会将完整的结构按选中位置进行拆分。

![image.png](./images/image%208.png)

再点击选中内含子区域的片段，按右侧的删除片段，即可创建第一个内含子，重复此过程直到所有内含子都添加完成。

![image.png](./images/image%209.png)

最后构选上Translate this feature in Sequence view，即可将序列按照CDS翻译为氨基酸序列。

![image.png](./images/image%2010.png)

![image.png](./images/image%2011.png)

记得保存得到的文件，就完成了。</content:encoded></item><item><title>Rstudio也能用GitHub Copilot了</title><link>https://blog.yorks0n.com/articles/rstudio_with_copilot/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/rstudio_with_copilot/</guid><description>希望我不是最后一个知道的。</description><pubDate>Fri, 27 Dec 2024 04:00:11 GMT</pubDate><content:encoded>之前在VS Code中体验过Copilot的自动补全，大为震撼，但是其他IDE写R的体验都不是很好，就没有日常用起来。最近偶然一搜，发现说Rtudio里也能用Copilot的自动补全，赶紧配置了试了一下。

注：此过程适用于Mac上英文版Rstudio，并且需要保证有良好的网络环境。

## 配置过程

首先将Rstudio更新到最新版，打开Rsutio，由于登录GitHub可能需要良好的网络环境，因此需要先给Rtudio设置http代理。首先在Rtudio中运行以下命令，打开`~/.Renviron`处的一个配置文件。

 ```
 file.edit(&apos;~/.Renviron&apos;)
 ```

在打开的文件中加入http代理设置如下，设置完后记得保存。

```
http_proxy=http://proxy.dom.com/  #代理服务器地址，或者为http_proxy=http://ip地址:端口号
http_proxy_user=user:passwd #用户名和密码，没有用户名和密码时可省略此行
```

随后在顶部菜单栏选择Tools - Global Options

![image-20241227103247146](./images//image-20241227103247146.png)

最下面一栏直接就有Copilot的选项，选中并在顶部启用，再登录自己的GitHub账号。

![image-20241227103503312](./images/image-20241227103503312-5266905.png)

如果网络条件不佳，可能会遇到GitHub登录页面打不开的情况。如果是网页上显示**Congratulations, you&apos;re all set!**，但是Rsutio中还是一直在加载，说明给GitHub配置的http代理有问题。

如果步骤正确，此时会显示登录的账号名称：

![image-20241227104214859](./images/image-20241227104214859-5267336.png)

这时按说就能正常使用Copilot了。

## 试用

我试着写了两行注释，其他部分都让Copilot帮我补全，运行正常。

```r
# generate some data to draw heatmap &lt;- 这行是我写的
set.seed(123)
df &lt;- expand.grid(x = 1:10, y = 1:10)
df$z &lt;- rnorm(nrow(df))

# load the ggplot2 package
library(ggplot2)

# draw a heat map with ggplot &lt;- 这行也是我写的
ggplot(data = df, aes(x = x, y = y, fill = z)) +
  geom_tile() +
  scale_fill_viridis_c() +
  theme_minimal() +
  theme(legend.position = &quot;bottom&quot;) +
  labs(title = &quot;Heatmap of z values&quot;,
       x = &quot;x values&quot;,
       y = &quot;y values&quot;,
       fill = &quot;z values&quot;)

```

画出的图

![image-20241227104417598](./images/image-20241227104417598-5267458.png)

赶快体验一下吧。</content:encoded></item><item><title>双十一买了啥</title><link>https://blog.yorks0n.com/articles/buy_11/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/buy_11/</guid><description>最近太忙了，半个多月前就打完了草稿，但一直没空更新，趁偷闲更新一下。 iPad mini A17 Pro...</description><pubDate>Thu, 05 Dec 2024 10:16:00 GMT</pubDate><content:encoded>最近太忙了，半个多月前就打完了草稿，但一直没空更新，趁偷闲更新一下。

## iPad mini A17 Pro

赶上国补的85折买的，首发破发的苹果还得是国补。虽然是不用加400就能上air的价格，但早就想买个mini日常娱乐用。到手后又配了大康的膜和咸鱼淘的微瑕紫色双面夹，发现不如橙色的亮眼，有些后悔，还是今年新出的紫色更好看。贴膜后屏幕摸起来不再涩涩的，也不担心丢在桌子柜子上刮到机器了。非常满意，几乎每天回到家就捧着它。现在每天白天看屏幕的时间太久了，回家看手机的时候总会觉得屏幕太小，很疲惫，mini的大小就刚刚好，既够大，又不至于大到不想捧着它。大部分时候我拿它看看b站的视频，或是看会儿直播（之前只用手机就不太会看直播，看屏幕久了太累了）。同时，用mini看微信读书也非常舒适，之前曾经在手机上用过，但那个屏幕太小，读书总不太得劲，宁可去用kindle看。我一直觉得看书这种事，偶尔导入一下书，其他时候只用kindle也不大麻烦，但现在发现用起来方便真的太重要了，能极大促进我拿起来读书的欲望，甚至让我第一次去充了个微信读书会员。

## caldigit TS3 plus雷电拓展坞
不知道是最近压力大还是双十一前后，购物欲望老强了，新的Mac mini M4也让人看着就心动。然而我的M2 16+512才买一年多，用着也没啥不妥，纠结之下就没买新的Mac mini。于是寻思着买点其他的给自己一点快乐，某天突然想到我的Mac mini的HDMI接口可能是有点松垮，加上经常会去机器上插拔优盘等，于是老会碰到HDMI线，让屏幕黑屏，这时候就要重新去动一动那个线，并且此趋势近期有愈演愈烈的倾向，便打算买个扩展坞。既然要买，准备买个雷电接口的，可那时去看群友挂在闲鱼上的品相价格俱佳的TS4已经被卖掉了，搜了搜有洋垃圾plugable实在不咋好看，就降了降六百多收了个闲鱼上的TS3 plus。Caldigit的这几个扩展坞还都是DP的接口，相比HDMI接口也更稳固一些。虽然旧的这款是DP 1.2的，好在接我4K 60 hz的旧LG显示器也完全足够了。顺便收拾了一下桌子，把Mac mini放在升降台下，扩展坞放在升降台上，插拔优盘很方便，也不再会黑屏了。把我之前的一个爱国者固态也长期插在扩展坞上，休眠或重启后也不会断连，美中不足是扩展坞老是温温的，不知道夏天会不会太热。</content:encoded></item><item><title>文献一团乱麻？试试PARA管理方法</title><link>https://blog.yorks0n.com/articles/para_and_zotero/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/para_and_zotero/</guid><description>文献积累——学术生涯的外部记忆 在科研之路上，你想要积累哪些知识？...</description><pubDate>Fri, 29 Nov 2024 05:30:00 GMT</pubDate><content:encoded>## 文献积累——学术生涯的外部记忆

&gt; 在科研之路上，你想要积累哪些知识？
&gt; 

有没有过这样的经历？你正在准备一个重要的研究报告或论文，需要找到那篇关键的文献，但却在堆积如山的文件和资料中找不到它。或者你读过一篇很好的文献，但当你想引用它的时候，你却忘记了它的具体内容。

在一些科幻作品中，存在“外部记忆装置”的设定，其中的人物往往不将全部信息记在脑中，而是在需要时从外部记忆中调取内容。如今我们的现实已经与之颇有些相似：我们不会记住每一个具体的知识细节，浩如烟海的内容爆炸也不允许我们这么做，但我们通常知道去哪里找到这部分知识。当下，电脑和手机已经成为我们肢体的延伸，搜索引擎强大的检索功能，赋予我们按照需求取用知识的能力。

![image.png](./images/image.png)

而在科研道路上，经年累月的学习不但锻炼着我们的实验技能，积累下来的知识同样是我们学习道路上宝贵的财富。在此过程中，我们读过的每一篇文献，被我们记住的不是其中具体的语句，而是各项工作中的主要结果和结论。但在有些时候，比方说想参考某个方法做个相似的实验，或是写作背景综述时，我们会回忆起曾经看过的文章，会去找出最原始的文章查看更多细节。这时，曾经整理过的文献便摇身一变，担当起我们学术生涯外部记忆的职责。

![image.png](./images/image%201.png)

## 为什么文献常常乱作一团？

那么，为什么明明每一篇文献都有明确的主题和关键词，整理起来却依旧存在非常多困难呢？举个例子，说有一篇文章，“如何做出一盘无敌好吃的小炒肉”，里面从肉的选购、处理、调味到烹饪方法一应俱全。你看完后，觉得非常好，这么棒的技巧我一定要学会，你会把它收在哪？

- 菜谱 —— 没错，再怎么说这也是个菜谱，放这准没错
- 年夜饭菜单 —— 今年的年夜饭由你掌勺，正巧家里有人最爱吃小炒肉，放这备着
- 如何买菜 —— 本文的肉类选购部分讲得太清晰了，常常温习准能以后买菜不踩坑
- 常用调味料 —— 刚搬了新家，需要买些调料，你正在想买什么合适
- ……

如果从上面几点出发，这些归类方式似乎都有各自的道理，这也是信息管理有时会比较困难的原因：在不同的场景下，相同的内容可以有不同的分类方式，并且往往没有对错之分。

因此我觉得，好的文献管理思路比工具更重要。现在能用来做文献管理的工具层出不穷，Endnote也好，Zotero也好，网上都能找到非常详细的用法教程。但是假如只有工具，没有恰当的内容组织思路，那工具里的文献也会堆成一团乱麻。我更想提供一个框架，让每个人可以根据自己的需要，将内容以一种便于寻找的方式组织起来。

&gt; 我们的目的：让内容便于被找到。
&gt; 

## 什么是PARA方法？

在之前的很长时间里，我一直隐约觉得，自己整理的文献资料库，其中的各个文件夹彼此之间没有明确的分隔关系，以至于想存一篇新文章的时候，要纠结半天放在哪。纠结完存进去后，要找来用的时候又找不出来这篇文章了。后来偶然间了解到了一种称为PARA的信息整理方法，它将内容分类为项目、领域与资源几个大类。或许它不是最好最完美的，但是相比于没有框架的时候，已经有了质的飞跃。也因此，我今天将其分享给大家，如果你们也遇到过相似的困扰，可以尝试一下这个方法。

所谓PARA，其实是Tiago Forte提出的一种组织信息的思路。其实，PARA分别代表Projects（项目）、Areas（领域）、Resources（资源）和Archives（归档）。

![image.png](./images/image%202.png)

这样讲可能比较抽象，举个我自己的例子，比如我关注基因组学和生物信息学，我所做的课题也与之有关，相关分析做得好可以帮助我产出成果，做不好则毕业都很费劲，我**需要为此负责**，因此**基因组学**就可称作我关注的一个**领域**。同时，我的课题是一个**物种的基因组测序项目**，从我开始着手找资料开始，历经测序、组装和分析，直到文章发表结束，因为能划分出非常**明确的开始和结束时间**，因此这个课题属于一个**项目**。同时，我又对**平面设计**比较**感兴趣**，会去看一些相关的书籍和学习资料，这些东西我看着会觉得很有意思，但如果不看也不太影响我完成课题，于是可以算作**资源**。另外，假如我之前有个项目已经做完了，已经完成项目的内容我当然不需要经常去关注，那它就可以被划到归档。

![image.png](./images/image%203.png)

然而，领域与项目、资源之间并不是独立的，而是可以互相滋养

**通过项目来打磨提升领域**——比方说，我关注**基因组学**，但是只靠看一堆基因组相关的文章提升实在有限，必须要自己去实际做一些项目来锻炼，在项目中熟悉各部分的流程，并实际掌握操作的技能。

**通过资源支撑领域域** ——我们日常看的各种文章、资料，大部分都属于资源而非领域，正如上面讲到，我们没法只靠读来掌握某些内容。但是每天的精力是有限的，假如分配给太多方面，面面俱到也很困难。于是更好的方法是**基于领域 （或者将来潜在的 Area）作为精进的方向，然后把资源当做领域的基石和养分**。

![image.png](./images/image%204.png)

## 如何将PARA方法应用在组织文献中

不过，要想用这种方式来管理自己的文献，首先需要花点时间想一想，对自己来说，究竟想要积累哪些知识？

这里先来讲讲我的，我在项目中放入了刚刚提到的物种测序项目，因为这是我的课题；在领域中包含了基因组学，数据可视化，生物信息学等，因为这是我的专业方向，同时与我的课题息息相关；在资源中放入了平面设计，认知与思维方式，效率，以及语言，因为我对这些方面非常感兴趣；最后，归档中有我之前做过的一个项目，某个物种的耐盐基因筛选，它已经结束了，于是进了归档。

这个清单的长度当然没有明确的限制，但是当你打算往自己关注的领域里放入二三十个主题时，也得掂量掂量有没有足够的精力。创建一个清晰的清单，能让你对自己想要积累知识的边界更加明确，就可以据此有意识地、战略性地决定看或者不看某篇文章，决定某个拖了很久的工作究竟是赶快弥补还是尽快放弃它。 相反，如果你不为自己定义清单，就会被不断拉着、推到别人的项目中去。比如，CNS新出了一堆顶刊文章，你看不看，看哪些？

![image.png](./images/image%205.png)

可以看到，其中有几部分是和科研有关的，另一部分则是兴趣使然。和科研有关的部分，我就时常需要读些论文，并将对应的知识积累起来。

然后，你需要选择一个用来管理文献的工具。我选择了Zotero作为文献管理的工具，它大概长这样。左边的区域包括以文件夹形式组织的目录，下方是给文献打上的标签，中间区域是文献的标题、作者、期刊、年份等信息，右边则是选中某条文章后的详细信息。

![image.png](./images/image%206.png)

你也完全可以选择别的工具，比如更为老牌的Endnote，可能会是更多人包括大家的导师的第一选择，生命科学图书馆之前是有Endnote可以下载的。我讲的与选择特定工具并不关联，你可以任意选择喜欢的工具，并在那个工具中实现相似的效果。

接下来需要在文献管理软件中根据选择好的项目、领域、资源创建大类。

假如你已经在使用这样的文献管理工具，已经积累了一些文章，但是它们有些混乱。可以这样重新开始：将所有现有的文章移动到一个新的文件夹，命名为归档和当前日期，然后开始接下来的步骤。因为与其花费大量时间整理它们，将来也不一定用得到，反而可能让你失去开始的契机。因此不如和它们暂时告别，不必担心丢失任何东西，它们都还在，当需要的时候还可以通过搜索找到它们。

让我们继续，在管理软件的目录下，按照项目、领域、资源和归档创建四个大类，并将大类下面为你选定的主题再分别创建文件夹。记住，一开始只需要创建到每个大类下的主题就可以了，只有当在你在这个主题下积累了一定的内容，感觉需要进一步细分时，才创建新的文件夹，可以最大程度避免文件夹的冗余和混乱。

这里还有两个小技巧，其一是默认的文件夹可能会按字母排序，你可以在前面加上数字，让它们按你想要的顺序排序。其二是我还为其添加了一个收集箱（Inbox），放在所有类别最前面，这样当遇到某篇可能感兴趣的文章时，可以先将其收进收集箱，等看完后判断一下，是将它储存起来以备将来查阅，还是和我需要的知识不太相关，因此直接删除。

![image.png](./images/image%207.png)

随后，可以进一步按照内容将某个项目拆分为更细的子类别。比如这里以我比较熟悉的基因组测序项目为例，它由前期的基因组调研、组装注释，以及下游的一系列分析组成。

我可以按照项目推进的阶段，将其拆分为一个个子项目，比如在调研阶段，我看的文章主要是基因组大小、染色体信息、近缘物种等资料，在组装注释阶段，需要看各种软件的使用方法，而在分析阶段，则需要阅读许多现有文章，总结其分析流程和方法。

这里强调两个实用的功能，一个是标签，我给一部分比较常用的标签设置了颜色，让其显示在文章处，比如标记文章是否已读，读完觉得文章是否重要。还可以按照文章类型标记标签，比如综述类、方法类，或是将文章归类为特定主题，一切都以自己将来找某个文章时是否方便为依据。

另一个实用的功能是Zotero里的Short Title功能，可以看向右图中中间这一列。这一列默认是不显示的，需要在调整显示的列中将其显示出来。可以看到我给不少文章加上了短标题，这样瞄一眼就能找到我想找的文章。

虽然这里只写了项目，但是领域、资源类别下同理进行划分。最后记得将已经完成的项目，放入归档中。

![image.png](./images/image%208.png)

总结一下，PARA方法实际是提供了一种归类思路，将所有的内容以某种分类规则，构建成了树状的结构。树状结构层次清晰，利于我们记忆，检索起来也非常方便。而文献管理软件中标签的存在，让文章间有了更复杂的联系，组建成网状结构，允许我们以更复杂的方式进行筛选：比如我想选择全部没有读过的、综述类型的、和细胞壁相关的文章，只需要同时选中这几个标签就能找到。

![image.png](./images/image%209.png)

## 一些小建议

再提几个可能能让文章不会过度混乱的小建议。

&gt; 保持克制，不当仓鼠
&gt; 

我们首先需要的，是考虑清楚自己打算积累哪些知识。我最开始就有过一阵这样子的阶段，每次看到一篇文章都想先将其保存下来，想着“万一用的上呢”。 仿佛保存过文章，我就有拥有了这部分知识。加上Zotero中保存文章实在是非常方便，点一下浏览器的收藏插件就可以将文章存下来，因此保存的文章越来越多，但其实大部分文章都没怎么仔细看过，文章越来越多，文档库也越来越混乱，从中找文章的过程也变得复杂。直到某个时候，我发现保存下来完全没看过的文章很多，我既看不完它们，也没法将它们用起来。后来才意识到，一篇文章如果只是被下载下来，存在电脑里，并不意味着我就拥有了这部分知识。因此盲目地收藏文章并不可取，反而很容易因为囤积了太多，使计划稍后仔细读一读的文章变成再也不读。

&gt; 定期整理
&gt; 

其次，不要想一次性设计出一个一劳永逸的资料管理系统。这也是我有过的困扰，将文献保存下来后，每次随便地想一个合适的文件夹储存它们。这样过了一段时间，我有好多好多并列的文件夹，但是我甚至不记得每个文件夹里存了些什么，不少文件夹的内容还互相有所交叉。终于某一天我下定决心，把所有的文件夹整理了一遍，能合并的合并，很多没看过、用不上的文章都删掉，这才感觉清爽了不少。并且意识到，很多最开始文件夹组织上的混乱，来源于课题早期对于整体脉络的不清晰，同时处在课题的探索阶段，什么都看一点，才弄出了一大堆各种内容的文件夹；到了课题中后期，主要内容已经明确，因为脉络不清晰造成的混乱也就自然而然地解决了。也正因如此，我觉得只有定期整理一下，让文献之间的结构伴随着你的成长，像植物那样逐渐生长出来，才能得到最适合你的文献管理结构。

&gt; 不必面面俱到。
&gt; 

有些时候某一篇文章，已经放在项目下的一个文件夹里了，你可能会纠结，用不用再去其他符合这篇文章气质的文件夹再放一份？我也曾纠结过这一点，感觉不把每个可能相关的文件夹都放一份，将来找的时候万一找不到就很麻烦。
而现在的我，对此建议是保持克制，只把文章放在你当前需要用到的类别中。因为后来想明白了，收集是为了之后的使用，并不为了打造一个事无巨细的图书馆。等将来的某一天真要找这篇文章的时候，回想到曾经在做某个项目的过程中看过，然后就会去项目下面根据所属的类别找到这篇文章，到那时如果有在别处用到它的需求，比如说你有了一个新的项目，在写一篇新的综述，再将其放在对应的合集中就可以了。也得益于使用了文献管理软件，在多个文件夹下存在的同一篇文章，并不会分散成多个文件，而是共用相同的条目信息，因此只要是同一篇文章，哪怕在每个文件夹中都放一份，最终在数量上也只算是有一篇，它们的笔记也都是共通的。

## 补充阅读

- [我的科研软件流分享 - 少数派](https://sspai.com/post/63830)

- [解决科研人痛点的大突破——Zotero 6.0 亮点速览 - 少数派](https://sspai.com/post/72163)</content:encoded></item><item><title>点名的风还是吹到了Blog</title><link>https://blog.yorks0n.com/articles/nine_questions/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/nine_questions/</guid><description>历史真是个圈。</description><pubDate>Wed, 23 Oct 2024 00:00:00 GMT</pubDate><content:encoded>以前还在玩QQ空间时，曾流行过一阵点名风潮。也不知最早是从何处兴起，点名者会罗列出一系列诸如姓名、生日、谁传给你的、未来想做什么这样的问题，写上自己的答案并@一些朋友们，被点者要复制这些问题，填上自己的回复，再重复这一过程。上次见到这种玩法估计得是十五六年前了，历史竟能如此相像？

![unnamed](./images/unnamed.jpg)

再说回来，感谢Dayu的邀请，这也让我停更了一年多的博客重新出现了些生机。好久没写，Hugo的语法都有了不少更新，以至于和之前的主题不太兼容。为了能继续用之前的主题，还给它提了issue，研究了半天才给修好。 

### 1. 简单介绍下自己或者你的博客？

如果你和我不太熟，可以叫我Yorkson。这些年来，我的名字少说还有十来种不同的叫法，甚至到了看到对应的叫法就能判断是哪个时期的哪些朋友们的地步。目前我还在生物信息学专业读博，因此博客中主要的文章主要和一些生信分析、或是数据可视化（我的兴趣之一）有关。有很多杂七杂八的爱好，每天高强度上网冲浪，但很多内容不便在此展开，虽然是 i 人但更推崇线下面对面的交流。

### 2. 什么契机让你开始写博客？

早在大学时就曾弄了自己的博客，甚至为域名去折腾了半天备案，后来发现花在折腾建立起博客上的时间远多于写东西的时间。最近的一次开始于22年上海疫情封控期间，被关在家里无事可做，于是尝试开始在少数派上写文章，也因此为契机能认识Dayu。后来为了能把一些杂七杂八的主题和零散的文章规整在一起，于是又一次买了域名弄了博客。另一方面的原因，则是因为这几年生信基本全靠自学，需要高强度上网检索各种奇怪问题，其中许多疑难杂症都是靠着世界另一处不认识的网友在博客等处写的文章解决的。这种「写下的东西能在未来某一天帮助素不相识之人」的感觉异常有趣，因此我希望能够以博客的形式分享知识，兴许能微微降低知识传播的门槛，生产出一些比AIGC质量稍高一点的内容。

### 3. 你是如何完成创作的？

哎，这个问题大抵是问写作的工作流。我可能会偶然间想到某个选题，将其记录下来，偶尔有什么点子就稍微往里补充一下。过了一阵子想写文章了，就在那期间高强度围绕这个选题进行一定的检索，或是写一些片段，并尽量以某个逻辑组织起来，然后觉得还差点意思，就丢在那不管了。直到某个时候，感觉写出来的东西没必要也无法做到完全完美，这才会发出来。还有些想整理成文章的是这些年各种摸爬滚打所记录下的笔记，但是一直拖着没有写，可能将来的某天会整理出来吧。

### 4. 运营博客的过程中是否有失去过动力？如果有，是为什么恢复的？

那可太有了，一旦停下就会停好久，不然也不至于一年半不写新东西。我觉得问题不大，至少我定期会有写作的愿望，过一阵又会犯懒不想写，尤其是忙的时候。不想写就不写，想写就写，就这么简单！不过这次大概是Dayu邀请我填这个点名才会继续更新一阵子吧，LOL。

### 5. 如何搭建博客，以及运营博客每年需要投入的资金？

之前是买了国内的服务器，做了域名备案放在上面，但众所周知会有奇怪的麻烦之处。现在直接用Hugo生成静态网站，挂在GitHub Page里，体验也没差，成本也只有域名所需的一年那几十块钱。GitHub页面在某些时空访问可能费点劲儿，但大家都是天天上网冲浪的人，这点问题应该是会有办法的。

### 6. 推荐 1 篇你博客中的文章，并推荐一个你喜欢读的博客，聊聊原因。

我会推荐这篇[论文可视化配色简易指南](https://blog.yorks0n.com/posts/color_guide/)，是我根据自己感兴趣的选题去整理出来的，我觉得会比较实用。最初发在少数派上，但因为一些图片懒得重新做从中删去了一部分，这里的是我写这篇文章的原始版本。要推荐一个博客，我会推荐[虹线](https://1q43.blog/)的博客，虽然部分文章可能会有人喜欢有人讨厌，但他的好几篇长文我读下来还是很喜欢并受到了不少启发的。

### 7. 推荐 1 个近期喜欢的事物？

推荐个最近刚买的书签管理工具，Anybox，几乎完美满足了我的书签管理要求，终于摆脱了缓慢的Raindrop，原因我也刚写了文章细说了一下，见[从Raindrop迁移到了Anybox](https://blog.yorks0n.com/posts/change_to_anybox/)。

### 8. 想做还没有做的事，或想尝试还没有尝试的主题？

作为一个有八百个兴趣的人，想做的事太多了，除去已经尝试过然后搁置的那些，大概近期反复想起的是学不同的语言或是想学画画吧，都是需要很多时间精力投入才能有所回报的爱好，现在越来越没耐心长时间地集中注意力了，这可不行。

### 9. 写到这里，闭上你的眼睛，深呼吸几分钟，或是出去溜达一圈，然后回来写任何你想写的东西。

好久不看书，这两天又拿出Kindle，发现集中注意力越来越困难了，让人分心的东西实在太多，这不太行。读书的过程让我有种安心的感觉，似乎是其他活动给不了的。但这几年似乎总在翻来覆去读之前已经看过的书，哪怕已经看了很多遍了。想要一些新鲜的，有意思的阅读内容。假如你已经读到了这里，不妨听我一个请求：如果让你只推荐一本书，你会推荐什么呀，请一定要告诉我！

### 写在最后

一鼓作气写完了这篇点名，似乎真有种和素未谋面的人交流的感受，不知道会有多少人能看到这篇文章呢？假如有些错别字还请谅解，应该会有的。

不论如何，如果你看到了这儿，向你问好！</content:encoded></item><item><title>从Raindrop迁移到了Anybox</title><link>https://blog.yorks0n.com/articles/change_to_anybox/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/change_to_anybox/</guid><description>苦raindrop久矣，终于找到趁手的书签管理工具了</description><pubDate>Tue, 22 Oct 2024 00:00:00 GMT</pubDate><content:encoded>长期以来，我一直使用Raindrop作为我的书签管理服务，苦raindrop久矣。从2017年左右，一直用着免费版本的Raindrop，主要因为它那些付费版本的功能我也不太用得上，这些年也在其中积累下来大几百个书签，其中不少还标注了标签和备注方便查找。它倒是也能用，既支持多平台同步，又有网页版，最初免费版不支持创建嵌套的文件夹，后来也支持了，可以说功能上没啥大毛病。

![Snipaste_2024-10-22_13-04-42](./images/Snipaste_2024-10-22_13-04-42.jpg)

然而这几年里，总想找机会把它换掉，无他，Raindrop的性能真是太差了。不仅各个平台的App都宛如网页版套壳，各种操作的响应也都非常慢。每次想添加新书签，还要在添加页面等一会儿，确定它同步完了再关闭窗口；搜索的时候，也经常弹不出搜索结果。为此，我一直在尝试各种书签管理工具，想找个满意的替代品，大致需求也不复杂：

- 性能良好，添加书签时的反应迅速
- 同时支持文件夹和标签两种分类方式，便于分大类和进行筛选
- 检索性能优秀
- 支持同步功能，需要至少有桌面与手机平台
- 最好能有独立App，而非依靠浏览器插件等形式实现
- 非订阅制，开源或可以买断

然而找了好久都没遇到合适的，许多开源项目都没有多端，或是同步起来相当费劲，亦或是书签多了后管理不便。一些付费服务页面fancy，但是性能巨差，或是性能好并且拥抱AI，于是每个月订阅费用感人。我还是希望能将书签管理与稍后读等内容管理分开的，避免混在一起检索起来麻烦，因此那些对内容的快速AI检索我也用不上。

前几年，也曾多次按月订阅试过Anybox，但最初不支持文件夹，支持Tag但不能手动调顺序，以至按类别检索效率略低。后来虽然更新出了标签嵌套，但截至目前还是不支持手动调整标签顺序，没法像文件夹那样方便。不过在最近的尝试中发现它支持了文件夹，甚至可以直接把Raindrop导出中的文件夹结构保留，解决了我主要的痛点。虽然软件为订阅制，但支持198元永久版买断，总比按月支出来得舒服。于是在又订阅了一个月把书签都导进来试用几天后，果断买断了，删除Raindrop，使用至今非常舒适。不管是软件本身提供的快速检索栏，还是结合了Raycast的插件，都异常丝滑，好好好！

![search](./images/search.gif)

甚至现在Anybox还可以将网页版归档下载下来保存，也许之后会把读过想储存的文章也迁移过来？

要说Anybox现在的缺点，估计就是没有网页版也不支持win吧，但我日常主要用Mac和iOS，倒也完全够用。</content:encoded></item><item><title>数据可视化——基本图形元素及其应用</title><link>https://blog.yorks0n.com/articles/basic_elements_data_vis/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/basic_elements_data_vis/</guid><description>介绍可视化作图过程中使用的基本元素，简单分析不同数据类型与适合使用的展示方式。</description><pubDate>Wed, 19 Jul 2023 00:00:00 GMT</pubDate><content:encoded>## 前言

本文旨在介绍可视化作图过程中使用的基本元素，简单分析不同数据类型适合使用何种图形进行展示。通过了解这些基本元素，我们可以实现以下两个目的：

- 更好地解读图片传递的信息
- 判断图表质量的好坏

在理解了基本元素的基础上，我们能够更好地设计图表，从而更高效直观地向读者传递我们的结论。

## 用于数据可视化的基本图形元素

### Marks and Channels

一张数据可视化图（特指将数据用图的形式展示出来）中的元素，基本可以分成下面提到的两大类。即使是较为复杂的图，也能拆分成诸多基本元素的组合。

其中第一类称为 **Mark（标记），是一张图中的基本图形元素。** Mark根据其维度可以细分为三种：

![Untitled](./images/vis_elements.png)

第二类元素是 **Channel（通道），指用于控制 Mark 如何呈现在图中的变量。** 通道可以分为以下几种：

- 位置
- 颜色
- 形状
- 斜率
- 大小（长度、面积、体积）

![Untitled](./images/vis_elements1.png)

这样讲非常抽象，来几个具体的例子：

- a 图，使用线段作为 Mark（柱状图就是些粗了点的线段），Channel 是长度，所以当我们在看柱状图时，比较的实际是不同线段（柱子）的长度
- b 图，用点作为 Mark，Channel 是点在图上的位置，每个点都有其坐标 (x,y)
- c 图，在 b 图的基础上，增加了一个颜色 Channel，用这个通道将点分成了红蓝两组
- d 图，在 c 图的基础上，又增加了面积作为 Channel 控制点的大小，额外编码了一个变量

![Untitled](./images/vis_elements2.png)

**以此可见，无论复杂还是简单的图，都是通过 Marks 与 Channels 的适当组合得到的。**

### Channel Rankings

在画图的时候，一次必然不会用到全部的上述元素。由于各种 Channel 传递信息的效果并不一致，要想让你的图更为直观，需要选择恰当的元素表现方式。

下图展示了不同类型的数据，用不同 Channel 进行表达时，其效果的优劣，越靠上的 Channel 越便于读者理解。

有顺序的数据（比如一组有大有小的测量值）应当以左边这组形式呈现，类别数据（比如野生型和突变体这两组材料）应当以右边的形式呈现。

![Untitled](./images/vis_elements3.png)

对于两类数据，效果最好的都是空间位置。我们来看一组例子，体会一下不同数值编码方式传递信息的效率差异。

浏览下面的每一张图，快速判断图中的数据能分为几组。

![Untitled](./images/vis_elements4.png)

- 第一的图，用位置+颜色编码，很容易将点进行分组。
- 第二张图，用大小+颜色编码，稍微混乱了一些，但还算可以分辨。
- 第三张图，该分成三组还是四组？这张图采用宽度+高度编码，还算可以分辨，但由于我们通常感知面积快于形状，所以矮宽/高瘦的椭圆形可能在直觉上会被归为一组，于是图中四组容易被认作大中小的三组。
- 第四张图，只用颜色进行编码，非常混乱，实际也是四组。

## 不同数据类型与其适合的展示方式

### One quantitative value

首先是一维数据，只有一组连续值，我们希望展示这组数据的分布情况。如果只用平均值、标准差来描述，可能会损失很多信息，便可以考虑用直方图或密度图来展示。

![Untitled](./images/vis_elements5.png)

#### 直方图（Histogram）

直方图（Histogram）是展示 **连续数据分布情况** 最常用的工具，它划分好一组区间，将落到每个区间中值的个数进行统计并绘图，使用线条的长度来编码数据。由于直方图需要对连续型数据做离散分组，因此它有一个明显的缺点，就是它的形状依赖于分组的端点，例如若有好几个相同的数值正好处在分组端点上，那么我们只要稍微向左或向右移动一下分组端点，这些数据点就会被划分入不同的区间，导致矩形条的高度变化。

- Mark: line
- Channel: length

![Untitled](./images/vis_elements6.png)

#### 密度图（Density plot）

密度图利用核密度估计，对原始数据估计其密度函数，相比直方图对数据的描述更加准确。然而其边界处可能由于边界效应与实际情况不符。

- Mark: line
- Channel: position

![Untitled](./images/vis_elements7.png)

### Two quantitative values

当面对二维连续值的情况，比一维稍微复杂一点，可以用散点图展示它们之间的关系。

![Untitled](./images/vis_elements8.png)

#### 散点图（Scatter plot）

散点图展示 **两个变量之间的关系** ，这种关系可能是线性或非线性的。图中每一个点的横纵坐标都分别对应两个变量各自的观测值，因此散点所反映出来的趋势也就是两个变量之间的关系。

- Mark: point
- Channel: position

![Untitled](./images/vis_elements9.png)

### One key, one value

假如一张表是这样的：

- **能够定位到某个表格位置的变量称作 Key**，这通常是我们统计对象的某个属性，比如某个材料的名称；
- **表格中某个格中具体的值被称为 Value**

![Untitled](./images/vis_elements10.png)

#### 柱状图（Bar chart）

柱状图可能是我们最熟悉的图形之一，目前是各种统计图形中应用最广泛的，但柱状图使用统计后的数据（平均值、标准差）进行作图，所能展示的统计量比较贫乏：只能以矩形条的长度展示原始数值，对数据的分布几乎没有任何展示。

比如在下图中，因为展示的是每个动物的平均质量，如果不加误差线，我们既不能看出它的变异程度，也看不到这些数据的分布。

- Mark: lines
- Channel: position, length

![Untitled](./images/vis_elements11.png)

#### 箱线图（Box plot）

统计（平均值、标准差）后画出的柱状图损失了太多信息，相比之下，直接用原始数据画出的箱线图呈现了 **更详细的数据分布情况** ，并允许数据中包含异常值。

- Mark: line, point
- Channel: position, length

![Untitled](./images/vis_elements12.png)

#### 小提琴图（Violin plot）

小提琴图是密度曲线图的变体，有时也与箱线图一同呈现，能够更清晰地展示数据的分布情况。由于其外形与小提琴的形状相似（尤其展示双峰数据时），所以称为小提琴图。通常要较多的数据量，才能呈现出比较好看的小提琴图。

- Mark: line, point
- Channel: position, length

![Untitled](./images/vis_elements13.png)

### One ordered key, one value

当我们的数据，其中的 Key 有内在顺序时，其呈现方式又可以有所不同。

![Untitled](./images/vis_elements14.png)

#### 折线图（Line chart）

比方说展示一组随时间（比如年份）变化的数据，一般会用折线图的形式，更容易体现出数据的变化趋势。

- Mark: line, point
- Channel: position

![Untitled](./images/vis_elements15.png)

各种常见的基本图片类型就讲到这，我在每张图处都表明了作图利用到的 Mark 与 Channel。比较后就会发现，各种图确实都可以抽象为作图元素的适当组合。

## 常见问题

以下介绍一些常见的问题与争议，同时包含一些注意事项。篇幅有限，没法将各种问题逐一分析，如果感兴趣也可以与我深入进行交流。

### 选择柱状图还是折线图

这个问题一般取决于数据的类型，尤其是其中 Key 的类型。

- 如果是**类别数据**，用柱状图
- 如果是**有序数据**，用折线图

需注意，类别数据不应使用折线图来展示，而有序数据也能用柱状图表示。

下面两张图展示了性别与身高的关系，在这里 Key 为性别，属于类别数据，因此柱状图可以，但是折线图不合适。因为折线图天生带有一种展示趋势的倾向，会错误地传递出一种「从 Female 到 Male 身高存在上升趋势」，但一般来说性别不会逐渐变化，通常也不会出现身高随着性别变化而改变的情况。

![Untitled](./images/vis_elements16.png)

再看下面的图，年龄与身高的关系。柱状图展示了不同年龄段的身高差别，折线图展示出从十岁到十二岁儿童身高有上升的趋势，这就非常合理了。

![Untitled](./images/vis_elements17.png)

### 原点是否从0开始

一个作图过程中需要注意的问题：原点是否从0开始？在不同图中这个问题存在一些争议，但是 **在柱状图中，原点一定要从0开始。** 我们有时也会见到，为了刻意传递出某种结论而在柱状图中不从零开始展示数据的情况。

回想一下前面提到柱状图的时候，我们提到**柱状图利用长度来编码数值**。正因如此，长度需要与数值以合适的比例关系进行对应，100 是 50 的两倍，因此在线性坐标轴上，对应 100 的柱子长度就该是 50 的两倍长。

而**折线图利用位置来编码数值**，所以在一些情况下，为了展示出更清晰的局部变化，可以不从0开始。

![Untitled](./images/vis_elements18.png)

### 雷达图与饼图

雷达图实际上是极坐标系中的折线图，**以到中心的距离编码数值**，然而其**可读性非常差**，绝大多数情况下避免使用。

- 纵坐标对应的数值不易阅读
- 折线的趋势变化不明显
- 折线图不应用来表示没有顺序的分组数据
- 除非周期性数据，否则一组数据结尾和开始处的连接没有实际含义

![Untitled](./images/vis_elements19.png)

饼图**用角度编码数值**，给人的感知是角度/面积，**可读性也不好**。因为人眼对角度或面积辨识能力不强，尤其是相似的角度非常多的时候。

![Untitled](./images/vis_elements20.png)

回看一下最开始放的排序图，角度与面积都排在了最后，因此请谨慎使用饼图。如果用，对数据进行排序后再画饼图，可以稍稍让读图变得轻松一点。

![Untitled](./images/vis_elements21.png)

### 一些奇怪的图

我翻了一些CNS文章，除了热图和树状/网状图，基本都是上面提到的图片类型。其中有些变体形式的图也非常不错，比如下面这张直接展示出原始值及其平均值，又省空间又直观。

![Untitled](./images/vis_elements22.png)

或是下面这种（我画了个示意图），相比于柱状图省去了柱子的部分，同样呈现出平均值和误差线，又比柱状图省下不少空间（柱状图的柱子宽度几乎毫无意义）。

![Untitled](./images/vis_elements23.png)

再举个例子，说说如何用图片元素的基本知识，帮助我们读一张图，尤其是如今日益花哨的各种组学图。下面是张呈现出转录组数据的火山图（Volcano plot），一眼看上去还挺炫，让我将其中的各种元素拆分一下：

- 横坐标与纵坐标都是取 log 后的连续型数值，坐标轴不包括离散（分组）数据，因此这是将（x,y）映射到位置的散点图，每个点代表一个基因
- 再看横纵坐标表示的含意，横坐标是 R-NR 数据的比值，因此越靠右表明比值越大，越靠左则比值越小
- 图中的两条曲线划定了一定范围，因此作为比较数据的阈值
- 数据点还映射到了不同的颜色，灰色是没有达到阈值的数据，黑色点达到阈值，其中又有些选出的基因，被标注以不同颜色，应该是依照某个其他因素进行了分组

那么，再接下去看看上下文有没有提到这些颜色代表了什么分组，就清楚它是要讲什么了。

![Untitled](./images/vis_elements24.png)

好了，这篇文章就写到这，我们下次再见。

## 参考资料与延伸阅读

- [Data Visualization - A practical introduction](https://socviz.co/index.html#preface)
- [Visualization Analysis &amp; Design](https://www.cs.ubc.ca/~tmm/talks.html#vad15sydney)</content:encoded></item><item><title>单变量异常值检测方法</title><link>https://blog.yorks0n.com/articles/outlier_detection/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/outlier_detection/</guid><description>整理一下检测单变量异常值的方法。</description><pubDate>Mon, 17 Jul 2023 06:01:55 GMT</pubDate><content:encoded>## 异常值？

首先，什么是异常值，某个特别的值真的是异常值吗？

在统计学中，异常值（outlier）是与其他观察值显著不同的数据点。它们可能来源于测量方法的变异性，可能指示出新的数据情况，或者也可能是实验误差的产物。然而，判断某个值是否为异常值并不轻松，也没有一劳永逸的方法或是唯一可信的标准，因此这里整理几种常见的单变量异常值检测方法，以供自己或他人将来参考。

至于如何处理异常值，是原样保留还是剔除它们，往往会随着分析目的等因素发生变化，但请一定三思，avoid [cherry-picking](https://en.wikipedia.org/wiki/Cherry_picking)。

## 异常值检测

### three-sigma rule

首先计算数据的平均值mu，与标准差std

three-sigma 法则将任何 $abs(x - µ) &gt; 3 * std$ 的值作为异常值，这里的3也可以根据情况进行调整

这种方式与另一种Z-score方法实际是一致的：对数据进行Z-score变换，就是在计算数据的Z统计量

$$
z = (x-µ)/σ
$$

对应于three-sigma方法中，就是这里的 $abs(z) &gt; 3$会被视为异常值。

这里划定异常值的系数取3，实际已经是一个非常极端的值了，我们假设Z-score变换后的数据符合标准正态分布，此时置信区间内的概率$p(|z| &gt; 3) = 0.9973$，即数据落在这个区间外的概率只有0.0027。

我们假设随机来一组数据：

```r
set.seed(2501)
# 生成一组10个符合正态分布的随机数，µ = 100，σ = 10
random_numbers_1 &lt;- round(rnorm(10, mean = 100, sd = 10))
# 99 104 103  91 106 100  96  90 110  99

# 再添加几个值，分别为68,220
data_1 &lt;- c(random_numbers_1, 68, 220)
# 99 104 103  91 106 100  96  90 110  99  68 220
```

此时样本均值和标准差分别为

```r
mu_1 = mean(data_1)
# 107.17

sigma_1 = sd(data_1)
# 37.13
```

此时 three-sigma的区间为$mu \pm 3*sigma = (-4.23, 218.57)$，是个大到离谱的区间了。上面的数据中只有220会被这个方式定义为异常值。这个范围对应初始的 $N(100,10^2)$ 中的概率为 $1 - 9.7^{-26}$，即有真实值落在区间外的概率为$9.7^{-26}$，因此是一个区间范围非常大，非常宽松的方法。其原因一方面是选择 3 作为系数，因此可以视情况将其调整为其他值，比如 2.5 等。

但是，计算置信区间的方式相对比较繁琐，一种更直观的是对所有数据直接计算 z 统计量

$$
|z| = \left|\frac{X - \bar{X}}{s}\right|
$$

```r
abs(round(scale(data_1)[,1],2))
# 0.22 0.09 0.11 0.44 0.03 0.19 0.30 0.46 0.08 0.22 1.05 3.04
```

其中68的z变量为1.05，220的z变量为3.04，如果以3为标准就可以将其作为异常值。

另一方面，该方法本身涉及到计算平均值和标准偏差，这两个值都受异常值影响很大，尤其是标准偏差，假设上面额外增加的 220 改成 200，这种方法的区间就会成为 $(10.54, 200.45)$，这时 200 落在了边界附近，却刚好不会被视为异常值。

### IQR 方法

有时也称为箱线图方法，通过计算数据的分位数判断异常值，大概方式如下

```r
Q25 = 25th_percentile
Q75 = 75th_percentile
IQR = Q75 - Q25         // inter-quartile range
IF (x &lt; Q25 - 1.5*IQR) OR (Q75 + 1.5*IQR &lt; x) THEN  x is a mild outlier
IF (x &lt; Q25 - 3.0*IQR) OR (Q75 + 3.0*IQR &lt; x) THEN  x is an extreme outlier
```

IQR 方法的好处在于，去掉异常值前后，其他值的中位数和 IQR 基本是不变的。

同样用上面的数据，计算一下这种方式的区间：

```r
quantile(data_1, probs = c(0.25,0.75))
# Q25 = 94.75
# Q75 = 104.50
# IQR = 9.75
```

此时1.5倍IQR的区间为，相对还是个比较窄的范围，后添加进去的 68 和 220 在此情况下都会被视为异常值。

$$
(Q25-1.5\cdot IQR, Q75+1.5\cdot IQR) = (80.12, 119.12)
$$

3 倍 IQR 的范围则为 $(65.5, 133.75)$ 相对会宽一些，此时只有220会被作为异常值。

$$
(Q25-3\cdot IQR, Q75+3\cdot IQR) = (65.5, 133.75)
$$

**这种方式的一个好处就是分位数对异常值不太敏感**，如果把220变为200，这个区间依然是不会变的。

1.5 倍 IQR 的区间$(80.12, 119.12)$放到原始的分布中去大致对应于概率 95% 的正态区间；3 倍 IQR 的区间对应 99.94% 的概率，真实值落入这个区间外的概率也足够低了；当然相比于 three-sigma，还是严格了一些。

因此，IQR 方法更容易检测出异常值，当然也更有可能把真实值视为异常值，因此需要谨慎选择 IQR 区间的倍数。

## 中位数绝对偏差 MAD

上面的方法可能会遇到一些问题，包括

- 均值和标准差的计算依赖于所有数值，因此离群值可能会对均值和标准差产生较大影响
- three-sigma、IQR等方法对于小样本不一定合适（？

还有另一种可以衡量变异程度的统计量，中位数绝对偏差（Median absolute deviation，MAD）

其计算也相当简便：

对于一组数据$X_1, X_2, X_3, ..., X_n$ ，其中位数为$\tilde{X} = median(X)$

MAD是各个数据与其中位数绝对偏差的中位数：

$$
MAD = median(|X_i - \tilde{X}|)
$$

MAD 相比方差更能适应数据集中的异常值：在标准偏差中，与均值的距离是平方的，因此大偏差的权重更大，因此离群值会严重影响它；在 MAD 中，由于中位数天生受异常值影响较小，少数异常值的偏差几乎不影响MAD。

上面 three-sigma 使用标准方差 σ 衡量变异程度，IQR 方法使用 IQR 衡量变异，类似的，在这里使用 MAD 衡量数据的变异幅度。MAD 的使用方式类似Z-score变换中将表标准差应用于平均值的过程，为了将 MAD 作为与标准偏差 σ 一致的估计量，需要有

$$
\hat{\sigma} = k \cdot MAD
$$

其中 k 是一个比例系数，取决于分布。对于正态分布的数据，k 被认为是

$$
k = 1/\Phi^{-1}(3/4) \approx 1.4826
$$

即标准正态分布 $Z = \frac{X-\mu}{\sigma}$ 的分位数函数 $\Phi^{-1}$（也称累积分布函数，R 中计算使用 qnorm）的倒数。

用一开始的数据计算

```r
# 99 104 103  91 106 100  96  90 110  99  68 220
mad_1 &lt;- median(abs(data_1 - median(data_1)))
# mad_1 = 5.5

round(abs((data_1 - median(data_1)) / (mad_1*1.4826)), 2)
0.06  0.55  0.43  1.04  0.80  0.06  0.43  1.17  1.29  0.06  3.86 14.78
```

类似，视情况选择合适的值作为阈值，即可检出异常值。如果选择 3，对应的区间为 (75.04, 123.96)，概率范围为98.5%；如果选择 4，对应的区间为 (58.73, 140.27)，概率范围为99.89%。

k 的推导过程如下

为了使 $\pm k*MAD$ 的区间落在概率为 $p_0$ 的标准正态分布中区间内，有以下公式

$$
p_0 = P(|X - µ| \le k \cdot MAD) = P\left( \left|\frac{X - µ}{σ}\right| \le \frac{k \cdot MAD}{σ}\right) = P\left( |Z| \le \frac{k \cdot MAD}{σ} \right)
$$

因此就有

$$
\Phi(k \cdot MAD/\sigma) - \Phi(-k \cdot MAD/\sigma) = p_0
$$

又因为

$$
\Phi(-k\cdot MAD/\sigma)=1-\Phi(k \cdot MAD/\sigma)
$$

所以

$$
\Phi(k \cdot MAD/\sigma)= \frac{1 + p_0}{2}
$$

令 $p_0 = 0.5$，即 50% 正态分布区间时，

$$
k = \frac{\sigma}{MAD} = \frac{1}{\Phi^{-1}(3/4)} \approx 1.4826
$$

这里选择 0.5 是因为，对于均值为零的对称分布，总体 MAD 是分布的第 75 个百分位数，因此标准正态分布的总体 MAD 刚好等于$\Phi^{-1}(3/4)$。 

## 参考资料

- [Recommended anomaly detection technique for simple, one-dimensional scenario?](https://stackoverflow.com/questions/2303510/recommended-anomaly-detection-technique-for-simple-one-dimensional-scenario)

- [5 Ways to Detect Outliers/Anomalies That Every Data Scientist Should Know ](https://towardsdatascience.com/5-ways-to-detect-outliers-that-every-data-scientist-should-know-python-code-70a54335a623)

- [Median absolute deviation](https://en.wikipedia.org/wiki/Median_absolute_deviation)</content:encoded></item><item><title>复现一张相关性图</title><link>https://blog.yorks0n.com/articles/corplot_case/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/corplot_case/</guid><description>前几天看到群里有人问如何画一张类似下图的、带拟合线与误差的相关性图，这里找点数据来演示一下怎么画。 找了点数字画了个例子，假设数据读进来是这样的两列：...</description><pubDate>Tue, 30 May 2023 01:24:00 GMT</pubDate><content:encoded>前几天看到群里有人问如何画一张类似下图的、带拟合线与误差的相关性图，这里找点数据来演示一下怎么画。

![demo](./images/corplot1.png)
找了点数字画了个例子，假设数据读进来是这样的两列：

![Untitled](./images/corplot2.png)

绘图的部分我用了这些

```r
leg &lt;- theme(title=element_text(size=15), 
             axis.text.x=element_text(size=14),
             axis.text.y=element_text(size=14),
             legend.text=element_text(size=14))
label_text &lt;- paste0(&quot;r = &quot;, round(cor(subdata$Na,subdata$K),2))
library(ggplot2)
ggplot(subdata, aes(x = log(Na), y = log(K))) +
  geom_point(size = 2,color = &quot;#31705a&quot;) +
  stat_smooth(method = &quot;lm&quot;, color = &quot;#31705a&quot;)+
  theme_classic() +
  annotate(&quot;text&quot;, x=5.8, y=9, label= label_text) +
  leg
```
以上代码画出来的图如下：
![Untitled](./images/corplot3.png)

其中各部分的解释如下
```r
leg &lt;- theme(title=element_text(size=15), 
             axis.text.x=element_text(size=14),
             axis.text.y=element_text(size=14),
             legend.text=element_text(size=14)) # 用于指定字体大小等，可以先忽略
label_text &lt;- paste0(&quot;r = &quot;, round(cor(subdata$Na,subdata$K),2)) # 用于计算相关系数r的值，并处理成标在图上的「r = xxx」的文本
library(ggplot2) # 用ggplot2包画图
ggplot(subdata, aes(x = log(Na), y = log(K))) + #指定画图的数据subdata，在aes(x = ,y = )中指定横纵坐标轴
  geom_point(size = 2,color = &quot;#31705a&quot;) + #绘制散点部分，点的大小为2，颜色为浅绿色
  stat_smooth(method = &quot;lm&quot;, color = &quot;#31705a&quot;)+ #绘制拟合线部分，method = &quot;lm&quot; 使用线性拟合，颜色同前
  theme_classic() + # 使用ggplot的classic画图主题，是个只显示横纵坐标轴的主题
  annotate(&quot;text&quot;, x=5.8, y=9, label= label_text) + # 添加上文字标注，类型是&quot;text&quot;，位置在x=5.8，y=9
  leg # 添加之前指定的字体大小部分，不关键
```</content:encoded></item><item><title>【读文献】单细胞分析最佳实践</title><link>https://blog.yorks0n.com/articles/read-single-cell-best-practice/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/read-single-cell-best-practice/</guid><description>Best practices for single-cell analysis across modalities</description><pubDate>Fri, 07 Apr 2023 00:00:00 GMT</pubDate><content:encoded># Best practices for single-cell analysis across modalities

跨模式单细胞分析的最佳实践，于 2023 年 3 月 31 日发表于 nature reviews genetics。最近在研究单细胞分析相关的资料，因此记下这篇笔记。文章中包含了 Transcriptome、Chromatin accessibility、Surface protein expression、空间转录组等多个方面，但就近期关注点而言，只精简记录单细胞转录组部分的笔记。如果有需要，可以[阅读原文](https://www.nature.com/articles/s41576-023-00586-w)。

---
![](./images/1680845994088.png)

## 从原始计数矩阵到高质量单细胞数据

原始计数矩阵是直接从测序数据定量得来的矩阵，一般根据每个细胞 barcode 与 UMI 确定细胞中各种 mRNA 的数量，然而原始数据中包含着各种系统噪声和误差（比如来自建库操作、样本质量、测序批次等），因此在这一预处理过程中试图去除误差。这一过程涉及到**质量控制**、**归一化**、**数据矫正**和**特征选择**等过程，还可能会涉及到消除批次效应以**整合多批次数据**的过程。

### 滤低质量细胞和噪声校正 Filtering low-quality cells and noise correction

大多数分析过程假定每个单细胞液滴中都包含来自单个完整细胞的 RNA。细胞质量差（比如死细胞）、溶液中破裂细胞产生的 RNA 污染、同时捕获多个细胞的情况违反这一假设，因此需要在进一步分析之前去除这部分数据。

- **低质量细胞**：检测基因数量过少、深度过低或是线粒体计数（植物还有叶绿体）过多的细胞都被认为是低质量细胞。一般通过手动设置的阈值来进行识别和过滤，可以参照[先前文章](https://doi.org/10.15252%2Fmsb.20188746)或是基于中值绝对偏差数对样本进行过滤。需要综合考虑过滤的指标，同时注意**质量控制是在样本水平上进行的**，因为样本之间的阈值可能会有很大差异。
    - 中值绝对偏差数（Median Absolute Deviation, MAD）
      
        基于中值绝对偏差数（Median Absolute Deviation, MAD）的样本自动过滤是一种统计方法，用于识别和剔除数据集中的离群值。这种方法主要有以下几个步骤：
        
        1. 计算数据集的中位数（median）。
        2. 对每个数据点，计算其与中位数的偏差绝对值。
        3. 计算这些绝对偏差的中位数，得到MAD值。
        4. 选择一个阈值，通常是MAD的某个倍数（例如3倍MAD），用于判断数据点是否为离群值。
        5. 剔除大于阈值的数据点，即被认为是离群值的数据点。
        
        这种基于MAD的方法对于处理非正态分布的数据集具有较好的鲁棒性，而且相对标准差受异常值影响更小，因此可以有效地识别和过滤异常值。
        

- **无细胞游离 RNA**：通常存在于溶液中，并在建库过程中分配给每个细胞，产生一种类似背景值的效果。如果是细胞类群特异性标志物的 RNA 污染了其他细胞，后续分析中可能将不同的细胞群混合在一起。流行的 SoupX 等方法根据样本中「空液滴」的表达情况去除污染；CellBender 将环境 RNA 的去除制定为无监督贝叶斯模型，该模型不需要细胞类型特异性基因表达谱的先验知识。应当尽量不忽略去除环境 RNA 这一步，以提升下游分析的质量。

- **空液滴和双联体液滴**（包含两个细胞的液滴）：由不同细胞类型形成的双联体很难注释，并可能导致细胞类型标注错误。常见的双峰检测方法随机抽取两个细胞组合成模拟双联体，并将其与其他细胞测量结果进行比较。scDblFinder 采用此方法， 并在多项测试中准确性和计算效率优于其他方法。还可以应用多种不同检测方法并比较结果以提高准确性。

### 归一化和方差稳定化 Normalization and variance stabilization

不同细胞的 mRNA 含量不同，加上测序过程随机误差，将导致细胞有不同的初始计数。归一化可以矫正测序深度的差异，使不同细胞具有可比性。随后稳定方差以确保少数离群值对整体数据影响不会太大。

**shifted logarithm transformation**：使用缩放系数s的 log(𝑦/𝑠+1) 表现良好，但不应使用 CPM（counts per million）作为输入。

&gt; should not be used with counts per million as an input, as it reflects an unrealistically large overdispersion.
原文如此，但没看懂为什么，待补充。
&gt; 

通过使用一个公因数缩放所有基因，会假定由于细胞大小导致的测序深度差异可以忽略不计。然而对于异质性较大的数据集，其中包含了特性不同的各种细胞，其本身基因表达差异就较大，难以对每个基因找到一个合适所有细胞的系数。

此外还有 **Scran** 标准化和 **Pearson** 残差方法。shifted logarithm transformation 被证明可以更好地稳定方差以进行后续降维，Scran 在批量校正任务中表现良好，Pearson 残差更适合生物变异基因的选择和稀有细胞身份的识别。

### 消除混杂的变异来源 Removing confounding sources of variation

混杂变异可以来源于技术和生物，并且应该分开处理。

- **批次效应**：多个样本的数据集可能会由于技术产生的批次效应，需要恰当的数据整合方法。canonical correlation analysis 与 Harmony 等线性嵌入模型在处理不同批次的简单整合上表现良好；在复杂任务重， atlas、scANVI、scVI、scGen等深度学习方法，及 Scanorama 等显性嵌入模型表现较好。scIB 包可用于使用上述基准的评估指标来评估整合效果。
- **生物因素**：细胞周期等因素同样会引入误差，使得细胞间差异来源于细胞周期而非细胞类型。可以使用 Scanpy 或 Seurat 中内置的细胞周期标记与校正函数作为基础；Tricycle 等更复杂的方法对细胞异质性高的数据集表现良好。

### 选择信息特征和降维 Selecting informative features and reducing dimensionality

理想情况下，特征选择方法应优先选择在亚群间（而非亚群内）变化的基因，并且不影响亚群内更小亚群的可识别性。

通过拟合基因模型获得 deviance 来识别信息量大的基因，模型假定所有细胞基因表达一致，然后检验哪些基因违反假设，从而选择基因。此外，按此方法利用了原始计数对基因进行排序，不依赖归一化，不会因为数值中零值过多产生误差（zero inflation）。选择特征后可以通过 PCA 等方式进一步降低数据集维度，同时 PCA 结果可以进一步作为输入应用 t-SNE、UMAP、PHATE 等可视化降维方法。注意，最近有研究表明，仅仅依靠2D嵌入可能会导致对细胞之间关系的错误解读。因此，结果不应仅基于对结果的视觉检查来制定，而应结合其他定量评估。

## 为细胞集群确定亚群身份 From clusters to cell identities

### 从单个细胞到集群 From single cells to clusters

识别细胞群的第一步是将表达模式相似的细胞聚类成组，推荐使用 Leiden 算法进行聚类。

### 为细胞集群确定细胞身份 Mapping cell clusters to cell identities

建议分三步进行：自动注释 → 手动注释 → 验证。

- **自动注释**：分为基于分类器的方法和基于参考数据集的映射方法。分类器可以参考 CellTypist 和 Clustifyr，两者利用先前注释过的数据集进行训练并参考大量基因进行分类；映射方法有 scArches、Symphony 或 Azimuth。这两类方法都依赖于参考数据的质量+模型质量+参考数据集对新数据的适用性。
- **手动注释**：利用细胞群的特异性标志基因进行注释。
- **验证**：需要仔细设计验证试验，并且对于复杂数据或稀有亚群，可能没有资料可供参考。

### 伪时间分析——从离散状态到连续过程 From discrete states to continuous processes

根据细胞表达模式的相似性，沿着轨迹对细胞进行排序的模型被称为轨迹推断或伪时间分析。这类分析的效果取决于数据集中存在的轨迹类型，Slingshot 对简单结构表现良好，PAGA 和 RaceID/StemID 对复杂结构表现更好，建议使用 [dynguidelines](http://guidelines.dynverse.org/) 选择适用的方法。当预期结构未知时，应采用不同假设通过多种方法确认轨迹和假设。推断出的轨迹不一定有生物学意义。

利用 RNA velocity （mRNA 剪切、未剪切、降解的比例），比如考虑模型剪接动力学的 **velocyto** 和 **scVelo**，可以根据未剪接和剪接片段确定 RNA velocity：如果一个基因被激活了，未剪切的 RNA 会先于剪切的 RNA 产生。获得的 RNA velocity 输入 **CellRank** 来估计细胞命运。

**谱系追踪**根据细胞中观察到的变异（例如自然发生的基因突变）来推断其谱系模型，判断克隆群体中的细胞分裂历史，可以使用 **Cassiopeia** 提供的多种算法进行分析，建议对比多种算法的结果。同时还有能处理更加复杂谱系的 **LineageOT** 工具，以及追踪静态条形码的 **CoSpar**。

## 揭示机制 Revealing mechanisms

对数据进行注释后，可选的分析变得多样，根据研究问题选择要进行的后续分析。

### 差异基因表达分析 Differential gene expression analysis

目前单细胞的差异表达分析从两个思路进行：

- **样本层面的方法**：将单个样本中的多个细胞细胞读数合并，生成人工合成的批量样本，再利用常规的转录组差异表达分析工具，比如 edgeR、DESeq2 或是 limma。
- **细胞层面的方法**：利用广义混合效应模型（比如 MAST)，对单个细胞进行建模。

各个工具之间的一致性和稳健性较低，但相对而言，**为常规 DEG 设计的工具表现良好**，而单细胞特异性的方法通常会低估基因表达的变异程度，因此倾向于将高表达的基因错误标记为差异表达基因。因此推荐 limma、edgeR 或 DESeq2。

### 基因集富集分析 Gene set enrichment analysis

常见的数据库包括 MSigDB、Gene Ontology、KEGG 与 Reactome 等，此外还有用于癌症信号通路的 PROGENy 和转录因子的 DoRothEA。一般采用超几何分布检验、GSEA 或 GSVA 进行富集分析。研究发现富集分析对基因集的选择敏感性大于统计方法，因此应当谨慎选择数据库。decoupleR 等框架提供了多个不同数据库的访问方法。为常规转录组开发的方法可以用于单细胞数据，但一些基于单细胞的方法（比如 Pagoda2），效果可能优于前者。

### 检测细胞组成的变化 Deciphering changes in cell composition

成分分析比较的是不同细胞类型的相对丰度。单变量统计模型，比如泊松回归或是 Wilcoxon 秩和检验可能将部分细胞类型误报为有显著差异，而实际只是样本组成引起的假象。有专门为单细胞设计的 scDC、scCODA 和 tascCODA 测试方法。

### 推断扰动效应 Inferring perturbation effects

利用细胞培养体系，同时进行大规模多重条件处理细胞的方法称为扰动（perturbations），perturb-seq 或 CROP-seq 等最新技术允许使用多模态数据、全基因组扰动和组合扰动对混池 CRISPR–Cas9 筛选进行分析。

### 细胞通讯分析 Communication events across cells

细胞通讯分析利用配体、受体及其相互作用的数据库来预测细胞间相互作用。推荐使用 LIANA，它提供了多种方法和数据库。此外还有CellChat、CellPhoneDB、SingleCellSignalR；提供细胞内活动的补充估计的 Nichenet 和 Cytotalk。

## 原文
原文中还有关于单细胞 ATAC、单细胞蛋白组、空间转录组等内容，但目前还不太关注，就先不记录了。如果有需要还请阅读原文。

[Best practices for single-cell analysis across modalities](https://www.nature.com/articles/s41576-023-00586-w)</content:encoded></item><item><title>Docker 打包 Shiny App</title><link>https://blog.yorks0n.com/articles/docker-pack-shiny-app/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/docker-pack-shiny-app/</guid><description>介绍了如何将 Shiny App 打包成 Docker 格式，方便在不同设备环境下托管</description><pubDate>Tue, 28 Mar 2023 09:30:49 GMT</pubDate><content:encoded>## 文件准备

将Shiny用到的`server.R`和`ui.R`一起放在`app`文件夹中

```bash
./app:
server.R ui.R
```

写个`Dockerfile`，把用到的包都写在 `install.r` 后面

```bash
FROM rocker/r-base:latest
LABEL maintainer=&quot;email &lt;example@mail.com&gt;&quot;
RUN apt-get update &amp;&amp; apt-get install -y --no-install-recommends \
    sudo \
    libcurl4-gnutls-dev \
    libcairo2-dev \
    libxt-dev \
    libssl-dev \
    libssh2-1-dev \
    &amp;&amp; rm -rf /var/lib/apt/lists/*
RUN install.r shiny shinyBS dplyr stringr
RUN echo &quot;local(options(shiny.port = 3838, shiny.host = &apos;0.0.0.0&apos;))&quot; &gt; /usr/lib/R/etc/Rprofile.site
RUN addgroup --system app \
    &amp;&amp; adduser --system --ingroup app app
WORKDIR /home/app
COPY app .
RUN chown app:app -R /home/app
USER app
EXPOSE 3838
CMD [&quot;R&quot;, &quot;-e&quot;, &quot;shiny::runApp(&apos;/home/app&apos;)&quot;]
```

按以下方式进行构建

```bash
# name of the image
export IMAGE=&quot;yorks0n/trxiv_shiny&quot;

# build image
docker build -t $IMAGE .

# run and test locally
docker run -p 8080:3838 $IMAGE
```

居然就行了！

## 部署在 Railway 上

```bash
# 安装
brew install railway

# 登录
railway login
```

创建一个项目，并输入项目名称

```bash
➜ railway init
&gt; Project Name TRxiv_shiny
Created project TRxiv_shiny on Personal
```

虽然当前目录下有个 `Dockerfile` 了，但是这 XX 的 railway 部署时候端口和默认 docker 的不太一样，或者我没找到哪里设置，所以如果要部署在 railway 上，还需要改一下 `Dockerfile`。虽然在这指定了`ENV PORT=3838`，但实际上 railway 每次开的端口都不太一样，所以标准 docker 的写法不太行。

```bash
FROM rocker/r-base:latest
LABEL maintainer=&quot;Yorkson &lt;yorks0n@qq.com&gt;&quot;
RUN apt-get update &amp;&amp; apt-get install -y --no-install-recommends \
    sudo \
    libcurl4-gnutls-dev \
    libcairo2-dev \
    libxt-dev \
    libssl-dev \
    libssh2-1-dev \
    &amp;&amp; rm -rf /var/lib/apt/lists/*
RUN install.r shiny shinyBS dplyr stringr
RUN addgroup --system app \
    &amp;&amp; adduser --system --ingroup app app
WORKDIR /home/app
COPY app .
RUN chown app:app -R /home/app
USER app
EXPOSE 3838
ENV PORT=3838
# 研究后发现，这里以获取PORT的方式，才能在 Railway 中部署
CMD [&quot;R&quot;, &quot;-e&quot;, &quot;shiny::runApp(&apos;/home/app&apos;, host = &apos;0.0.0.0&apos;, port=as.numeric(Sys.getenv(&apos;PORT&apos;)))&quot;]
```

```bash
railway up
```

## 参考资料

[在Windows系统下，基于WLS从零开始部署我的 R shiny项目到 Docker 中，并将镜像发布到 Docker Hub（内附详细操作流程）_douerw的博客-CSDN博客](https://blog.csdn.net/douerw/article/details/121256642)

[Dockerizing Shiny Applications](https://hosting.analythium.io/dockerizing-shiny-applications/)

[Dockerized Shiny Apps with Dependencies](https://hosting.analythium.io/dockerized-shiny-apps-with-dependencies/)</content:encoded></item><item><title>部署预印本追踪 TRxiv 到 Github Action</title><link>https://blog.yorks0n.com/articles/deploy-trxiv-github-action/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/deploy-trxiv-github-action/</guid><description>将JS写的抓取 Altmetric 热门预印本，与 bioRxiv API 结合后储存在 csv 文件中的过程，部署在 Github Action...</description><pubDate>Fri, 24 Mar 2023 16:30:23 GMT</pubDate><content:encoded>将JS写的抓取 Altmetric 热门预印本，与 bioRxiv API 结合后储存在 csv 文件中的过程，部署在 Github Action 中。官方文档写的顺序都有点混乱，网上找到的教程又经常都比较老了，因此自己记录一个。

## 新建Github仓库

新建一个public仓库，名叫TRxiv，并将远程仓库`git clone`到本地。

```bash
git clone git@github.com:Yorks0n/TRxiv.git

cd TRxiv

```

## 创建一个动作元数据文件

要让仓库里能被以Action的形式直接调用，需要在**根目录**中创建一个`action.yml`配置文件，可以在这个文件中指定Action的输入和输出，调用的参数及运行环境

```bash
# action.yml
name: &apos;trxiv&apos;
description: &apos;Tracking popular bioRxiv and medRxiv preprints&apos;

runs:
  using: &apos;node16&apos;
  main: &apos;dist/index.js&apos;
```

## 准备运行的代码

手动将写好的JS脚本拷贝进来，完整代码在此 [Yorkson/TRxiv](https://github.com/Yorks0n/TRxiv)。

```bash
# 在这里初始化一下npm
npm init -y
```

准备一个`.gitignore`文件，防止在推送的时候把不必要的文件放到储存库，可以用下面这个工具，或者自己写一下，比如这里就可能有`node_modules` 

[https://www.toptal.com/developers/gitignore](https://www.toptal.com/developers/gitignore)

## 文件推送到远程仓库

然后push到远程仓库

```bash
git add .
git commit -m &quot;Initialize&quot;
git push
```

## 打包软件

因为前面把`node_modules` 从上传的文件列表中忽略了，但脚本`index.js`内有些依赖的包，所以最好把软件和依赖打包在一起，官方推荐用`ncc` 

```bash
npm install @vercel/ncc
```

然后对`index.js` 进行打包

```bash
ncc build index.js -o dist
```

打包产物会存放于`dist/index.js`

## 创建工作流

在本地创建`.github/workflows/main.yml`，这个文件实际确定了 Github Action 的行为，此`yml`格式文件一定要注意正确的缩进。

配置文件内容：

```bash
# main.yml
## 动作的名称
name: &apos;TRxiv update&apos;

# 触发条件
## 条件1，代码push进仓库
## 条件2，定时任务，在UTC 10和22点，即北京时间18点和6点运行
on:
  push:
  schedule:
    - cron: &apos;0 10,22 * * *&apos;

# jobs 定义了要执行的一系列任务 

jobs:
  ## 这个job的名称
  TRxiv_update_job:
    ## runs-on 内置运行任务的server类型
    runs-on: ubuntu-latest
    name: Update the csv file
    steps: 
      ## 必须有这一步，让运行的文件夹成为一个git repo
      - uses: actions/checkout@v3
      ## 运行脚本，指向我们的repo
      - name: &apos;run script&apos;
        uses: Yorks0n/TRxiv@main
      ## 运行完后，把运行产生在本地的data.csv更新回仓库中
      - name: Commit files
        run: |
         git config --local user.email &quot;github email adress&quot;
         git config --local user.name &quot;github user name&quot;
         git pull
         git add README.md
         git add data.csv
         git commit -m &quot;update data.csv&quot;
        shell: bash
      ## 使用秘钥确认具有上传权限，同时以秘钥方式提交不会触发push action，避免陷入loop
      - name: Push changes
        uses:  ad-m/github-push-action@master
        with:
         github_token: ${{ secrets.MY_GIT_TOKEN }}
         branch: main
```

## 再次将文件推送到远程仓库

```bash
git add .
git commit -m &quot;Update Workflow&quot;
git push
```

## 后续更新

每次想更新修改前，先在目录中把最新版的环境拉下来

```bash
git pull
```

**修改过脚本后，要重新打包用到的代码**：`ncc build index.js --license licenses.txt`

然后再提交回仓库

## 参考

[How to Build Your First JavaScript GitHub Action](https://www.freecodecamp.org/news/build-your-first-javascript-github-action/)

[如何使用 Github Actions 自动抓取每日必应壁纸?](https://zhuanlan.zhihu.com/p/354188341)

[Permission denied to github-actions[bot]](https://stackoverflow.com/questions/72851548/permission-denied-to-github-actionsbot)

[Creating a JavaScript action - GitHub Docs](https://docs.github.com/en/actions/creating-actions/creating-a-javascript-action)</content:encoded></item><item><title>Hello, again</title><link>https://blog.yorks0n.com/articles/hello-again/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/hello-again/</guid><description>我为什么又开始写 Blog 了？</description><pubDate>Fri, 24 Mar 2023 15:29:49 GMT</pubDate><content:encoded>兜兜转转又开始写 Blog 了，之前几次都没写过多少文章。实际花在折腾 Blog 的时间，远比真正写东西的时间更多。因为没啥值得看的内容，页面无法访问了也一直没有去解决。

但这次再开博客，倒不是有了汩汩冒出的表达欲，而是自一年前在少数派开始写点文章后，逐渐感受到了输出的重要。之前学习各种东西的过程中一直在输入，会记下不少笔记，但很少整理，几乎就堆在各种笔记软件中。时隔很久再去看，也还是最初的样子，往往看的时候已经不太记得当初某一步为什么要这样设置，或是做了哪些没有记录下来的操作。因此，准备把自己折腾过的东西整理成可以复现的形式，也是更好掌握和回顾知识的过程。

另一方面，在这几年的学习过程中，几乎都是通过搜索引擎与自学研究各种东西，看到高质量的内容中，除了诸多官方提供的教程，就是许多人在博客中记录的学习心得，受益良多。因此，假如能进行一定输出，说不定也能在未来的哪一天帮上其他人的忙。

最后，从去年年底开始，以 ChatGPT 为首的大语言模型，不由分说地闯进了人们的生活中。目前，我也几乎每天都会用到它，但几乎只局限在遇到不懂问题时候的 Q&amp;A。但 LLM 的一大限制因素就在于优质内容的输入，在内容工厂的摧残下，中文互联网的内容良莠不齐。因此也希望我写的文章，能在将来的某一天，为模型输出更好的结果贡献一点微小的概率。

----
又及，还没有想好怎么对文章进行分类，索性先写起来。同时会把以前写过的东西也都整理到一起，因此日期早于这篇文章的内容，都应该是在其他地方已经发过的。整理搬运过程估计还会持续很久，但已经发现 Gridea 插入图片不太趁手了，估计迟早会再换种部署方式，也许是 Hugo 吧。</content:encoded></item><item><title>1 dataset 100 visualizations 中有意思的可视化</title><link>https://blog.yorks0n.com/articles/interesting-1-dataset-100-visualizations/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/interesting-1-dataset-100-visualizations/</guid><description>分享最近看到的一组有意思的数据可视化</description><pubDate>Thu, 09 Mar 2023 20:40:01 GMT</pubDate><content:encoded>分享最近看到的一组有意思的数据可视化。
由 ferdio 出品的，主题为「1 dataset 100 visualizations」。他们选用了一组非常简单的数据，用一百种不同的图进行可视化，借此「展示数据可视化的多样性和复杂性，以及如何使用有限的视觉元素来讲述不同的故事」。尽管使用了相同的原始数据，但每张图都有其独特的重点，传递出的信息也不尽相同。
![](./images/1680530087246.png)

我计划从中选几个有代表性的图，并尝试解读这种可视化突出了数据怎样的特点。
先从比较常见的开始，下面两张图都是将数值编码成了长度，算是最常见的柱状图了。依照组合顺序的不同，左图将相同年份的数据摆在一起，更能突出相同年度中，几个国家之间谁的数量更多；右边的图将同一国家两个年度的数据放在一起展示，更能体现出每个国家世界遗产数量都在上升这个趋势。
  ![](./images/1680530106670.png)
与此同时，假如使用堆积柱状图，则突出的是两个年度，这三个国家世界遗产总量的增长趋势。
  ![](./images/1680530119989.png)
另外，上面几张图中还有一个特点，它们都将各个部分的具体数值直接标注在了对应的区域。这种方式蛮好，可以减轻看图时「视线需要在坐标轴和数据间反复切换，估算数值」所产生的负担。在这样处理的图中，即使完全删去纵坐标轴也不影响数据解读。

下面这两张图则是让我比较眼前一亮的（尤其是下面第二张），仔细去看，它们虽然形状不太相似，但实际是几乎一样的两张图——用在一条直线上的位置标记多个数据点的数值。我觉得它们好在以下几个方面：
-	清晰明了，无论是比较同一年度各个国家的数值（点的位置），还是增长幅度（两点间的连线长度）都一目了然
-	节约空间，如果把第二张图放平，只占据柱状图单个柱子的空间，就足以展示六条柱子所传达的信息
-	可以体现出跨越性的增长与压倒性的优势：丹麦（橙色）的世界遗产数量从04年的不如挪威（深蓝色），到22年超越挪威，这种跨越性的增长趋势在这两张图中一目了然，反观上面的几个柱状图，都需要在柱子长度间反复多次比较数值，才能观察到这种变化；另一方面，瑞典（蓝色）无论哪个年度的数量都远超另外两个人国家，这个结论在前面的图中也能通过比较得出，但在这张图中尤其清晰。
究其原因，这两张图将本身分散的长度、位置信息合并在了同一条线上，使得相互间的比较更为容易。但它也有一些缺点：
-	假如是多个时间点，比如三个年度，在这张图中就容易造成混乱
-	这批数据的变化趋势一致，都是22年的数值高于04年，假如在不同国家间，有的数量增加，有的数量减少，可能就需要带箭头的线段才能表示年份间的变化趋势。
  ![](./images/1680530135444.png)
同样，假如不放在一条直线上，而是按位置分开的图也有，比如下面这张图。上面提到的一些优点，比如增长幅度的大小、丹麦超越性的增长、瑞典压倒性的数量也都可以看到，但少了在原位的国家名称与数量标注，感觉就没那么醒目了。但这张图也有它的优点：使用颜色来表示年份而不是国家，假如有国家的数量下降了，在这张图上就会很好地展现出来。
 ![](./images/1680530144415.png)
这次就先写这些，溜了溜了。
如果对更多可视化感兴趣，或是想找找新的画图思路，可以直接去原网站查看可视化结果。

## 参考资料
[1 dataset. 100 visualizations.](https://100.datavizproject.com/#)</content:encoded></item><item><title>论文可视化配色简易指南</title><link>https://blog.yorks0n.com/articles/color_guide/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/color_guide/</guid><description>论文作图时用得上的配色技巧与工具</description><pubDate>Tue, 20 Sep 2022 00:00:00 GMT</pubDate><content:encoded>注：本文首发于少数派，此处有删改，您可以 [前往此处](https://sspai.com/post/75989) 阅读修订后版本。

## 色彩模型

### 人眼的色彩感知

我们能看到颜色主要与人眼的生理特性有关，视杆细胞和视锥细胞在其中发挥了重要作用。其中，视杆细胞主要负责感受光的明暗，视锥细胞负责感受不同波长的光。大多数人有三种不同类型的视锥细胞，它们各自对不同波长的光有不同的灵敏度：红色、绿色和蓝色。当某些视锥细胞缺失或敏感度发生变化，将导致色觉异常。

![三种视锥细胞对不同光波长的光具有不同的敏感度。来源：](./images/color_selection.png)

三种视锥细胞对不同光波长的光具有不同的敏感度。来源：

### RGB 模型

RGB 模型绝对称得上是数字时代最为常见的色彩模型，它将红色（R）、绿色（G）、蓝色（B）三种颜色的光，按照不同比例混合，得到各种不同的颜色。RGB 模型如此流行，一方面是因为它符合人眼对色彩的感知过程（对应三种视锥细胞），另一方面，屏幕上的每个像素也都是由红绿蓝三个次级像素组成，直接以此方式编码， 极大地方便了在屏幕上进行显示。

![RGB色彩模型](./images/color_selection%201.png)

RGB色彩模型

### HSB/HSV

虽然 RGB 模型既常用又方便理解，但它并不符合人对颜色的直观感受。我们看到某个颜色时，不会把它拆分成红绿蓝三个组分，而是直接感知三种视锥细胞叠加后的效果。因此，后来又出现了称为 HSV 的色彩模型（也称HSB）。

![color_selection](./images/color_selection%202.png)

你也许在选颜色时见到见过这种模型，它仿佛将所有颜色放入了一个倒置的圆锥。

HSV 模型采用三个维度的数值描述颜色：

- 色相（Hue），圆锥的最外围一圈，即它是什么颜色；
- 饱和度（Saturation），圆锥上某个点到中轴的距离，离中轴越近饱和度越低，颜色也越接近黑白灰；
- 亮度（Brightness 或 Value），圆锥上点到尖端的距离，越接近尖端，亮度越低（越黑）。

那 HSV 相比 RGB 直观在哪里？举个例子，左边颜色只降低亮度后，可以得到右边的颜色；但要是通过 RGB 来调整，就需要同时调整红绿蓝三种颜色值，颜色很容易一下就偏得没边了。

![color_selection](./images/color_selection%203.png)

### 为什么要有不同的色彩模型

一个很好的例子是地图制图投影方式和飞行路径图，我们可以将不同的色彩空间模型视为不同的地图投影方式。根据选择地图类型（色彩空间）的不同，同样的飞行路径可能看起来大不一样。

![墨卡托投影地图上从洛杉矶到莫斯科、纽约到莫斯科的飞行路线。](./images/color_selection%204.png)

墨卡托投影地图上从洛杉矶到莫斯科、纽约到莫斯科的飞行路线。

![正射投影](./images/color_selection%205.png)

正射投影

## 根据数据类型选择颜色

![color_selection](./images/color_selection%206.png)

### 类别色阶（**Categorical color scales**）

类别数据使用类别色阶。

当数据是一组类别时，它们没有内在的顺序，比如不同的分组实验材料。下图中不同的国家，并不会说某个国家比另一个国家排在前面或是后面，就属于**类别数据，因此要用类别色阶**（**Categorical color scales**）。

何为类别色阶？红色、黄色、蓝色，它们适合区分没有内在顺序的类别，其中一种颜色并不比另一种颜色更重要。

![color_selection](./images/color_selection%207.png)

### 单向色阶（**Sequential color scales）**

连续色阶是**从暗到亮/从亮到暗的颜色渐变**，它们适合可视化从低到高变化的数值数据，比如温度、质量或浓度。

![From ****Chroma.js Color Palette Helper****](./images/color_selection%208.png)

From ****Chroma.js Color Palette Helper****

![color_selection](./images/color_selection%209.png)

这时并不是说就不能分组，你依然可以将特定数值划分成一个个区间，对每个区间采用一个颜色。

![color_selection](./images/color_selection%2010.png)

或是不划分区间

![color_selection](./images/color_selection%2011.png)

注意⚠️：

- 在单向的顺序色阶中，只能使用一到两种色调，比如浅蓝色到深蓝色（单色，蓝色），或是从浅黄色到深蓝色（双色，蓝色和黄色）。
- 好的顺序色阶中，变化的并不只是颜色的色相（Hue），颜色的亮度（Lightness）与饱和度也在同步变化。
- 对低值使用浅色，对高值使用深色（亮度更低、饱和度更高）。使用颜色渐变时，请确保亮色代表低值，而深色代表高值。对于大多数读者来说，这将是最直观的
  
    ![color_selection](./images/color_selection%2012.png)
    

### 双向色阶（**Diverging color scales**）

双向色阶（Diverging / bipolar / double-ended color scales）与单向色阶类似，但是它不再是亮度或饱和度的从低到高变化，它中间亮度更高，然后向两侧色调与亮度同时变化。

![color_selection](./images/color_selection%2013.png)

双向色阶通常用于：

- 正值和负值这样两端有明确对立关系的值
- 有个有意义的中间点，比如0、50%、平均值、选定的阈值

![color_selection](./images/color_selection%2014.png)

同单向色阶一样，双向色阶也可以再分为分组和不分组两种：

![双向，分组](./images/color_selection%2015.png)

双向，分组

![双向，不分组](./images/color_selection%2016.png)

双向，不分组

## 从色彩集中选择颜色

这里介绍四个工具

[The Data Viz Color Picker](https://www.learnui.design/tools/data-color-picker.html#palette)

[Colorpicker for data](https://tristen.ca/hcl-picker/#/hlc/6/1/15534C/E2E062)

[CARTOColors - CARTO](https://carto.com/carto-colors/)

[chroma.js palette helper](https://vis4.net/palettes/#/9%7Cs%7C00429d,96ffea,ffffe0%7Cffffe0,ff005e,93003a%7C1%7C1)

### Data Viz Color Picker

****PALETTE****

![color_selection](./images/color_selection%2017.png)

****SINGLE HUE****

![color_selection](./images/color_selection%2018.png)

****DIVERGENT COLOR****

![color_selection](./images/color_selection%2019.png)

### ****Colorpicker for data****

![color_selection](./images/color_selection%2020.png)

### **CARTOColors**

****Sequential schemes****

![color_selection](./images/color_selection%2021.png)

****Diverging schemes****

![color_selection](./images/color_selection%2022.png)

****Qualitative schemes****

![color_selection](./images/color_selection%2023.png)

## 注意事项

### 色觉异常

前面提到，由于有三种视锥细胞存在，我们可以感知红绿蓝三种颜色极其组合。如果其中某种视锥细胞的灵敏度不够，那么会导致色弱；如果某种细胞完全不起作用，那么就会导致色盲。因此有三种不同类型的色弱，和三种不同类型的色盲。

在人群中，色弱相比色盲更加常见，大约6-7%的男性有某种色弱，而大约2-3%的男性是色盲。

![color_selection](./images/color_selection%2024.png)

因此，某些颜色的组合应当避免，比如红色-绿色-棕色。

![color_selection](./images/color_selection%2025.png)

我们比较熟悉的荧光图中也会倡议使用洋红色+绿色的组合，而不是红色和绿色的组合。

另一方面，在选择颜色时，不仅在色相（Hue）上发生变化，也让饱和度和亮度同时变化，也有助于增加色彩的区分度。一些工具会给出相同配色在不同色觉异常人士眼中的效果。

![color_selection](./images/color_selection%2026.png)

![color_selection](./images/color_selection%2027.png)

![color_selection](./images/color_selection%2028.png)

![color_selection](./images/color_selection%2029.png)

还有一种方式，是用颜色和模式同时来表示不同的类别，比如加上阴影，或是采用不同的虚实线段。

![color_selection](./images/color_selection%2030.png)

![color_selection](./images/color_selection%2031.png)

### Less is more

如非必要，勿增实体

- 是否有替代渐变色的数值表示方式（能不用，就不用）
  
    比如采用长度（条形图）、位置（点图）或是面积的大小
    
    ![color_selection](./images/color_selection%2032.png)
    
- 避免同时使用过多颜色（能少用，不多用）
  
    如果图中使用了超过七种颜色，可能要考虑其他的图表类型，或是将类别组合在一起。
    
    颜色本身是帮助读者区分类别的，但是颜色越多，就越难快速阅读和理解，在读图时将不得不反复在图例和图形间来回查阅。
    
    ![color_selection](./images/color_selection%2033.png)
    

### 更好地分配颜色

对相同变量使用相同颜色，简化理解过程

![color_selection](./images/color_selection%2034.png)

配合图例解释颜色指代的内容：图形的大小代表什么、深浅是对应哪个变量，这些都需要解释清晰。

![color_selection](./images/color_selection%2035.png)

详略得当地使用颜色，将不重要的元素用灰色或其他非常浅的颜色来表示，可以突出需要重点关注的数据

![color_selection](./images/color_selection%2036.png)

保证对比度，避免使用互补色（比如红配绿、橙配蓝）

![color_selection](./images/color_selection%2037.png)

避免使用彩虹色渐变

彩虹色渐变有几个大的问题：

- 它的颜色变化并不均匀，其中绿色占据了几乎1/3的范围
- 各种颜色之间的亮度变化不均一

![color_selection](./images/color_selection%2038.png)

## 参考资料

**Star:**

[Colorimetry and the Cartography of Color](https://medium.com/thinking-design/colorimetry-and-the-cartography-of-color-415ef5315c0a)

色彩空间

[弄清色彩的作用和表达 - 少数派](https://sspai.com/post/72510)

不同的色彩模型

[Which color scale to use when visualizing data - Datawrapper Blog](https://blog.datawrapper.de/which-color-scale-to-use-in-data-vis/)

根据数据类型（离散、连续）选择颜色

[What to consider when choosing colors for data visualization](https://blog.datawrapper.de/colors/)

一些颜色安排上的注意事项

[Spectrum, Adobe&apos;s design system](https://spectrum.adobe.com/page/color-for-data-visualization/)

选择颜色的注意事项

[How The Rainbow Color Map Misleads](https://eagereyes.org/basics/rainbow-color-map)

彩虹色渐变为什么不合适

[How your colorblind and colorweak readers see your colors - Datawrapper Blog](https://blog.datawrapper.de/colorblindness-part1/)

色觉异常

**Other:**

[When to use sequential and when to use diverging color scales - Datawrapper Blog](https://blog.datawrapper.de/diverging-vs-sequential-color-scales/)

[When to use classed and when to use unclassed color scales - Datawrapper Blog](https://blog.datawrapper.de/classed-vs-unclassed-color-scales/)

[Your Friendly Guide to Colors in Data Visualisation](https://blog.datawrapper.de/colorguide/)

[10 ways to use fewer colors in your data visualizations - Datawrapper Blog](https://blog.datawrapper.de/10-ways-to-use-fewer-colors-in-your-data-visualizations/)

如何减少使用的颜色数量

[A map from Great Circle Mapper](http://www.gcmap.com/mapui?P=svo-lax&amp;MS=bm&amp;DU=mi&amp;SG=0.82&amp;SU=mach)

大圆航线

[Coloring for Colorblindness](https://davidmathlogic.com/colorblind/#%23000000-%23E69F00-%2356B4E9-%23009E73-%23F0E442-%230072B2-%23D55E00-%23CC79A7)

色觉异常的颜色选择</content:encoded></item><item><title>Karabiner 助力，让你的键盘操作快人一步</title><link>https://blog.yorks0n.com/articles/karabiner/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/karabiner/</guid><description>如何借助 Goku 书写 Karabiner 配置文件</description><pubDate>Thu, 16 Jun 2022 13:19:19 GMT</pubDate><content:encoded>注：本文首发于少数派，您可以 [前往此处](https://sspai.com/post/73827) 阅读修订后版本。

Karabiner 全称 Karabiner-Elements[^下文简称为 Karabiner]，是 macOS 上的一款功能强劲的改键工具，可以将键盘上的按键映射成其他一个或多个按键组合。然而，Karabiner 使用JSON 作为配置文件，非常繁琐且不易理解，给上手带来了很高的门槛。

![上图展示了 Karabiner 中与 Goku 中，实现相同效果所需要的写法差异。](./images/carbon.png)

上图展示了 Karabiner 中与 Goku 中，实现相同效果所需要的写法差异。

于是，有人专门为其制作了一个工具「Goku」，借助 [Goku](https://github.com/yqrashawn/GokuRakuJoudo) 可以方便地为 Karabiner 进行配置。

**准备工作：**

- Karabiner-Elements 可以从[官网](https://karabiner-elements.pqrs.org/)进行下载
- Goku 使用 Homebrew 进行安装：`brew install yqrashawn/goku/goku`
- 在 Karabiner 中确保配置文件 Profiles 选择默认的 Default
- 前往 `~/.config/`目录，创建名为 `karabiner.edn` 的 Goku 配置文件
- 参考下文进行配置文件的编辑，每次编辑完后在终端中执行 `goku` 使修改生效

## 将 Caps Lock 变为键盘功能的中枢

通常，我们将`⌃Control + ⌥Option + ⇧Shift + ⌘Command` 同时按下的组合称为 Hyper 键，因为程序内置的快捷键不会预设这么复杂的组合，因此使用 Hyper 键设定快捷键，能最大程度上避免与预设发生冲突。

大写锁定键 `Caps Lock` 位于键盘左侧中间，用起来很顺手，但我只用它切换输入法，输入大写字母靠 `⇧shift`，因此这里先对它下手，你也可以选择其他顺手且不常用的按键。

以下的 Goku 配置文件 `karabiner.edn` 写法，可以将大写锁定键修改为 Hyper 键，这时只需要按下这一个键，就可以发挥 `⌃Control + ⌥Option + ⇧Shift + ⌘Command` 同时按下的效果。

```clojure
{
:main [
       {:des &quot;caps_lock -&gt; hyper&quot;
         :rules [
                 [:##caps_lock :!CTOleft_shift]
                 ]}
       ]
}
```

然而，如果只是将 `Caps Lock` 转化为 Hyper 键，它会失去本身切换输入法的效果。幸好 Karabiner 支持在按键单独按下与组合按下时，为触发不同的效果。

以下写法可以让 `Caps Lock` 与其他键一同按下时变为 hyper 键，单独按下时触发 `Control+Space` 切换输入法。

```clojure
{
:main [
       {:des &quot;caps_lock -&gt; Ctrl+space(alone) and caps_lock -&gt; hyper&quot;
         :rules [
                 [:##caps_lock :!CTOleft_shift nil {:alone :!Tspacebar}]
                 ]}
       ]
}
```

以下是一些常用按键在 Goku 中的简化写法：

```clojure
    ;; !  | means mandatory -   modifier(s) alone when pressend change behavior
    ;; #  | means optional  -   modifiers are optional (but at least one necessary)

    ;; :!Ca is keycode :a and prefix a with !C

    ;; C  | left_command
    ;; T  | left_control
    ;; O  | left_option
    ;; S  | left_shift
    ;; F  | fn
    ;; Q  | right_command
    ;; W  | right_control
    ;; E  | right_option
    ;; R  | right_shift

    ;; ## | optional any
    ;; !! | command + control + optional + shift (hyper)
```

而要知道键盘上每个按键各叫什么名字，可以使用 Karabiner 配套的 Karabiner-EventViewer 进行查看。

## 结合 Keyboard Maestro 实现快速搜索

单靠 Karabiner 只能发挥其一半的功力，要想发挥其全部实力，还是要与 Keyboard Maestro（下称 KM）或是 Alfred 这些支持自动化的工具搭配，才能达到强强联合的效果。这里以 KM 为例，实现快速搜索选中的内容。

在 KM 中创建如下图的 Macro，为其指定 `Hyper + S` 的组合键，这样只需要选中想搜索的内容，按下快捷键即可使用 Google 进行搜索。

![karabiner](./images/karabiner.png)

同时，借助 KM 独特的冲突调色盘功能，当你为多个 Macro 设定了相同快捷键，按下快捷键后会触发选择界面，借此只需记忆一个快捷键，便可触发多种不同的搜索功能。

![karabiner](./images/karabiner%201.png)

## Hyper + 字母实现程序快速切换

日常使用时，常常需要在不同的应用间来回切换。cmd + tab 虽然可行，但每次的应用顺序不固定，还要找到想切换到的程序，甚至因此诞生了一些专门为切换应用而生的工具。利用 Karabiner 搭配 Keyboard Maestro，即可实现 `Hyper + 字母` 一键切换应用。

在 Keyboard Maestro 中添加 Macro， 选择 `Activate a Specific Application` 即可，配置成如下图即可在激活此 Macro 时切换到 Chrome。

![karabiner](./images/karabiner%202.png)

这时，如果在 KM 中将 New Trigger 设置为按键的 `Hyper + c`，即可在按下此组合键时快速切换到 Chrome。

但这毕竟是一篇介绍 Karabiner 的文章，因此我演示一下如何在 Karabiner 的配置文件中，直接激活特定的 Macro。

以下配置文件可以实现 `Hyper + C` 切换到 Chrome 的效果。

```clojure
{
:templates {:km &quot;osascript -e &apos;tell application \&quot;Keyboard Maestro Engine\&quot; to do script \&quot;%s\&quot;&apos;&quot;
            }

:main [
       {:des &quot;caps_lock -&gt; Ctrl+space(alone) and caps_lock -&gt; hyper&quot;
         :rules [
                 [:##caps_lock :!CTOleft_shift nil {:alone :!Tspacebar}]

                 [:!!c [:km &quot;open: chrome&quot;] ] ;;caps+c open Chrome
                 
                 ]}
       ]
}
```

我在前面模板的基础上增加了两部分：

- 开头利用 `:templates` 创建了一个名为 `:km` 的脚本，可以快速激活 KM 中的Macro；
- 在 `:rules` 中新增加了一行规则，`:!!c` 表示 `Hyper + C` 的组合键[^这里 !! 是 hyper 键的缩写写法]，`:km &quot;open: chrome&quot;` 则表示调用前面创建的 `km` 脚本，并执行 `&quot;open: chrome&quot;` 这个 Macro。

## 进阶，让每个键都能成为修饰键

`Hyper` 键只有一颗，用久了总有因为键位冲突感到不够的那天，比如我既想用 `S` 键触发 Search，又想用它激活 Sorted 3。这部分我将介绍如何利用层（layer）的概念，让键盘上的每个键都能成为独一无二的修饰键。

所谓层，可以理解为按下某个键后，键盘上其他键的功能随之发生变化，例如下图就是按下 `option` 键后键盘的变化，我们可以称之为 option 层。

![Kapture 2022-06-15 at 21.39.24.gif](./images/Kapture_2022-06-15_at_21.39.24.gif)

如下规则定义了一个称为「semicolon-mode」的层，在这里我将使用频率较低的分号`;`定义为触发按键：

- `:semicolon [&quot;semicolon-mode&quot; 1]` 指按下分号「semicolon」后，将变量 `semicolon-mode` 设置为 1，即进入「semicolon-mode」层；
- `:afterup [&quot;semicolon-mode&quot; 0]` 指松开分号后，将变量 `semicolon-mode` 设置为 0，即退出「semicolon-mode」层；
- 单独按下依然为分号本身 `:alone :semicolon` 。

在 `[:hyphen [:km &quot;insert: underline&quot;] [&quot;semicolon-mode&quot; 1]]` 这里，我定义了按下减号`-` ，触发 KM 中名为 `&quot;insert: underline&quot;` 的 Macro，输出一个下划线，这个规则只在`[&quot;semicolon-mode&quot; 1]` 时（即按住分号时）才有效。

```clojure
{
:templates {:km &quot;osascript -e &apos;tell application \&quot;Keyboard Maestro Engine\&quot; to do script \&quot;%s\&quot;&apos;&quot;
            }

:main [
       {:des &quot;This is the semicolon-mode&quot; 
         :rules [[:semicolon [&quot;semicolon-mode&quot; 1]  nil {:afterup [&quot;semicolon-mode&quot; 0] 
                                                 :alone :semicolon}] 

                [:hyphen [:km &quot;insert: underline&quot;] [&quot;semicolon-mode&quot; 1]]  ;; semicolon - to insert _(underline)
        ]}

       ]
}
```

## 结语

「花一些时间，折腾一点小东西，收获一个没多大用的成果，感到巨大的快乐」，这是我对摸鱼的定义。摸鱼摸得久了，总能折腾出些有意思的东西。目前，我每天都用这些快捷键输入一些常用短语，切换程序或是快速搜索，省下的时间可能并没有多少，但是有种莫名的快乐，我觉得这就足够了。

## 相关文章

[macOS 改键利器：Karabiner-Elements 使用详解 - 少数派](https://sspai.com/post/46184)

[使用 Karabiner 改善 Poker 键盘体验 - 少数派](https://sspai.com/post/47659)

[让键盘变成你想要的样子：改键利器 Karabiner-Elements - 少数派](https://sspai.com/post/42921)

## 参考资料

[Karabiner God Mode](https://medium.com/@nikitavoloboev/karabiner-god-mode-7407a5ddc8f6)

[使用 Goku 配置 Karabiner](https://einverne.github.io/post/2020/08/use-goku-config-karabiner.html)

[yqrashawn/GokuRakuJoudo](https://github.com/yqrashawn/GokuRakuJoudo/blob/master/tutorial.md#advance3)</content:encoded></item><item><title>我的植物组学数据库合集 Ver.20220528</title><link>https://blog.yorks0n.com/articles/my-bioinfomatics-db-collection-ver20220528/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/my-bioinfomatics-db-collection-ver20220528/</guid><description>这是我日常会用到，整理出来的主要与植物学、基因组学有关的在线数据库集合。</description><pubDate>Sat, 28 May 2022 17:14:41 GMT</pubDate><content:encoded>## What

这是我日常会用到，所以整理出来的主要与**植物学、基因组学**有关的在线数据库集合。

链接在此：[database](https://raindrop.io/Yorks0n/database-23820830/search)

![](./images/1680599742462.png)

## How-to

我利用了「#标签」的形式对链接进行分类，因此在检索的时候，可以直接点击下面的标签进行选择，也可以在搜索框中以「#标签名」的形式输入一个或多个标签进行筛选，多个标签之间使用空格隔开。

![](./images/1680599748401.png)

举个例子，假如想寻找和拟南芥蛋白有关的数据库，则可以在下面的标签中依次点击「#拟南芥」和「#蛋白」，也可以直接在搜索框中输入这两个标签。

![](./images/1680599753486.png)

补充说明：

-   如果这个数据库只包含一个物种的数据，我会给它打上「#物种名」的标签，但如果它同时带有多物种内容，比如 NCBI 或是 Ensembl plants，我就不会给它打物种名的标签。
-   有些数据库我也没有想好怎样用最简短的标签进行概括，所以标签描述不一定完备，也欢迎提修改意见。

## Why and why

### 为什么要做这个

知识共享也好，流动着的知识才是好知识也好，可能就是我觉得有意思吧。

### 为什么不用文件夹

文件夹组成的是一种树状结构，然而每个数据库的属性并不是整齐的树状。比如一个数据库，即可以带有「拟南芥」的属性，表明它主要是一个拟南芥的数据库，同时它还可能带有一个「蛋白」的属性，表明其是蛋白质结构、或是蛋白修饰的数据库，因此这样的数据库并不能单一地根据物种或是数据类型进行分类。

### 为什么使用 [Raindrop.io](http://Raindrop.io)

我使用了书签管理服务 Raindrop，直接对其中一个文件夹进行共享，因为一方面发现它很方便，不论是检索还是发布；另一方面，我也想过用 Notion 或是飞书的在线文档形式，可能会更稳定一点，但是我懒，不想再一条条输一遍了，也许之后发布方式会改吧。

## 后续计划

### 如何更新

欢迎提意见和建议，包括如何改进标签，更准确地描述数据库；有哪些新的数据库值得加入进来，_Et cetera_。可以留言或直接与我联系。</content:encoded></item><item><title>利用 n8n 打造飞书 RSS 推送机器人</title><link>https://blog.yorks0n.com/articles/use_n8n_to_build_feishu_rssbot/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/use_n8n_to_build_feishu_rssbot/</guid><description>本文介绍了基于 n8n 搭建的自动化平台，实现监控 RSS 更新并推送到飞书消息的功能。</description><pubDate>Wed, 25 May 2022 10:19:19 GMT</pubDate><content:encoded>注：本文首发于少数派，您可以 [前往此处](https://sspai.com/post/73255) 阅读修订后版本。

## 前言

本文介绍了基于 n8n 搭建的自动化平台，实现监控 RSS 更新并推送到飞书消息的功能。

文末会列举一些实现此工作流的其他方式，包括发送请求和接收提醒的手段。同时，n8n 还可以通过模块组合，实现更多更复杂的功能，本文只作为抛砖引玉。

阅读本文可能需要一定 Linux 基础知识。

## n8n 是什么

n8n 是一个开源的自动化流程搭建工具，可以实现类似 IFTTT 的效果，比如「如果明天下雨，就推送要带伞的消息」。优点是开源、可以自己部署并将信息都储存在本地，同时可以与 Github、Telegram、Slack 等各种服务实现联动，以搭建自动化工作流。

## 利用 Docker 安裝 n8n

n8n 可以直接下载 Win 或是 Mac 版本，快速在本地使用，但如果想更稳定地长期运行，更适合部署在云服务器、树莓派或 NAS 等工具上。

这里以在云服务器上使用 Docker 进行部署为例，更多安装方式可参考 [Installation guides for n8n](https://docs.n8n.io/hosting/installation/)。

假设已经安装好了 Docker，那么 n8n 的部署就非常简单，先新建一个文件夹储存数据。

```bash
# 创建数据储存文件夹
mkdir ~/n8n-data
```

复制运行下面的代码，利用 Docker 安装 n8n。如果云服务器有防火墙，需要把对应的端口打开，这里需要打开`5678`的 TCP 端口。

```bash
# 利用Docker安装运行n8n
docker run -d \
--name n8n --restart unless-stopped \
-p 5678:5678 \
-v ~/n8n-data:/home/node/.n8n \
-e GENERIC_TIMEZONE=&quot;Asia/Shanghai&quot; \
n8nio/n8n 
```

稍作等待，等 Docker 安装完成后，如果一切顺利，访问`服务器ip地址:5678`就能看到 n8n 的运行页面了，初次进入需要创建账号密码。

![Untitled](./images/Untitled.png)

点击右上角的 New blank workflow 即可开始创建，也可以从软件提供的 Workflow 示例中，选择自己想部署的自动化流程。

这里以搭建一个 RSS 更新自动推送到飞书的机器人为例。

## 搭建飞书 RSS 推送机器人

以下是我配置好的一个流程模板，复制以下内容粘贴到 n8n 新建 workflow 的页面。

```json
{
  &quot;nodes&quot;: [
    {
      &quot;parameters&quot;: {
        &quot;url&quot;: &quot;https://sspai.com/feed&quot;
      },
      &quot;name&quot;: &quot;RSS Feed Read&quot;,
      &quot;type&quot;: &quot;n8n-nodes-base.rssFeedRead&quot;,
      &quot;typeVersion&quot;: 1,
      &quot;position&quot;: [
        160.5,
        440
      ]
    },
    {
      &quot;parameters&quot;: {
        &quot;conditions&quot;: {
          &quot;number&quot;: [
            {
              &quot;value1&quot;: &quot;={{new Date($node[\&quot;Latest Read\&quot;].data[\&quot;latestRead\&quot;]).getTime()}}&quot;,
              &quot;value2&quot;: &quot;={{new Date($node[\&quot;RSS Feed Read\&quot;].data[\&quot;isoDate\&quot;]).getTime()}}&quot;
            }
          ],
          &quot;boolean&quot;: [],
          &quot;string&quot;: [
            {
              &quot;value1&quot;: &quot;={{$json[\&quot;title\&quot;]}}&quot;,
              &quot;operation&quot;: &quot;contains&quot;
            }
          ]
        }
      },
      &quot;name&quot;: &quot;IF&quot;,
      &quot;type&quot;: &quot;n8n-nodes-base.if&quot;,
      &quot;typeVersion&quot;: 1,
      &quot;position&quot;: [
        560,
        440
      ]
    },
    {
      &quot;parameters&quot;: {
        &quot;functionCode&quot;: &quot;const staticData = this.getWorkflowStaticData(&apos;global&apos;);\n\nif (items.length &gt; 0) {\n  staticData.latestRead = items[0].json.isoDate || staticData.latestRead;\n}\n\n\nreturn items;&quot;
      },
      &quot;name&quot;: &quot;Write Latest Read&quot;,
      &quot;type&quot;: &quot;n8n-nodes-base.function&quot;,
      &quot;typeVersion&quot;: 1,
      &quot;position&quot;: [
        760,
        340
      ]
    },
    {
      &quot;parameters&quot;: {},
      &quot;name&quot;: &quot;NoOp&quot;,
      &quot;type&quot;: &quot;n8n-nodes-base.noOp&quot;,
      &quot;typeVersion&quot;: 1,
      &quot;position&quot;: [
        750,
        580
      ]
    },
    {
      &quot;parameters&quot;: {
        &quot;triggerTimes&quot;: {
          &quot;item&quot;: [
            {
              &quot;mode&quot;: &quot;everyX&quot;,
              &quot;value&quot;: 1
            }
          ]
        }
      },
      &quot;name&quot;: &quot;Cron&quot;,
      &quot;type&quot;: &quot;n8n-nodes-base.cron&quot;,
      &quot;typeVersion&quot;: 1,
      &quot;position&quot;: [
        -40,
        440
      ]
    },
    {
      &quot;parameters&quot;: {
        &quot;requestMethod&quot;: &quot;POST&quot;,
        &quot;options&quot;: {
          &quot;batchInterval&quot;: 3000,
          &quot;batchSize&quot;: 1
        },
        &quot;bodyParametersUi&quot;: {
          &quot;parameter&quot;: [
            {
              &quot;name&quot;: &quot;msg_type&quot;,
              &quot;value&quot;: &quot;interactive&quot;
            },
            {
              &quot;name&quot;: &quot;card&quot;,
              &quot;value&quot;: &quot;={\n  \&quot;config\&quot;: {\n    \&quot;wide_screen_mode\&quot;: true\n  },\n  \&quot;header\&quot;: {\n    \&quot;template\&quot;: \&quot;black\&quot;,\n    \&quot;title\&quot;: {\n      \&quot;content\&quot;: \&quot;{{$json[\&quot;title\&quot;]}}\&quot;,\n      \&quot;tag\&quot;: \&quot;plain_text\&quot;\n    }\n  },\n  \&quot;elements\&quot;: [\n    {\n      \&quot;tag\&quot;: \&quot;div\&quot;,\n      \&quot;text\&quot;: {\n        \&quot;content\&quot;: \&quot;{{$json[\&quot;contentSnippet\&quot;]}}\&quot;,\n        \&quot;tag\&quot;: \&quot;lark_md\&quot;\n      }\n    },\n    {\n      \&quot;tag\&quot;: \&quot;hr\&quot;\n    },\n    {\n      \&quot;elements\&quot;: [\n        {\n          \&quot;content\&quot;: \&quot;[阅读原文]({{$json[\&quot;link\&quot;]}})\&quot;,\n          \&quot;tag\&quot;: \&quot;lark_md\&quot;\n        }\n      ],\n      \&quot;tag\&quot;: \&quot;note\&quot;\n    }\n  ]\n}&quot;
            }
          ]
        },
        &quot;headerParametersUi&quot;: {
          &quot;parameter&quot;: [
            {
              &quot;name&quot;: &quot;Content-Type&quot;,
              &quot;value&quot;: &quot;application/json&quot;
            }
          ]
        }
      },
      &quot;name&quot;: &quot;HTTP Request&quot;,
      &quot;type&quot;: &quot;n8n-nodes-base.httpRequest&quot;,
      &quot;typeVersion&quot;: 1,
      &quot;position&quot;: [
        1000,
        340
      ]
    },
    {
      &quot;parameters&quot;: {
        &quot;functionCode&quot;: &quot;const staticData = this.getWorkflowStaticData(&apos;global&apos;);\n\nlatestRead = staticData.latestRead;\n\nfor (let item of items) {\n  item.json.latestRead = latestRead || &apos;2022-05-05&apos;;\n  //item.json[\&quot;content:encodedSnippet\&quot;] = item.json[\&quot;content:encodedSnippet\&quot;].replace(/[\\r\\n]/g,\&quot;\\\\n\&quot;);\n}\n\nreturn items;&quot;
      },
      &quot;name&quot;: &quot;Latest Read&quot;,
      &quot;type&quot;: &quot;n8n-nodes-base.function&quot;,
      &quot;typeVersion&quot;: 1,
      &quot;position&quot;: [
        360,
        440
      ]
    }
  ],
  &quot;connections&quot;: {
    &quot;RSS Feed Read&quot;: {
      &quot;main&quot;: [
        [
          {
            &quot;node&quot;: &quot;Latest Read&quot;,
            &quot;type&quot;: &quot;main&quot;,
            &quot;index&quot;: 0
          }
        ]
      ]
    },
    &quot;IF&quot;: {
      &quot;main&quot;: [
        [
          {
            &quot;node&quot;: &quot;Write Latest Read&quot;,
            &quot;type&quot;: &quot;main&quot;,
            &quot;index&quot;: 0
          }
        ],
        [
          {
            &quot;node&quot;: &quot;NoOp&quot;,
            &quot;type&quot;: &quot;main&quot;,
            &quot;index&quot;: 0
          }
        ]
      ]
    },
    &quot;Write Latest Read&quot;: {
      &quot;main&quot;: [
        [
          {
            &quot;node&quot;: &quot;HTTP Request&quot;,
            &quot;type&quot;: &quot;main&quot;,
            &quot;index&quot;: 0
          }
        ]
      ]
    },
    &quot;Cron&quot;: {
      &quot;main&quot;: [
        [
          {
            &quot;node&quot;: &quot;RSS Feed Read&quot;,
            &quot;type&quot;: &quot;main&quot;,
            &quot;index&quot;: 0
          }
        ]
      ]
    },
    &quot;Latest Read&quot;: {
      &quot;main&quot;: [
        [
          {
            &quot;node&quot;: &quot;IF&quot;,
            &quot;type&quot;: &quot;main&quot;,
            &quot;index&quot;: 0
          }
        ]
      ]
    }
  }
}
```

粘贴后可以看到如下的界面：

![Untitled](./images/Untitled%201.png)

这里有几处可以配置，第一处是 **Cron**，设置自动化流程触发的频率，每隔 X 时间间隔运行一次，图中设置为每隔一小时运行。在获取 RSS 时，运行频率不宜过高。如果访问过于频繁，一方面会给对方服务器造成较大负担，同时可能被服务器禁止访问。

![Untitled](./images/Untitled%202.png)

第二个是在 **RSS Feed Read** 处，填写想订阅的 RSS 地址，这里以少数派 RSS 为例，填写完后点击Excute node，先运行一次获取数据，方便后续设置。

![Untitled](./images/Untitled%203.png)

第三处（可选）**IF** 处，设置是否需要针对标题或内容等进行过滤，默认不过滤。

![Untitled](./images/Untitled%204.png)

这时先转到飞书，在**飞书桌面端**，打开一个群（建议先创建一个单人的群进行调试），打开**设置**，找到**群机器人**，并点击**添加机器人**，选择自定义机器人加入群聊，详细操作可以参照 [飞书自定义机器人指南](https://open.feishu.cn/document/ukTMukTMukTM/ucTM5YjL3ETO24yNxkjN?lang=zh-CN)。

![Untitled](./images/Untitled%205.png)

最后在 **HTTP Request** 处填入飞书机器人 webhook 地址。

![Untitled](./images/Untitled%206.png)

填写完成后 Excute node 尝试运行，一切顺利的话就能在飞书中看到推送来的RSS消息了。

![Untitled](./images/Untitled.jpeg)

这里使用了卡片的形式展示消息，若是想调整消息展示样式，可以参考少数派文章 [手把手教你用飞书 Webhook 打造一个消息推送 Bot](https://sspai.com/post/68578)。

![一图流配置](./images/Untitled%207.png)

一图流配置

## 消息机器人安全设置

由于采用 Webhook 的形式，请务必保管好 Webhook 链接，如果泄露可能会导致被推送垃圾信息。为了进一步加道保险，飞书提供了三种安全设置方式，分别是自定义关键词、IP 白名单和签名校验。

前两种方式非常好理解，也都很好设置。自定义关键词是只有当消息中至少含有一个预设的关键词时，才会进行消息推送；IP 白名单则是只推送名单中来源的 IP 所发送的请求。但是这两种方式也有一定的局限性：

- 关键词有时使消息不够简洁
- 部署在本地树莓派等设备上时，IP 地址不固定，无法指定
- 关键词和 IP 白名单各自最多只能添加十个条目

因此这里详细介绍一下在 n8n 中进行签名校验的配置方式。

飞书的签名需要将「timestamp + &quot;\n&quot; + 密钥」组合起来当作签名密钥，采用 Hmac SHA256 算法计算签名，再进行 Base64 编码。在发送消息请求时，需要增加对应的`timestamp`和`sign` 字段。

```json
// 开启签名验证后发送文本消息的请求示例
{
        &quot;timestamp&quot;: &quot;1599360473&quot;,
        &quot;sign&quot;: &quot;xxxxxxxxxxxxxxxxxxxxx&quot;,
        &quot;msg_type&quot;: &quot;text&quot;,
        &quot;content&quot;: {
                &quot;text&quot;: &quot;The message content is here&quot;
        }
}
```

在 n8n 中，可以使用 **Crypto** 模块利用密钥生成签名，复制以下代码粘贴到配置界面，可以得到生成飞书签名用的模块组合。

```json
{
  &quot;nodes&quot;: [
    {
      &quot;parameters&quot;: {
        &quot;action&quot;: &quot;hmac&quot;,
        &quot;type&quot;: &quot;SHA256&quot;,
        &quot;value&quot;: &quot;={{&apos;&apos;}}&quot;,
        &quot;dataPropertyName&quot;: &quot;sign&quot;,
        &quot;secret&quot;: &quot;={{$json[\&quot;timestamp\&quot;]+&apos;\\n&apos;+$json[\&quot;secret\&quot;]}}&quot;,
        &quot;encoding&quot;: &quot;base64&quot;
      },
      &quot;name&quot;: &quot;Crypto&quot;,
      &quot;type&quot;: &quot;n8n-nodes-base.crypto&quot;,
      &quot;typeVersion&quot;: 1,
      &quot;position&quot;: [
        -80,
        440
      ]
    },
    {
      &quot;parameters&quot;: {
        &quot;values&quot;: {
          &quot;string&quot;: [
            {
              &quot;name&quot;: &quot;timestamp&quot;,
              &quot;value&quot;: &quot;={{Math.round(new Date().getTime()/1000)}}&quot;
            },
            {
              &quot;name&quot;: &quot;secret&quot;
            }
          ]
        },
        &quot;options&quot;: {}
      },
      &quot;name&quot;: &quot;Set&quot;,
      &quot;type&quot;: &quot;n8n-nodes-base.set&quot;,
      &quot;typeVersion&quot;: 1,
      &quot;position&quot;: [
        -280,
        440
      ]
    }
  ],
  &quot;connections&quot;: {
    &quot;Set&quot;: {
      &quot;main&quot;: [
        [
          {
            &quot;node&quot;: &quot;Crypto&quot;,
            &quot;type&quot;: &quot;main&quot;,
            &quot;index&quot;: 0
          }
        ]
      ]
    }
  }
}
```

将上面新增的两个模块按下图方式进行拖拽连接：

![Untitled](./images/Untitled%208.png)

从飞书机器人设置界面中，勾选**签名校验**得到密钥，填写在 **Set** 模块中。

![Untitled](./images/Untitled%209.png)

接下来将 **Latest Read** 模块中的代码替换为以下内容，储存计算出的签名，方便在请求的时候调用。

```json
// JS code in the Latest Read Module
const staticData = this.getWorkflowStaticData(&apos;global&apos;);

latestRead = staticData.latestRead;

for (let item of items) {
  item.json.latestRead = latestRead || &apos;2022-05-05&apos;;
  item.json.timestamp = $item(&quot;0&quot;).$node[&quot;Crypto&quot;].json[&quot;timestamp&quot;];
  item.json.sign = $item(&quot;0&quot;).$node[&quot;Crypto&quot;].json[&quot;sign&quot;];
}

return items;
```

最后在 **HTTP Request** 模块中增加校验用的字段：Body Parameters - Add Parameter，添加两个参数，Name 分别为 `timestamp` 和 `sign`，Value 处点击右侧 Add Expression，再分别点击选择传入的两个对应字段的值。

![Untitled](./images/Untitled%2010.png)

这样一番倒腾，给飞书机器人模块增加了签名校验，使得信息推送更加安全。当一切配置妥当后，别忘了点击界面右上角的激活，让工作流开始自动运行。

![配置密钥验证一图流](./images/Untitled%2011.png)

配置密钥验证一图流

## 后记

本文介绍了如何用 n8n 打造一个飞书 RSS 推送机器人。订阅什么样的 RSS 来源，可以是网站自身提供的 RSS 地址，也可以利用 RSShub 将各种奇怪的网站转化为 RSS，甚至是利用 kill-the-newsletter 将任意 Newsletter 邮件转化为 RSS 进行追踪。

同时，实现类似工作流的手段还有很多。对于 n8n 这部分，可以使用 IFTTT、Integrately，或是 Github Action 等，实现工作流中「监控 RSS 更新并发送 Webhook 请求」这部分；对于接收提醒，文中利用了飞书作为展示消息的界面，而 n8n 也支持连接到 Telegram、Slack 等通讯软件，或是通过 Send Email 模块实现邮件通知，以及发送到 Cubox、flomo 等各种支持 Webhook 的工具中。

更多功能，更多组合，尽请探索，把闲置的云服务器或是积灰的树莓派等折腾起来吧。</content:encoded></item><item><title>「#」的前世今生</title><link>https://blog.yorks0n.com/articles/history_of_hash/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/history_of_hash/</guid><description>当看到「#」时，你会想到什么？</description><pubDate>Mon, 23 May 2022 10:19:19 GMT</pubDate><content:encoded>注：本文首发于少数派，您可以 [前往此处](https://sspai.com/post/73345) 阅读修订后版本。

## 千变万化的「#」

当看到「#」时，你会想到什么？

如果你下国际象棋，它可能代表着一局对决的终结[^国际象棋中，# 表示将军（checkmate）]；如果你是程序员，它可能是被 `#!` 指定的解释器，或是一行注释的开始；如果你刷微博，它可能是当前最热的话题。中文里，「#」通常称为「井字」或「井号」，在日语中称为「番号记号」或「井桁」，英式英语中则通常称之为「hash」。

「#」的大部分名称来源于其形状，含义却随着上下文发生变化。对大部分人而言，与「#」的第一次会面，大概是电话拨号盘角落中那个不起眼的方块。

## *libra pondo* 的千年的漫步

先将时间拨回罗马时期，那时「一磅重」被称为「*libra pondo*」，其中 *libra* 意思是尺度或是平衡；*pondo* 则来自于动词 *pendere*，表示「称重」。从这两个词根中，「#」得到了它最早的形状与名称。

十四世纪晚期，来源于 *libra* 的「lb」进入了英语中，同时配上了一条表明缩写的短线「~」，即 ℔。

由于 ℔ 在当时的广泛使用，部分早期印刷机开始把它作为了一个单独的字符进行印刷。

![Isaac Newton 所写的 ℔ 符号与 1698 年印刷品中的样子](images/hashtag.png)
左图是 Isaac Newton 所写下的 ℔ 符号，右图是它出现在 1698 年印刷品中的样子。

随着之后的发展，℔ 逐渐演变成了两个不同的形式：

- 来源于抄写员潦草笔记的「#」
- 没有短线修饰代表磅的「lb」

而这个符号本身，却则淹没在时间长河中。

与此同时，它的老搭档 *pondo* 也开始了独自的演变之路。它先以 *pund* 的形式出现在古英语中，又在现代英语中成为 pound。历经数千年，*libra* 与 *pondo*，这一对古老的搭档，最终又重新连接在一起。[^在美式英语中，# 被称为 pound sign]

如果不是偶然的经历，也许「#」将一直存在于生活不起眼的角落，默默无闻地行使它最初的功能。

## 拨号盘一隅

在电话出现的早期，拨号数字利用脉冲拨号（Pulse dialing）进行传输。在这种技术中，每个数字对应一到十次脉冲信号。上世纪40年代末，贝尔实验室发明了一种新的拨号系统。新系统在每个数字被按下的时候，发出一个独特的声音信号，被称为双音多频（Dual-Tone Multi-Frequency）。然而直到1968年，电话上的拨号键还只有 0-9 的按键。

![早期转拨盘式电话与 WE 1500 按键电话](images/Snipaste_2023-05-18_21-10-40.png)
左图，早期使用脉冲拨号的转拨盘式电话；右图，贝尔实验室于 1963 年推出的世界第一台按键电话 WE 1500。

1968年，为了实现菜单选择等更多功能，贝尔实验室计划在数字 0 按键的两侧添加两个新的按键。在设计拨号盘新样式的过程中，曾诞生过一系列尝试性设计，比如在 0 的两侧分别增加带有五角星与菱形符号的按键。然而这些字符在当时标准的打字机键盘上并不存在，导致记录时会产生障碍。

此时，负责新拨号系统设计的贝尔实验室的工程师 Douglas A. Kerr，被任命选择更加合适的符号替代它们。

![Douglas A. Kerr](images/hashtag-2.png)

Douglas Kerr 曾经担任设计美国信息交换标准代码（ASCII）的委员会负责人。基于过去的工作经验，也考虑到打字机的键盘设计，他与团队最终选择了包含在 ASCII 字符集中的「*」与「#」作为新的按键符号。

这个决定，使得「#」以前所未有的姿态进入了世界上绝大多数人的生活，它也将比历史上任何时候都更为人所熟悉。

## 来「#」聊天吧

1988年，Jarkko Oikarinen 创建 Internet Relay Chat (IRC)，这是一个基于文本的即时聊天系统。它被设计用于以组群的形式进行多人聊天，许多人可以加入同一个称为频道（channel）的组群中，频道的名称以「#」开头，用户可以用 `/join #channelname` 的方式加入某一个频道。

![IRC 客户端 HexChat 截图](images/354f6753b4f984b446c521dac65c9297.png)

2007年，曾经在 Google 和 Uber 担任开发主管的 Chris Messina 在 Twitter 上提议，可以用一个类似的系统来标记网络上感兴趣的主题，并发出了第一条倡议使用「#标签」的推文。然而这一建议并没有立刻得到广泛认可，Twitter 联合创始人 Evan Williams 甚至告诉 Messina，这个概念永远都不会流行。

![hashtag](images/hashtag-3.png)

Messina 没有放弃这个概念，他甚至写了一篇 [Groups for Twitter; or A Proposal for Twitter Tag hannels](https://factoryjoe.com/2007/08/25/groups-for-twitter-or-a-proposal-for-twitter-tag-channels/) 来详细阐释其使用方式。在当年的圣地亚哥大火期间，他联系了在 Twitter 上直播事件的加州居民 Nate Ritter，并建议后者在所有相关推文中带上 `#SanDiegoFire` 的标签。Twitter 这才逐渐认识到到这是对内容进行分组的有效方式。终于，2009 年 Twitter 官方将标签系统加入搜索工具中。次年，热门话题功能出现，将时下最流行的话题展示在所有用户面前。

2014 年，牛津词典将其作为一个新的条目，添加到当年的更新中：

&gt; **hashtag** *n.*(on social media web sites and applications) a word or phrase preceded by a hash and used to identify messages relating to a specific topic; (also) the hash symbol itself, when used in this way.
在推特等社交网络媒介中，出现在 # 符号后用来标注主题的词语。
&gt; 

## 「#」的今天与明天

如今，「#」已经很少用来表示重量，也只有偶然间才在通话时被按下，但它依旧活跃在互联网弄潮儿的指尖。如果要用一个词形容现在的它，那或许是「主题」。在用 Markdown 写作时，它界定着层级的标题，在文章开头结尾打下标签，以最简洁的方式描述着文章的主题；在媒体上，一个个标签引导着时下最流行的趋势，却也在看不见的地方暗流涌动。相同的标签，连接不同的内容，把彼此独立的信息编织成网，同一个标签下，聚集着相似的人们。那么，是否一切都可以打上标签？标签网络之中，是否也隐藏着我们的未来？

![hashtag-4](images/hashtag-4.png)
Google Ngram 统计的「#」在 1800-2019 年英文文献中出现的频率

&gt; 在你眼中，「#」代表什么？
&gt; 

## 图片来源

[https://www.newyorker.com/books/page-turner/the-ancient-roots-of-punctuation](https://www.newyorker.com/books/page-turner/the-ancient-roots-of-punctuation)

[https://www.smashingmagazine.com/2016/01/why-i-moved-from-a-square-to-a-circle-calculator-interface-design/](https://www.smashingmagazine.com/2016/01/why-i-moved-from-a-square-to-a-circle-calculator-interface-design/)

[https://zh.m.wikipedia.org/zh-hans/脉冲拨号](https://zh.m.wikipedia.org/zh-hans/%E8%84%89%E5%86%B2%E6%8B%A8%E5%8F%B7)

[http://dougkerr.net/Pumpkin/AboutAuthor.htm](http://dougkerr.net/Pumpkin/AboutAuthor.htm)

## 参考资料

- *[Shady Characters : the Secret Life of Punctuation, Symbols, &amp; Other Typographical Marks](https://shadycharacters.co.uk/)*
- [Hashtag History: From Typewriters to Twitter Trends](https://www.copypress.com/blog/the-hashtag-a-history-deeper-than-twitter/)
- [Hashtag - Wikipedia](https://en.wikipedia.org/wiki/Hashtag)

[^国际象棋中，# 表示将军（checkmate）]:</content:encoded></item><item><title>克服低效率恐惧，回归健康生活</title><link>https://blog.yorks0n.com/articles/efficiency_and_life_balance/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/efficiency_and_life_balance/</guid><description>前言 这是一篇关于数字健康的文章，旨在探讨为什么会对低效率产生恐惧，这种恐惧会带来什么影响，以及如何缓和这种恐惧。...</description><pubDate>Sun, 15 May 2022 10:19:19 GMT</pubDate><content:encoded>## 前言

这是一篇关于数字健康的文章，旨在探讨为什么会对低效率产生恐惧，这种恐惧会带来什么影响，以及如何缓和这种恐惧。

本文并非要倡导停止追求高效，也不是否定优秀工具的重要性，而是希望大部分只是希望利用工具辅助完成任务的人，不要过分纠结于寻求完美的工具和高效的方法，却反倒影响了工作目标的实现。

## 好工具，低生产力

在赛博朋克主题的作品中，存在一种科学技术高度发达，但是底层人民的生活水平并没有随之提高的现象，被称为『高科技，低生活』。与之相似，我们现在的工作过程也存在一种现象：软件功能愈发齐全，技术方法百花齐放，但我们的生产力并不一定随之提高。

产生这种现象的原因之一，是我们在努力提高效率的过程中，错把追求高效本身当作了我们的目标，而不是我们实现目标的手段。

## 对低效率的恐惧使效率成为目标

类似错失恐惧症（fear of missing out, FOMO），一种担心自己错过可以改善生活的信息、经历的感觉，现在也有一种可称为**低效率恐惧（fear of low efficiency, FOLE）**的现象，又称生产力色情或是效率成瘾。我们担心浪费任何时间，沉迷于优化自己花费时间的方式，然而实际的产出却寥寥无几。这种恐惧甚至会妨碍我们完成重要的事本身，我自己就曾在写作时纠结过是否用了最好的写作软件，在做笔记时担心是否采用了最先进的笔记技巧，而不是专心在自己的内容上。

正如其他成瘾现象都基于某种奖赏机制，**低效率恐惧可能也源于高生产力带来的正向反馈**。提高生产力通常能带来直接的好处，比如产出增加或收入提高，这种反馈不断正向强化我们的行为，最终使效率在不经意间成为了我们的目标。

**低效率恐惧可能还源于消费主义试图消费一切的动机**。为了促进销售，商家贩卖焦虑，其中也有一种对低效率的焦虑。商家将购买某个工具或某门课程，与高效之间画了连线，给人植入『使用了这个软件，学了这门课程，你就能变得和效率达人一样高效』的印象。我们的消费欲望，来源于我们对想成为的人（idol）的模仿欲。我们期待通过与效率达人们使用相似的工具，模仿他们的工作流程，变得像他们一样高效且成果斐然。

另一方面，**低效率恐惧也是一种拖延的表现**。当我们不想工作时，列计划或是阅读提高工作效率的文章，实际上充当了感觉上的替代品。在我们逃避真正工作的同时，给了我们正在从事产出的错觉。

## 将效率作为目标会引起哪些问题

效率工具是辅助我们完成任务的手段，完成工作才是真正的目的，但在追求高效的过程中很容易将手段与目的混淆。如果花费过多本属于工作和生活的时间追求效率，整天忙忙碌碌，最终发现产出却寥寥无几，**平添焦虑的同时效率不升反降**。

不论技术怎样进步，软件和算法都只能按照它们设计出来的方式运行，它们不能替我们做出决定，也无法承担责任。**使用合适的工具可以帮助我们工作，追求完美的工具则是一种猎奇**。就像机械键盘，有人花数百上千组装自己的键盘，已经不再只是为了用键盘实现打字的目的，而是把折腾它的过程作为一种乐趣了。

对错过新工具、新技术的焦虑同样会导致沉迷于用即时的短期满足来缓解焦虑，比如不停地钻研各种效率文章，将工具一个个进行试用比较，甚至可能因为害怕错过提升效率，去参加一些我们并不真正需要的活动，例如报名我们用不上的学习课程。学会了屠龙之技，**失去的是本当用于工作的时间，错过的则是我们自己的生活**。

## 如何缓解低效率恐惧

### 确定自己关注的主题和领域

知识浩如烟海，如果不清楚自己真正关注什么，便无法针对性地进行积累。如同在海上航行却没有目标，如果不论遇到什么都囫囵地装进口袋，最终得到的只有乱糟糟的收藏夹，并不会促进实质性的能力提升。这里推荐少楠的《P.A.R.A.》方法，将自己所有关注的内容划分成领域、项目、资源等方面。**领域（Area）**是自己日常需要精进的方面，如果搞砸了需要承担对应的责任；**项目（Project）**有明确的起止时间和目标；**资源（Resource）**是自己持续感兴趣，但哪怕放弃，也不会影响他人的事。具体如何实践，可以进一步阅读少楠的文章[不知道积累什么知识，是因为你没有自己关注的领域](https://mp.weixin.qq.com/s?__biz=MzI0MDA3MjQ2Mg==&amp;mid=2247485941&amp;idx=1&amp;sn=28e92a5f06fb1883e95d6dc14db63d5d&amp;chksm=e9212b94de56a2824cd58114927e2011d71e89b85358bf973c3ba50449ca0eb398b4fa254d55&amp;mpshare=1&amp;scene=1&amp;srcid=0512NCDIBaqvdu4CXusvsg2l&amp;sharer_sharetime=1652338328485&amp;sharer_shareid=6d6f8a7d66e79b9e6c40cbf64b5690df#rd)。

### 反思对效率工具的使用，识别真正的限制因素

回顾自己使用了哪些效率工具，如何使用，是否朝着自己关注的领域与设定的长期计划前进。当我们做计划或是研究效率技巧的时候，我们是希望籍此辅助自己完成工作，还是在逃避推进工作。识别哪些因素真正妨碍了我们的工作，是工具或者生产力系统的缺陷吗？虽然各种算法和工具可以辅助我们进行思考和决策，但不能依赖工具而忽略了我们自身应当承担的责任。我们记下了许多笔记，但是再好的软件也不能替代我们理解和运用这些知识；相反，如果我们积极地应用这些知识，哪怕手中只有纸笔，也能非常好地掌握知识。

### 停止盲目收集，调整信息来源

留意信息的输入途径，如果使用收集箱inbox的形式，让自己的列表中放更多对自己关注的项目/领域/资源有帮助的内容。有些文章当下感到值得一读，便放进了收集箱，过一阵子再看到时觉得读它可有可无，那就应当果断将其删掉，并非一定放进收集箱的东西都非得读完。

### 重器轻用，建立适合自己的工作流

与其不断搜寻可以提高生产力的技巧，阅读如何做笔记的文章，不如确定一个适合我们的系统并稳定地使用它。Kenshin在[重器轻用就是高效](https://sspai.com/post/71576)的文章中提到，许多人纠结于选择哪个笔记工具，是因为试图在某一个工具中实现All-in-One，并以为这样就能达到简单高效。然而没有完全满足用户需求的工具存在，因此应当重器轻用，发挥各个工具的长处。Spike112也在其文章[工作流的祛魅](https://sspai.com/post/71658)中指出，在永无止境的探索过程中，新旧工具的迁移消耗了我们大量的时间和精力，应当根据场景识别需求而选择工具，而不是根据某个工具的功能去寻找它的使用场景。这篇文章中也提出，工作流比工具重要，而实践又比工作流和工具更重要，因为真正有用的工作流，是在实践的过程中不断升级优化产生的。就像只有自己整理房间，才更清楚每个工具放在哪里，也只有在整理的过程中，才能思考诸如如何优化工作环境的问题，让自己在之后的工作中更加顺手。

### 专注于我们关注的内容本身

关注内容本身，而非如何获取、储存这些内容。花更多的时间与我们收集到的内容呆在一起，思考如何使用它们，而非利用一系列自动化流程将笔记碎片积累到数据库后，囤积在那再也不看。乍看之下，笔记本中满满的笔记摘录很有成就感，但如果从此不再使用，笔记本只能成为笔记的坟场。问一问自己，我积累了这么多的笔记，然后呢？思考我们为什么要记笔记，是为了更好地理解某个概念，学习新领域的知识，通过笔记辅助我们思考和写作，亦或只是为了把玩某种先进的笔记技巧？为自己收集的内容找一个出口，比如写作，将死气沉沉的笔记调动起来，在输出的过程中厘清思路，进而更好地掌握输入的内容。

### 刻意花一些时间远离网络

网络上信息无穷无尽，作为个人不可能将其全部吸收。短时间大量的信息输入会助长失控感，引起焦虑。不妨花些时间独自思考，阅读，散步，健身，做些让自己感到放松舒适的事。生活不只有高效的工作，只有保持克制，接受自己和工具的不完美，才能重新出发，以更好的节奏投入新的工作。

&gt; 接受系统和工具的不完美，真正重要的是我们做的事本身。
&gt; 

最后，感谢您的阅读。

## 参考资料

- [放弃纠结、拥抱妥协，重器轻用就是高效](https://sspai.com/post/71576)
- [年度征文 | 我是如何艰难地克服「效率成瘾」的？](https://sspai.com/post/71518)
- [工作流的祛魅：从工具、阅读到写作](https://sspai.com/post/71658)
- [收藏≠学会，别再让你的收藏夹吃灰了！](https://sspai.com/post/72939)
- [Automations, Time spent in the environment, &quot;And then what?&quot;](https://buttondown.email/jessmartin/archive/time-spent-in-the-environment-and-then-what/)
- [From FOMO to JOMO: the joy of missing out](https://nesslabs.com/jomo)
- [Productivity addiction: when we become obsessed with productivity](https://nesslabs.com/productivity-addiction)</content:encoded></item><item><title>科研论文作图基本知识</title><link>https://blog.yorks0n.com/articles/basic-about-paper-figures/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/basic-about-paper-figures/</guid><description>参考几个期刊的投稿指南，整理了一些论文作图时会遇到的基本概念及要求。</description><pubDate>Mon, 18 Apr 2022 00:00:00 GMT</pubDate><content:encoded>本文参考了 Nature、Science、Plant Cell 等期刊的图片指南整理而成，旨在介绍一些作图前后会遇到的基本概念及要求。应注意的是，本文只能作为参考，**具体的作图要求会依据期刊发生变化，应遵循期刊提供的投稿指南**。

### 科研论文绘图的特点

相比于文字描述，**论文中的图表通常是最快传递大量复杂信息的手段**。

- 高质量的图片结果会传递出**专业性**，给读者良好的第一印象
- 许多人在阅读时也会从图片开始，因此应保证图片**清晰准确地传递信息**
- 图片也是吸引读者进一步阅读文章内容的基础，因此条件允许时**适当兼顾艺术性**

### 本文包含什么

本文包含许多在作图前后，尤其是完成单张结果图后，进行进一步图片组合时所需了解的基本概念与注意事项。

### 本文不包含什么

本文不是指导投稿某个期刊时的作图规范，一切具体标准与要求仍以各期刊自己的投稿指南为准。

---

## 创建画布

### 图片格式

图片格式可以分成[位图与矢量图](https://business.oregonstate.edu/student-experience/resources/DAMlab/vector-and-bitmap-image-guide)两种：

位图（Bitmap），又称栅格图（Raster graphics），指使用像素点组成的阵列来表示的图像，通过定义每个像素点的位置及其颜色来生成图片，比如JPG、TIFF等。
矢量图（Vector）是用点、直线或多边形等基于数学方程的几何元素表示的图像，如PDF、EPS等。

![](./images/1680600531904.jpeg)

由于矢量图记录的是形状的计算方式，其经过放大也不会变得模糊，因此是作图时首选的图片格式。

期刊主要接受的位图格式为TIFF，接受PDF等矢量图；其中PDF中可以同时储存位图与矢量图，因而成为更加通用的格式；尽量避免使用PowerPoint储存图像。

### 画布尺寸

由于出版时版面宽度限制，期刊通常会对图片的尺寸有所要求，为了更好地排列每张Figure中的图片大小及位置，同时匹配字号和图片尺寸，最好在新建画布时就设定好尺寸。

每个期刊对于图片尺寸的要求各不相同，一般会区分单栏或双栏的布局方式。
![](./images/1680600541142.png)
部分期刊的图片尺寸要求如下：
| 期刊   | 单栏（cm）  |   双栏（cm）   |
|-------|-------|-------|
| Nature | 9 | 18 |
| Plant Cell | 8.25 | 16.5 |
| Science | 5.5 | 12 |

图片的高度一般没有明确要求，PC建议最大图片高度20 cm，Nature建议最大图片高度17 cm，以尽量保证图片和图例在同一页范围内。

### 颜色模式

颜色模式是数字图像中表示颜色的算法，期刊中常见要求有[RGB模式与CMYK模式](https://99designs.ca/blog/tips/correct-file-formats-rgb-and-cmyk/)。
![](./images/1680600551809.png)
- RGB模式：利用红（R）、绿（G）、蓝（B）三种颜色的加法混合，产生各种各样的颜色。
- CMYK模式：将三原色叠加生成的四种颜色，即青色（C）、洋红色（M）、黄色（Y）与黑色（K），利用减法混合，形成CMYK颜色。

不同期刊对于投稿图片中的颜色模式的要求也各有不同，比如Science要求CMYK，Plant Cell则要求RGB。
不用担心，这两种颜色模式可以相互转换，但每次都会损失一点数据，所以最好先用RGB处理好图像，一旦有需要，再将其转换为CMYK模式。

## 字体

衬线，是指笔画末端的装饰线，是区分不同英文字体最显著的特征。有衬线的字体叫做**衬线字体**（Serif），而没有的则是**非衬线**（Sans-Serif）。（「Serif」意为「衬线」，「Sans」在法文中意为「没有」）
![](./images/1680600561146.jpeg)
常见期刊一般要求使用非衬线字体，如Arial或Helvetica，且不同期刊对于图片中的字体大小也有要求：
| 期刊   | 最小字号（pt）  |     最大字号（pt）   |
|-------|-------|-------|
| Nature | 5 | 7 |
| Science | 5 | 7 |
| Plant Cell | 6 | 8 |

要注意的是组合多张图片时，通常图片会被缩放，这时实际显示出的字号会发生变化，应以最终缩放后的字号为准；多张图片的标注（即标注 A, B, C, D 时），应采用大写加粗，具体字号另各有要求。

## 颜色

图片中的颜色应当差异明显且视觉效果良好。期刊都会要求考虑到色觉障碍人士，因而要求避免使用诸如红色与绿色这样的颜色组合作为对比（改为使用洋红色与绿色），尤其是在荧光显微照片中。
![](./images/1680600567695.png)
## 分辨率

在涉及到位图的时候，就要考虑分辨率，通常以ppi作为单位（pixels per inch）。分辨率过低会导致图片在放大时边缘模糊。
在纯线条与文字组成的图片中（如化学式），分辨率尤其重要。一个好的方法是将图片放大至400%（至少200%），观察其边缘是否依然锐利清晰。
![](./images/1680600572700.png)
纯矢量图不需要考虑分辨率；如果导出位图则照片尽量达到300 ppi。

## 图片布局

一大原则就是避免空间浪费，但应保证不同的照片边缘有明显分界线；同时图片边缘尽量对齐。

![](./images/1680600577500.png)

## 额外注意事项

务必整理好所有作图过程中使用过的原始图片，尽量保证其分辨率，最好是原始格式的原始文件，因为部分杂志会要求提供原始图片。

相比于文中提到的要求，不同期刊对于图片都会有各自的额外要求，一切应以期刊提供的投稿指南为准。比如[Nature](https://www.nature.com/nature/for-authors/initial-submission)要求所有图片中的文字可编辑；[Science](https://www.science.org/content/page/instructions-preparing-initial-manuscript)要求避免使用灰度图等。

---

推荐进一步阅读[Plant Cell](https://academic.oup.com/plcell/pages/general-instructions)提供的*Detailed Figure Guidelines*，里面不但有杂志自身的投稿要求，还对许多基本概念有详细介绍，同时对一些可能犯的错误提供了修改意见。

### References

- 位图与矢量图: _https://business.oregonstate.edu/student-experience/resources/DAMlab/vector-and-bitmap-image-guide_  
- RGB模式与CMYK模式: _https://99designs.ca/blog/tips/correct-file-formats-rgb-and-cmyk/_  
- Nature: _https://www.nature.com/nature/for-authors/initial-submission_  
- Science: _https://www.science.org/content/page/instructions-preparing-initial-manuscript_  
- Plant Cell: _https://academic.oup.com/plcell/pages/general-instructions_  
- Figures and tables - springer: _https://www.springer.com/gp/authors-editors/authorandreviewertutorials/writing-a-journal-manuscript/figures-and-tables/10285530_</content:encoded></item><item><title>为什么我们不喜欢学习</title><link>https://blog.yorks0n.com/articles/why_dont_we_love_study/</link><guid isPermaLink="true">https://blog.yorks0n.com/articles/why_dont_we_love_study/</guid><description>读书笔记 ——《为什么学生不喜欢上学?》</description><pubDate>Mon, 11 Apr 2022 10:19:19 GMT</pubDate><content:encoded>最近读完了 Daniel T. Willingham 所写的《为什么学生不喜欢上学?》。这是介绍教育原理的书，旨在给教师提供教学意见。其中的许多内容直观地解释了「学习」这个过程中所运用到的「认知原理」。我们自然没有提升教学水平的任务，但它同样能为我们学习或向他人有效传递信息提供参考。

---

## 认知原理

全书共提到了9个认知原理，分别是：

1. 人类具有好奇心，但大脑会尽力避免思考
2. 事实性的知识先于技能
3. 记忆是思考的残留物
4. 我们依靠已知内容理解新的内容
5. 练习才能熟练掌握
6. 学习早期的认知力与晚期的截然不同
7. 学生在学习方面相似多过差异
8. 学生智力上的差异可以通过更持久的努力改变
9. 教学水平也需要通过练习提高

此处并不期待制作出这本书的知识总结，而是摘取部分我觉得较为实用的要点进行回顾。

## 我们如何思考

下图是一张简化的大脑运作模型，我们从环境（外部信息源）获取信息进入工作记忆（工作区），利用工作记忆进行思考；我们还会从长期记忆（内部信息源）提取与工作相关的信息到工作区，协助处理信息。**工作记忆的空间有限**，且没有什么已知的好办法扩展它。一旦工作记忆变得过于拥挤，思考就会异常艰难。因此，思考的成功取决于四个方面：

- 环境中的信息
- 长期记忆中的信息
- 长期记忆中的步骤
- 工作记忆的空间大小

![4fa357a4-45aa-44c8-84df-f8e8a6336e5e.png](./images/4fa357a4-45aa-44c8-84df-f8e8a6336e5e.png)

简化的大脑运作模式图

&gt; 工作记忆的空间大小不是由内容的文字多少决定，而是由有意义的片段决定
&gt; 

&gt; 长期记忆中的背景知识可以帮助把大块的内容合并成有意义的信息单元
&gt; 

&gt; 背景知识使合并成为可能，它使得片段间的联系变得容易，提高了工作记忆的空间利用效率，最终使理解变得容易。
&gt; 

## 只有好奇并不使人思考

这并不是说好奇不重要，好奇心依然是我们最好的老师。大脑天生懒惰，当我们能侥幸通过某种方式完成任务时，便不会再去积极思考，反而会依赖记忆，在下次任务出现时依照记忆行动。思考的过程耗费相当的精力，只有**当我们明白解决某一问题后会带来愉悦感时，我们才会喜欢思考**。太过简单或太过困难的问题都不会让人开心，因此只有恰当地依照对方的背景知识，提出合适的问题，才能促成对方积极思考。

## 背景知识帮助我们思考

思考是以新的方式组合信息，这既包含随时可以从外部查询的信息，又包含长期记忆中的信息。外界直接获取的信息储存在短期的工作记忆中。我们**熟悉的信息不会占用太多工作记忆**，因为大脑可以根据长期记忆将信息组合成新的单元进行暂时存放；**不熟悉的新内容则会占据大量工作记忆**，**导致难以思考**。但如果能在查找时，将新获得的信息与之前的信息建立关联，可以帮助记忆，减少在工作记忆的空间占用。

**背景信息还帮助我们进行交流**。在与他人沟通时，为了避免过度冗长，我们通常会适当省略一些信息。事无巨细将每个细节讲出来会导致啰嗦，也会令听者失去耐心；相反，如果过度省略信息，在双方知识不对等的情况下，会导致无法互相理解，反而加剧交流障碍。

## 记忆是思考的残留

如果我们仔细地思考过一件事情，就更有可能之后再次想起它，思考让大脑明白某件事是应该被存储的。记忆不是我们想要记住或尝试记住的事，**记忆是我们所思考的事**。

## 我们在已知的环境中理解新事物

学习知识的过程在于用相关联的事实来解释一个中心概念，而不是建立事实性的知识点清单。思考的过程就是在为知识点建立**联系**，这与记住知识点本身同样重要；理解一个新的概念就是让恰当的已有概念进入工作记忆，并加以重新组合，因此**理解其实就是记忆**。

![53bd5968-aa78-457d-961b-e821427134a7.png](./images/53bd5968-aa78-457d-961b-e821427134a7.png)

可以通过类比等方法帮助理解抽象的概念，但类比也需要恰当地选择例子，如果受众对于例子过于不了解，那么此类比也难以帮助其理解问题。

一个问题通常具有表层结构和深层结构。表层的结构是直观的，但对于解决问题可能帮助不大；正确辨别问题的深层结构有助于解决问题，然而一个问题可能有多种深层结构，因而难以正确处理它。

将抽象概念利用类比转化成一个具象事件的过程，实际上是在把问题的**深层结构**与一个好理解的**表层结构**建立联系。

&gt; 何为「表层结构」与「深层结构」：以小学奥数题为例，一个水池一边排水一边进水，问多久水池能装满。如果只看到表层结构中的水池、水龙头，是不会将它与先前例题中牛吃草的吃草速度、牧草生长速度联系起来的；而这个问题的深层结构是「速度差」，即进水与排水的速度差，或是吃草与长草的速度差，只有把握了这一深层结构，才能解决这一类而非这一个具体的问题；因为表层结构是多变的，而深层结构间可能有共通之处。
&gt; 

因此在不能把问题正确地由表层结构连结到恰当的深层结构上时，便无法利用已有知识解决问题。

通过接触更多例子，或是比较不同的例子，可以帮助我们建立对深层结构（抽象概念）的理解，此即**练习**的作用。

## 练习，还是练习

练习使得在进行底层的基础过程时，得以不假思索，为更高级更深入的过程提供思考所需的空间；不恰当的练习设计会磨灭积极性，所以需要恰当选择练习的内容与形式。

&gt; 何为「基础过程」：所谓基础也就是人在某一个领域一遍又一遍重复的事情，通过练习使其达到自动化，它们为日后更高级的工作奠定了基础。例如乒乓球员练习发球，通过练习使其几乎不占用额外的精力，让注意力得以更多地转移到比赛的其他过程。
&gt; 

由于工作空间区域有限且无法通过某种方式扩展，因此就得：

- 采取某种方式压缩其中的内容
- 提高工作记忆中操纵信息的效率

实际上这两者都是从长期记忆中提取一部分到工作区中，因此只占用工作区内的一小部分。

练习可以使记忆更长久，而**分散练习**有助于记忆维持更长的时间，同时让学生有更多的机会思考如何将学到的东西加以应用，即练习**如何将问题与恰当的知识点建立联系**的过程。要达到自动化需要很多练习，最好的办法是既分散联系的时间，又分散练习的环境，尽量多设计有创意的方法来练习最关键的技巧，使得能够在更高阶的环境中学到基本技能。

## 一些额外的建议

与人搭档合作，一同学习是个好办法。

&gt; 但除非被问及，否则不要建议别人该做什么。你不会希望做一个什么都懂的圣人。如果你的搭档想咨询你的建议，他会来问你的，这时候你当然可以畅所欲言了。但是在他问你之前，当好一个谨慎的、支持的旁观者，不要以为自己是万能的协调者，不管你多有信心、解决方法多好都不要插手。
&gt; 

---

## 参考资料

[为什么学生不喜欢上学?](https://book.douban.com/subject/4864832/)</content:encoded></item></channel></rss>