热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

FIT文件格式解析及MATLAB读取程序

FIT文件格式解析(http:blog.csdn.netshizhixin,Email:zxshi@nlpr.ia.ac.cn,2011年12月)摘要:本文档主要介绍了用Ult

FIT文件格式解析

(http://blog.csdn.net/shizhixin,Email: zxshi@nlpr.ia.ac.cn,2011年12月) 

摘要:本文档主要介绍了用UltraEdit查看FIT文件及简要的说明了FIT文件的数据存储方式,并附上了FIT文件数据读取及保存为TXT的MATLAB程序。此外,通过读取lamda的相关信息,文中还显示了5条FIT文件中读取出来的光谱。
 

用UltraEdit打开一个光谱FIT文件,其十六进制表示如下:



一个 FIT 文件包含一系列逻辑单元,而每个单元的开头都是用一组标题记录描述随后的数据记录。一个 FIT 文件的逻辑记录长度总是 2880 字节(bytes),每字节8 位(bits)。标题和数据组都在一个新的逻辑记录里起始。FIT标题用 ASCII 码编辑成每一个开始用一个 8 字符的关键词(keyword) 定义信息的类型(80字符)。一个 FIT 标题卡片映象的基本语法格式是:

Keyword=Value/Comment

(关键词=参数值/注释说明)

关键词是一个左边对齐的 8 字符 ASCII 码字符串, 放在 1-8 列里, 字母必须大写。“=”号出现在第 9 列, 而第 10 列是空格。逻辑值(F 或 T)和数值在数值区中紧靠右排列,字符串用符号: ' ' 括出,字母大写。符号“/”用来表示数值区结束。注释说明紧接符号“/”,用大小写ASCII码字符书写。因此,为了在普通计算机上简化参数译码,要求对大多数基本参数使用一个固定格式,而且对所有其他参数也建议使用这个固定格式,建议和部分要求的固定格式如下:

1) Logical Variable (逻辑变量): T 或 F, 在 30 列里。

2) Integer Variable (整数变量): 右对齐在 11-30 列里,若有虚部右对齐在31-5 0 列里。

3) Real Variable (实变量): 要求 10 进制小数点,右对齐(如果用指数记数法)在 11-30 列里, 若有虚部,右对齐(如果用指数记数法)在 31-50 列里。

4) Character Variable (字符变量):虽然允许较长的字符串,但正常的长度用 8 个字符表示。在11 列里用符号 ' 随后跟字符串,紧接着用一个符号 '结束,它不能出现在 20 列之前。

按照此方法,可以读取出来FIT文件的头文件记录如下:

SIMPLE  =                    T / NORMAL FIT IMAGE                             
BITPIX = -64 / DATA PRECISION
NAXIS = 2 / NUMBER OF IMAGEDIMENSIONS
NAXIS1 = 3992 / NUMBER OF COLUMNS
NAXIS2 = 250 / NUMBER OF ROWS
EXTEND = T /Extensions may bepresent
CRVAL1 = 3.56089999899 / Central wavelength(log10) of first pixel
.
.
.
WAT0_001= 'system=linear' /
WAT1_001= 'wtype=linear label=Wavelength units=Angstroms'/
CD1_1 = 0.000100000 / Log10 dispersion perpixel
CRPIX1 = 1 / Starting pixel(1-indexed)
CTYPE1 ='LINEAR ' /
DC-FLAG = 1 / Log-linear flag
END


头文件读取完后,紧接的是数据文件,但是这里注意的是头文件的字节大小必须如开始说的是2880的整数倍,否则在后补空格。全部记录长度均为 23040 bits (2880bytes *8 bit, 3840bytes*6 bit)。这个长度能用市场上出售的所有计算机的位长和字长除尽, (即 6,8,12,16,18,24,32,36,48,60 和 64 bits)。这种通用性适用于在各种各样的计算机上读写记录。如图:


END结束的位置在0x27b2(第10162个字节处,可以通过读取这个关键字获取),所以从0x27b3开始补空格,空格的结束位置应该计算如下:

NUMBER_HEAD_UNIT= 10162/2880=3.5284722222222222222222222222222

因而头文件应该包括四个2880的数据单元,即头文件结束的位置:

END_HEADER_POSITION= 2880*4=11520(0x2cff)

空格应该在0x2cff处结束。从文件开头到偏移11520个字节,即0x2d00处开始正式的数据存储,如下图所示:

这里注意的是上图中0x2d00处的00表示起始数据就是0,不是其他标志。数据的实际长度为:

NAXIS1* NAXIS2 * BITPIX /8 = 8276000

其中:

NAXIS1:数据列数;

NAXIS2数据行数,这里数据250应该为250条光谱数据(通过焦面上4000根光纤和16台光谱仪);

BITPIX:数据表示的位数,64位,8个字节;

但是,8276000/2880 = 2873.6111111111111111111111111111,不是2880的整数倍,所以文件存储的长度应该为:

DATA_LENGTH= 2874*2880 = 8277120

所以,结束地址应该是:

END_DATA_POSTION= END_HEADER_POSITION + DATA_LENGTH

= 11520+8277120=8288640(0x7e7980)

如图所示:

 从上图也可以看出,数据结束后又开始了新的文件头,新的数据块,这里的数据存储及读取方式如开始所述类似,此处不再赘述。

    下面附上MATLAB程序,其中包含了对数据的读取和写入TXT文件:

clc,clear,close all;
filename = '20100121\9b_1_sp01.FIT';
fr_id = fopen(filename,'r','s'); %FITfile
info=FITinfo(filename);
%FIT file head info, which includeprimarydata and image
oset=info.PrimaryData.Offset;
%thesize of primarydata head and it is also the start of primarydata
cols =info.PrimaryData.Size(1);%the columns of primary data
rows =info.PrimaryData.Size(2);%the rows of primary data
SIZE_UNIT = 2880; %The size of a FIT logical record
SIZE_TYPE_NAME= 8; % size of keyword, Keyword= Value/Comment
SIZE_TYPE = 80; % size of (Keyword= Value/Comment)
num_type_prim = oset / SIZE_TYPE;%the numbers of primarydata head type

%-------get the start position oflamda and its step(log10)
for i=1:num_type_prim
fseek(fr_id, (i-1)*SIZE_TYPE,-1);
type_name = fread(fr_id, SIZE_TYPE_NAME,'*char');
switch type_name'
case 'BITPIX ' %data dispersion
fseek(fr_id,2,0); %skip two bytes,cause there are '= ' after type_name
str_tmp = fread(fr_id, SIZE_TYPE -SIZE_TYPE_NAME - 2,'*char');
data_percision =str2num(str_tmp(1:20)');
data_percision = abs(data_percision);
case 'CRVAL1 ' %thestart position of lamda
fseek(fr_id,2,0);
str_tmp = fread(fr_id, SIZE_TYPE -SIZE_TYPE_NAME - 2,'*char');
lamda_start =str2num(str_tmp(1:20)');
case 'CD1_1 ' %the step of lamda
fseek(fr_id,2,0);
str_tmp = fread(fr_id, SIZE_TYPE -SIZE_TYPE_NAME - 2,'*char');
lamda_deta =str2num(str_tmp(1:20)');
end
end

% calc the array of lamda(not logformat)
lamda = lamda_start:lamda_deta:lamda_start+lamda_deta*(cols-1);
for i=1:length(lamda)
lamda(i) = 10^lamda(i);
end

%--------------------write primaryhead----------------------
fph_id =fopen('primary_head_info.txt','w','b');
fseek(fr_id,0,-1);
for i=1:num_type_prim
head_info = fread(fr_id,SIZE_TYPE);
fwrite(fph_id,head_info);
fprintf(fph_id,'\r\n');
end
fclose(fph_id);

%--------------------write primarydata----------------------
fpd_id =fopen('prim_data.txt','w','s');
fseek(fr_id,oset,-1);
for i=1:5 %because of the openspeed in txt, this only write five rows data into txt file.If you want all, youcan replace 5 with rows
data_prim = fread(fr_id, cols, 'double');
figure
plot(lamda, data_prim);
fprintf(fpd_id,'%f ',data_prim);
end
fclose(fpd_id);


程序运行结果:
 




 

参考文献

[1]柯大荣 赵永恒.FIT 基本格式及其扩展.中国科学院北京天文台,1993年7月,

http://www.lamost.org/~yzhao/doc/FIT.html

[2] FIT Standard, Definition of theFlexible Image Transport System 


推荐阅读
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
  • OpenMap教程4 – 图层概述
    本文介绍了OpenMap教程4中关于地图图层的内容,包括将ShapeLayer添加到MapBean中的方法,OpenMap支持的图层类型以及使用BufferedLayer创建图像的MapBean。此外,还介绍了Layer背景标志的作用和OMGraphicHandlerLayer的基础层类。 ... [详细]
  • 本文介绍了使用C++Builder实现获取USB优盘序列号的方法,包括相关的代码和说明。通过该方法,可以获取指定盘符的USB优盘序列号,并将其存放在缓冲中。该方法可以在Windows系统中有效地获取USB优盘序列号,并且适用于C++Builder开发环境。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 图像因存在错误而无法显示 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 总结一下C中string的操作,来自〈CPrimer〉第四版。1.string对象的定义和初始化:strings1;空串strings2(s1);将s2初始 ... [详细]
  • 本文整理了Java中org.apache.solr.common.SolrDocument.setField()方法的一些代码示例,展示了SolrDocum ... [详细]
author-avatar
迷彩三角裤_625
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有