chemfig

据别人介绍,在绘制平面分子式,乃至化学反应式、机理图时,大家使用的基本都是ChemDraw。当然ChemDraw是一款强大的软件,无论是平面的还是立体的分子结构式都能毫不费力地绘制出来。当然这份强大是要钱的,对于平面的分子式或反应式,不要钱而且还可行的方案大致也就LaTeX语言中的Chemfig宏包。

Chemfig是法国学者开发的宏包,εTeX,pdfLaTeX等TeX编译器都能正常使用,并且相对来说开发是比较活跃的。

texlive

TeX Live 是 TUG (TeX User Group) 发布并维护的的 TeX 系统,可以称得上是TeX的官方系统。对于任何阶段的TeX用户,都可以使用TeX Live, 以保持在跨操作系统、跨用户的TeX文件一致性。

texlive Docker镜像及服务化改造

texlive的安装B站有很多教程,目标是需要提供绘制chemfig化学方程式转换的服务,而texlive软件本身并不提供相关的api服务,需要对其进行服务化改造,因为考虑容器化部署,需要将texlive封装成docker镜像

话不多说,我们选择的基础镜像是 texlive:2020 ,使用Python对外提供服务,关于texlive相关的介绍可以参考博客:chemfig化学式转换为pdf

拉取镜像并运行

docker pull texlive:2020

docker run --name texlive -d texlive:2020

docker ps -a | grep  live
dda1561ae866 texlive:2020 "tail -f /dev/null" 8 seconds ago Up 2 texlive docker exec -it dda1561ae866 bash

安装python,制作texlive-python镜像

# texlive是基于Alpine Linux,目前主流
cat /etc/issue
Welcome to Alpine Linux 3.12 # 修改apk镜像源
vi etc/apk/repositories

替换文件内容为阿里源:

http://mirrors.aliyun.com/alpine/v3.8/main/

http://mirrors.aliyun.com/alpine/v3.8/community/

# 更新软件库
apk update
fetch http://mirrors.aliyun.com/alpine/v3.8/main/x86_64/APKINDEX.tar.gz
fetch http://mirrors.aliyun.com/alpine/v3.8/community/x86_64/APKINDEX.tar.gz
v3.8.5-67-gf94de196ca [http://mirrors.aliyun.com/alpine/v3.8/main/]
v3.8.5-66-gccbd6a8ae7 [http://mirrors.aliyun.com/alpine/v3.8/community/]
OK: 9578 distinct packages available # 安装python3
apk add --no-cache python3 python3-dev py-pip # 验证安装
python3 -V
Python 3.6.9
bash-4.4# pip3 -V
pip 18.1 from /usr/lib/python3.6/site-packages/pip (python 3.6)

保存镜像

docker commit dda1561ae866 textlive-python

至此,我们的拥有python环境texlive镜像就已经制作好了

服务化改造

python脚本

from flask import Flask, abort, request, jsonify
import os
import subprocess
import uuid
import base64 app = Flask(__name__) @app.route('/texlive/translate/', methods=['POST'])
def translate():
if not request.json or 'chemfig' not in request.json:
abort(400)
chem_fig = request.json['chemfig']
# 由于不好测算化学方程式图形的大小,这里支持配置纸张大小,我们这里默认a5paper
if 'paper' in request.json:
paper = request.json['paper']
else:
paper = 'a5paper'
tempFile = open("template.tex")
lines = tempFile.readlines()
lines[2] = lines[2].replace("a5paper", paper)
lines[15] = chem_fig + "\n"
uuidStr = str(uuid.uuid1())
new_file_name = uuidStr + '.tex'
newFile = open(new_file_name, "a+")
for line in lines:
newFile.write(line)
newFile.flush()
newFile.close()
try:
# 这里使用subprocess比较稳定,os.system经常会出现莫名问题,至少这个pdflatex命令用os.system会报错
subprocess.run(["pdflatex", "-interaction=nonstopmode", new_file_name])
pdf_string = open(uuidStr + '.pdf', "rb").read()
encoded = base64.b64encode(pdf_string)
pdf_link = "data:application/pdf;base64,{}".format(encoded)
pdf_link = pdf_link.replace("b'", "").replace("'", "")
except:
remove_file(uuidStr)
else:
remove_file(uuidStr) return jsonify({"image": pdf_link}) def remove_file(uuid_str):
os.system('rm ' + uuid_str + '.tex')
os.system('rm ' + uuid_str + '.log')
os.system('rm ' + uuid_str + '.pdf')
os.system('rm ' + uuid_str + '.aux') if __name__ == '__main__':
app.run(host="0.0.0.0", port=8080, debug=False)

Latex模板

template.tex

\documentclass{minimal}
\usepackage{xcolor, mol2chemfig}
\usepackage[a5paper, margin=10px, total={6in, 8in}]{geometry} \usepackage[helvet]{sfmath}
\setcrambond{2.5pt}{0.4pt}{1.0pt}
\setbondoffset{1pt}
\setdoublesep{2pt}
\setatomsep{%(atomsep)spt}
\renewcommand{\printatom}[1]{\fontsize{8pt}{10pt}\selectfont{\ensuremath{\mathsf{#1}}}} \setlength{\parindent}{0pt}
\setlength{\fboxsep}{0pt}
\begin{document} \chemfig{H_3C-[:30]N**6(-(=O)-(**5(-N(-CH_3)--N-))--N(-CH_3)-(=O)-)} \end{document}

mol2chemfig.sty

requirements.txt

Flask

startup.sh

python3 ./main.py

DockerFile

FROM hub.iflytek.com/ainote/texlive-python:2020
COPY main.py /home
COPY mol2chemfig.sty /home
COPY template.tex /home
COPY requirements.txt /home
COPY startup.sh /home
WORKDIR /home
EXPOSE 8080
RUN pip3 install -r requirements.txt && ls
CMD ["bash", "startup.sh"]

服务镜像制作

构建 texlive-python-api

# dockerfile构建
docker build -t texlive-python-api .
# 打tag
docker tag texlive-python-api xxx.xxx.com/xxx/texlive-python-api:2020
# 推送远程镜像仓库
docker push xxx.xxx.com/xxx/texlive-python-api:2020

跑一个试试

docker run -p 8080:8080 -d --name texlive-python-api texlive-python-api

请求body

{"paper":"a6paper",
"chemfig":"\\chemfig{CH_3-[:108,,1]N-[:54](-[:180,0.85,,,draw=none]\\mcfcringle{1.03})%\n-[:126]N-[:198]-[:270](-[:342]\\phantom{N})-[:210](=[:270]O)-[:150]N(%\n-[:210,,,2]H_3C)-[:90](=[:150]O)-[:30]N(-[:330])-[:90,,,1]CH_3}\n\n\\bigskip\n\n\\chemfig{CH_3-[:108,,1]N-[:54](-[:180,0.85,,,draw=none]\\mcfcringle{1.03})%\n-[:126]N-[:198]-[:270](-[:342]\\phantom{N})-[:210](=[:270]O)-[:150]N(%\n-[:210,,,2]H_3C)-[:90](=[:150]O)-[:30]N(-[:330])-[:90,,,1]CH_3}"}

postman



拷贝出来放在浏览器就可以直接访问了,这个是a6纸张的渲染效果,可以根据图的大小动态的传入纸张规格



再来个大的

{"paper":"a3paper",
"chemfig":"\\chemfig{CH_3-[:108,,1]N-[:54](-[:180,0.85,,,draw=none]\\mcfcringle{1.03})%\n-[:126]N-[:198]-[:270](-[:342]\\phantom{N})-[:210](=[:270]O)-[:150]N(%\n-[:210,,,2]H_3C)-[:90](=[:150]O)-[:30]N(-[:330])-[:90,,,1]CH_3}\n\n\\bigskip\n\n\\chemfig{\nO%5\n=[:270]%3\n(\n-[:210]%2\n(\n<[:150]%4\n-[:90.4,2.094]%115\n-[:18]%109\n-[:330]%110\n-[:30,,,,dlh]%111\n-[:90]%112\n-[:150,,,,dlh]%107\n-[:210]%108\n(\n-[:162]\\mcfabove{N}{H}%113\n-[:234]%114\n-[:306,,,,dbl={73}{73}]%->115\n)\n-[:270,,,,dlh]%->109\n)\n-[:270,,,2]HN%1\n-[:330,,2]%93\n(\n-[:270]%95\n-[:210]%96\n-[:270]%97\n-[:330]%98\n-[:30]%99\n-[:330]%100\n-[:270]%101\n-[:210]%102\n-[:270]%103\n)\n=[:30]O%94\n)\n-[:330]\\mcfbelow{N}{H}%6\n-[:30]%7\n(\n<:[:90]%9\n-[:30]%10\n(\n-[:330,,,1]NH_2%12\n)\n=[:90]O%11\n)\n-[:330]%8\n(\n=[:270]O%15\n)\n-[:30]\\mcfabove{N}{H}%13\n-[:330]%14\n(\n<:[:270]%16\n-[:330]%19\n(\n=[:270]O%21\n)\n-[:30,,,1]OH%20\n)\n-[:30]%17\n(\n=[:90]O%22\n)\n-[:330]\\mcfbelow{N}{H}%18\n-[:30]%23\n<:[:90]%24\n(\n=[:150]O%26\n)\n-[:30,,,1]NH%25\n-[:90,,1]%27\n-[:30]%28\n(\n=[:90]O%29\n)\n-[:330]\\mcfbelow{N}{H}%30\n-[:30]%31\n(\n-[:90]%33\n-[:30]%34\n-[:90]%35\n-[:30,,,1]NH_2%36\n)\n-[:330]%32\n(\n=[:270]O%37\n)\n-[:30]\\mcfabove{N}{H}%38\n-[:330]%39\n(\n<:[:270]%43\n-[:330]%44\n(\n-[:30,,,1]OH%46\n)\n=[:270]O%45\n)\n-[:30]%40\n(\n=[:90]O%42\n)\n-[:330]\\mcfbelow{N}{H}%41\n-[:30]%47\n(\n<:[:90]%49\n)\n-[:330]%48\n(\n=[:30]O%51\n)\n-[:270,,,2]HN%50\n-[:330,,2]%52\n(\n<[:30]%54\n-[:330]%55\n(\n-[:270,,,1]OH%57\n)\n=[:30]O%56\n)\n-[:270]%53\n(\n=[:330]O%58\n)\n-[:210,,,2]HN%59\n-[:270,,2]%60\n-[:210]%61\n(\n=[:270]O%62\n)\n-[:150]\\mcfabove{N}{H}%63\n-[:210]%64\n(\n<:[:270]%104\n-[:330,,,1]OH%105\n)\n-[:180,1.732]%91\n(\n-[:150,,,,dlhs]O%92\n)\n-[:270,,,1]NH%90\n-[:210,,1]%82\n(\n<[:270]%84\n(\n-[:330]%86\n-[:270]%87\n(\n-[:210,,,2]HO%89\n)\n=[:330]O%88\n)\n-[:210]%85\n)\n-[:150]%81\n(\n=[:90]O%83\n)\n-[:210]\\mcfbelow{N}{H}%71\n-[:150]%69\n(\n-[:90]%68\n(\n=[:30]O%70\n)\n-[:150]O%67\n-[:90]%65\n(\n<[:30]%66\n)\n-[:150]%->23\n)\n<[:210]%72\n-[:270]%73\n(\n=[:330]O%75\n)\n-[:210]%74\n-[:270,,,,drh]%80\n(\n-[:330,,,1]NH_2%106\n)\n-[:210]%79\n-[:150,,,,drh]%78\n-[:90]%77\n-[:30,,,,drh]%76\n(\n-[:330]%->74\n)\n}\n"}

PS:LaTeX是一种基于ΤΕΧ的排版系统,不光是化学方程式,其他latex语法都可以通过本镜像渲染,template.tex是模板文件,对latex排版有要求的可以自行定制

参考链接

chemfig化学式转换为pdf:https://www.cnblogs.com/xiaoqi/p/chemfig.html

mol2chemfig:http://chimpsky.uwaterloo.ca/mol2chemfig/index

Chemfig中文手册:https://chemfig.man.huzheyang.cn/index.html

用latex绘制有机化学分子式:http://static.latexstudio.net/wp-content/uploads/2016/09/chemfig.pdf

基于texlive定制chemfig化学式转换Python服务镜像的更多相关文章

  1. docker容器化python服务部署(supervisor-gunicorn-flask)

    docker容器化python服务部署(supervisor-gunicorn-flask) 本文系作者原创,转载请注明出处: https://www.cnblogs.com/further-furt ...

  2. SharePoint 2013 Word 转换PDF服务介绍及示例

    前言:在SharePoint使用过程中,经常会发现将文档进行格式转换的需求,之前,看到SharePoint 2013有将PPT转换PDF文档的服务,后来,才发现SharePoint 2010开始,就有 ...

  3. 翻译:打造基于Sublime Text 3的全能python开发环境

    原文地址:https://realpython.com/blog/python/setting-up-sublime-text-3-for-full-stack-python-development/ ...

  4. SharePoint Word 转换PDF服务介绍及示例

    前言:在SharePoint使用过程中,经常会发现将文档进行格式转换的需求,之前,看到SharePoint 2013有将PPT转换PDF文档的服务,后来,才发现SharePoint 2010开始,就有 ...

  5. twistd 启动Python服务

    twistd 启动Python服务 shell 脚本如下: #! /usr/bin/env sh MAIN_MODULE=pdf_task.py ROOT="/var/www/pdf/&qu ...

  6. 基于scrapy爬虫的天气数据采集(python)

    基于scrapy爬虫的天气数据采集(python) 一.实验介绍 1.1. 知识点 本节实验中将学习和实践以下知识点: Python基本语法 Scrapy框架 爬虫的概念 二.实验效果 三.项目实战 ...

  7. 基于Spring Cloud、JWT 的微服务权限系统设计

    基于Spring Cloud.JWT 的微服务权限系统设计 https://gitee.com/log4j/pig https://github.com/kioyong/spring-cloud-de ...

  8. 在C#/.NET应用程序开发中创建一个基于Topshelf的应用程序守护进程(服务)

    本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区. 文章目录 C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf ...

  9. Cola Cloud 基于 Spring Boot, Spring Cloud 构建微服务架构企业级开发平台

    Cola Cloud 基于 Spring Boot, Spring Cloud 构建微服务架构企业级开发平台: https://gitee.com/leecho/cola-cloud

随机推荐

  1. Python装饰器(2)

    上一篇介绍了装饰器的常规使用方法,即函数形式的装饰器.这篇文章中,进一步介绍类class跟装饰器的相关知识. [用装饰器来装饰类函数] 这是今天介绍的第一种使用场景,比较常见.因为目前好多的编程语言都 ...

  2. ES6学习笔记(1)- 块级作用域

    1. var声明变量和变量提升(Hoisting)机制的问题 在JS中通过var关键字声明的变量,无论在函数作用域中亦或是全局作用域中,都会被当成当前作用域顶部的变量,和就是所谓的提升机制(Hoist ...

  3. 使用dcmtk库读取.dcm文件并获取信息+使用OpenCV显示图像

    借助VS2013和OpenCV的绘图功能,在工程DICOMReader.sln中实现了对单张.dcm图像的读取与显示,以下是详细步骤. 前期准备工作 编译器:VS2013 库:dcmtk-3.6.0( ...

  4. 生成元(JAVA语言)

    package 第三章; import java.util.Scanner; public class 生成元 { public static void main(String[] args) { / ...

  5. 【Spring Cloud & Alibaba全栈开源项目实战】:SpringBoot整合ELK实现分布式登录日志收集和统计

    一. 前言 其实早前就想计划出这篇文章,但是最近主要精力在完善微服务.系统权限设计.微信小程序和管理前端的功能,不过好在有群里小伙伴的一起帮忙反馈问题,基础版的功能已经差不多,也在此谢过,希望今后大家 ...

  6. Android Studio 之 编写精美的聊天界面

    •准备工作 首先制作一张 .9 格式的聊天气泡,参见我的这篇博客: 需要注意的是,制作完成后,应该将原始文件删除,否则AS会分不清楚而报错. 新建一个 Empty Activity,Java 和 XM ...

  7. Linux性能优化:内存使用情况分析

    Blog:博客园 个人 目录 什么是内存 Linux内存回收机制 查看Linux内存情况 查看/proc/meminfo 使用free命令查看 Buffer和Cache Swap 内存泄漏和内存溢出 ...

  8. c++一些概念

    面向对象语言三大特征: 封装,多态,继承 封装: 1.将函数定义到结构体内部,就是封装. 2.编译器会自动传递结构体的指针给函数. 类: 带有函数的结构体,称为类. 成员函数: 结构体里面的函数,称为 ...

  9. CVPR2021| 继SE,CBAM后的一种新的注意力机制Coordinate Attention

    前言: 最近几年,注意力机制用来提升模型性能有比较好的表现,大家都用得很舒服.本文将介绍一种新提出的坐标注意力机制,这种机制解决了SE,CBAM上存在的一些问题,产生了更好的效果,而使用与SE,CBA ...

  10. 高精度减法(c++)

    高精度减法 每当要进行精度较高的运算时,就要用到高精度. 下图是各个类型的数值范围: 如果想不起各个类型占多少字节,可以采用下面的方法: printf("%d %d",sizeof ...