mrc stack文件 转成 独立的mrc文件
MRC文件 和 MRC Stack文件 简介
MRC文件 是冷冻电镜电子显微图像中常用于数据处理的一种图像文件(二进制文件)可以存储二维和三维的图像。需要特殊的解码软件可以显示,如chimera,EMAN等软件。
MRC文件一般用.mrc
和.mrcs
后缀表示,其中.mrcs
代表MRC Stack文件。
MRC stack文件 和MRC文件的唯一区别就是文件名的后缀不一样,实际上就是MRC文件。
后缀名加S的原因是为了将一系列的二维的MRC文件 集合存成一个MRC文件时,区别一般的MRC文件。
如此我们就知道mrcs文件里存的是一系列二维图像的集合而不是一个三维图像。
MRC文件/未经过motion correction的文件,在文献中也常用movie来表述,因为逻辑上很类似,movie本身也是一系列二维图片的集合,frames 多帧图像。
MRC的数据块逻辑:其实就是三维数组(x,y,z),对应三维图像;二维数组(x,y),对应二维图像。而MRCs文件就是把多个二维图像(二维数组X,Y)集合写成三维图像(三维数组X,Y,Z 其中Z就对应二维图像的序号)。所以文件头和数据块都可以是一样的。
.mrcs文件转多个独立的.mrc文件
由于没有找的已有的程序可以处理我的需求,所以自己基于MRC文件的MRC/CCP4 2014 file format文档,解析二进制文件进行重写。
代码块
# -*- coding: utf-8 -*-
"""
Created on Tue Dec 6 21:06:55 2022
@author: anis
"""
import struct
import os
dir = cur_path = os.getcwd()
#=====================获取mrc文件的主头数据 头部固定1024字节或256个4字节===============
def getHeader(mrcFile):
with open(mrcFile,"rb", ) as mrc:
word1=mrc.read(96)
value1=struct.unpack("24i",word1)
["NX","NY","NZ","MODE","NXSTART","NYSTART","NZSTART","MX","MY","MZ","CELLA1","CELLA2","CELLA3","CELLB1","CELLB2","CELLB3", \
"MAPC","MAPR","MAPS","DMIN","DMAX","DMEAN","ISPG","NSYMBT"]
mrc.seek(96)
word2=mrc.read(100)
value2=struct.unpack("25i",word2)
["EXTRA"]
mrc.seek(196)
word3=mrc.read(28)
value3=struct.unpack("7i",word3)
["ORIGIN1","ORIGIN2","ORIGIN3","MAP","MACHST","RMS","NLABL"]
mrc.seek(224)
word4=mrc.read(800)
value4=struct.unpack("200i",word4)
return value1+value2+value3+value4
#===================================获取data块数据================================
def getData(mrcFile,fmt,NZ):
with open(mrcFile,"rb", ) as mrc:
mrc.seek(1024)
data=mrc.read(4*fmt*NZ)
value=struct.unpack("f"*fmt*NZ, data)
return value
#============================将一个mrcs文件data数据写入多个mrc文件================================
def mrcs2mrc(originFile):
header=getHeader(originFile)
NX=header[0]
NY=header[1]
NZ=header[2]
li=list(header)
li[2]=1
header=tuple(li)
fmt=NX*NY
data=getData(originFile,fmt,NZ)
for Z in range(NZ):
data_block=data[fmt*(Z):fmt*(Z+1)]
with open("MRCdir/"+str(Z+1).rjust(2,'0')+"_"+originFile.split(".")[0]+".mrc","wb", ) as mrc:
header_packed=struct.pack("i"*256,*header)
mrc.write(header_packed)
data_packed=struct.pack("f"*fmt,*data_block)
mrc.write(data_packed)
print(str(Z+1).rjust(2,'0')+"_"+originFile.split(".")[0]+".mrc 已写入")
print("done!")
return 0
if not os.path.exists("MRCdir"):
os.makedirs("MRCdir")
for root, dirs, files in os.walk(dir):
for file in files:
(fileName, extension) = os.path.splitext(file)
if (extension == '.mrcs'):
mrcs2mrc(file)
MRC文件格式:
struct函数 unpack和pack(二进制数据转元组,元组转二进制数据)
用于处理二进制数据的struct
函数, 数据格式的定义
- 示例
- 打印unpack的数据 控制台结果:
(320, 320, 1, 2, -512, -512, -512, 1023, 1023, 1023, 1152248054)
- 打印pack的数据 控制台结果:
b'@\x01\x00\x00@\x01\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x00\xfe\xff\xff\x00\xfe\xff\xff\x00\xfe\xff\xff\xff\x03\x00\x00\xff\x03\x00\x00\xff\x03\x00\x00\xf6\xe8\xadD\xf6\xe8\xadD\xf6\xe8\xadD\x00\x00\xb4
mrc文件中的数据块的数据类型是float32
,4个字节,对应下表中的“f
”
note
由于没有对文件头进行过多操作,所以getHeader中贪便宜,unpack的时候没有考虑数据类型,所有的都按照 “i
” 类型unpack,后又按“i
” 又原封不动的pack回去了。