0

HITRAN 数据库是分子旋转-振动跃迁的列表。它以文本文件的形式给出,其中每行 160 个字符,具有定义分子、同位素等的固定宽度字段。格式有据可查,甚至在MathWorks 文件交换上还有一个程序可以读取数据库并模拟频谱的一部分。但是,我需要读取光谱的特定部分,然后用它对测量的光谱进行一些拟合,所以我需要更多定制的东西。

正如该函数的注释部分以及其他地方所给出的,以下行应正确读取每一行:

database = which('HITRAN2012.par');
fid = fopen(database);
hitran = textscan(fid,'%2u%1u%12f%10f%10f%5f%5f%10f%4f%8f%15c%15c%15c%15c%6c%12c%1c%7f%7f','delimiter','','whitespace','');
fclose(fid);

前两个字段表示从 1-47 运行的分子代码和从 1-9 运行的同位素代码。

不幸的是,分子 1-9 没有前导零,无论我做什么,它似乎都在默默地混淆 MATLAB。如果我加载整个数据库然后输入

unique(hitran{1})

我没有得到 1-47 的数字,但我得到了 10-92 缺少一些数字。据我所知,当 MATLAB 遇到前导空格时,它会将行移过来,然后填充末尾,这样“12”就变成了“12”,但我不确定。我也试过

hitran = textscan(fid,'%160c','delimiter','\n','whitespace','');

然后尝试解析生成的字符串,但这有时也会被第一个空格弄糊涂。

例如,第一条水线看起来像

exampleHitranLine = ' 14    0.007002 1.165E-32 2.071E-14.05870.305  818.00670.590.000000          0 0 0          0 0 0  7  5  2        7  5  3      005540 02227 5 2 0    90.0   90.0';

第一段代码遇到这一行并返回'14'而不是' 1'and '4'。如果我只是读取一个仅包含分子 1 的子集(如本例中所示),那么第二种读取方法可以正常工作。但是,如果我尝试读取整个数据库,则分子 1-9 的行会向左移动,这会弄乱所有其他字段。

我应该注意,我尝试将数字字段读取为浮点数和整数,但都没有给出令人满意的结果。整个文本形式的数据库将近 700 MB,所以我需要一些尽可能高效的东西。

我究竟做错了什么?

4

2 回答 2

0

在 FileExchange 上有一个新文件,它将以 HITRAN 2004+ 格式数据读取。请尝试一下,如果有任何问题,请告诉我。

于 2014-03-10T06:11:27.347 回答
0

我没有关于为什么会发生这种情况的答案,但我确实有一个解决方案。如果有人对原因有答案,我很乐意接受。

这是把事情搞砸的领先空间。MATLAB 有点太聪明了,当textscan遇到一个前导空格时,它会判断它是多余的并丢弃它并移动到接下来的两个字符。为了让它在文件中正确读取,我必须逐行测试第一个字符是否为空格,然后用前导零替换它,如下所示:

database = which('HITRAN2012_First100Lines.par');

fileParams = dir(database);
K = fileParams.bytes/162;
hitran = cell(K,19);

fid = fopen(database);
for k = 1:K
hitranTemp = fgetl(fid);
if abs(hitranTemp(1)) == 32;
    hitranTemp(1) = '0';
end
    hitran(k,:) = deal(textscan(hitranTemp,'%2u%1u%12f%10f%10f%5f%5f%10f%4f%8f%15c%15c%15c%15c%6c%12c%1c%7f%7f','delimiter','','whitespace',''));
end
fclose(fid);

我在 MATLAB 2013a 中工作。我应该认为这是一个错误并报告它吗?是否有某些原因应该像这样吞噬领先空间?

更新:

我上面的解决方法很慢,但有效。然后我不得不处理 HITEMP 数据库,它比它大几倍,所以我最终向 MathWorks 提交了支持票。MathWorks 技术支持建议的解决方法是将所有内容作为文本读取,然后进行转换。这节省了大量的磁盘读取和工作。

fileParams = dir(database);

fid = fopen(database);

hitran = textscan(fid,'%2c%1c%12c%10c%10c%5c%5c%10c%4c%8c%15c%15c%15c%15c%6c%12c%1c%7c%7c','delimiter','','whitespace','');

fclose(fid);

moleculeNumber = uint8(str2num(hitran{1}));
isotopologueNumber = uint8(str2num(hitran{2});
vacuumWavenumber = str2num(hitran{3});
...
etc.

根据应用程序的不同,对于较大的数据库,您可能希望分块执行此操作,而不是一次全部执行。

他还表示,他会将这种行为转发给开发团队,以供将来更新时考虑。

于 2013-10-16T19:23:31.487 回答