如何在IDL中读取HDF5 Time64列?

时间:2014-04-08 16:54:37

标签: hdf5 idl pytables

在Python中(使用pytables),可以很容易地创建包含时间戳的行的HDF5表(列数据类型为Time64,请参阅http://pytables.github.io/usersguide/datatypes.html)。

是否可以读取包含IDL 8.2中类型为Time64的列的表?

的默认方法
fid = H5F_OPEN(filename)
tabID = H5D_OPEN(fid, '/path/to/table')
data = H5D_READ(tabID)
如果节点/path/to/table包含Time64类型的列,则

似乎会阻塞。我想在IDL中有一种转换/解释数据类型的方法,即使IDL本身不支持它,或者不支持?毕竟,Time64列只是8个字节的值......

我能找到的最相关的IDL文档是http://www.exelisvis.com/docs/HDF5_Overview.html

作为一个侧面问题:来自HDF5组的HDFView似乎也不支持Time64,尽管HDF5中存在一种特殊的8字节列类型(对不起,我不允许发布另一个链接)。 pytables使用的这种列类型是不是标准的列类型?


编辑:我创建了一个包含带有Time64列的表的示例性hdf5文件,请参阅链接的注释。该文件是使用以下Python代码创建的:

import tables as T
import time

exampleTableColumns = {
    'id': T.Int32Col(pos=0),
    'value': T.Float32Col(pos=1),
    'timestamp': T.Time64Col(pos=2),
    }
with T.openFile('time64-example.h5', 'w') as h5:
    exampleTab = h5.createTable(
        '/', 'example', exampleTableColumns)
    # Add some test values
    t = time.time()
    for i in range(10):
        exampleTab.row['id'] = i
        exampleTab.row['value'] = i**2
        exampleTab.row['timestamp'] = t + 0.5*i
        exampleTab.row.append()
    exampleTab.flush()

我尝试从IDL读取它是:

fid = h5f_open(filename)
exampleTab = H5D_OPEN(fid, '/example')
; id: 32 bit signed integer, value: float32, timestamp: 8 byte value
struct = {id:0L, value:0.0, timestamp:0LL}
dt = H5T_IDL_CREATE(struct)
exampleData = H5D_READ(exampleTab, dt)
print, 'exampleData.id:', exampleData.id
print, 'exampleData.value', exampleData.value
print, 'exampleData.timestamp', exampleData.timestamp
h5d_close, exampleTab
h5f_close, fid

H5D_READ在获得自定义数据类型后不会再次阻塞,但idvalue字段中的值已经出现乱码。这是我从print语句得到的输出:

exampleData.id:           0           0           0  1095914052   174536304   153749104           0   172915600  1095914052   910565433
exampleData.value     0.000000     0.000000     0.000000      13.1451     0.000000     0.000000     0.000000     0.000000      13.1451      640.894
exampleData.timestamp                     0                     0                     0   3833484811918717440      5858206660165639             153997792
      5858318295760901             154274128   4051322254670378805      5858331130331138

如果我将struct更改为(我相信的等效定义)struct = {id:lonarr(1), value:0.0, timestamp:0LL},则打印语句会产生:

exampleData.id:   262404320           3   262404416           4   262404512          14           0   172915600  1095914052   910565433
exampleData.value     0.000000     0.000000     0.000000     0.000000     0.000000     0.000000     0.000000     0.000000      13.1451      640.894
exampleData.timestamp                     0                     0                     0   3833484811918717440                     0             153997568
      5858318295760901             154274128   4051322254670378805       791781549539330

1 个答案:

答案 0 :(得分:0)

我已经想出如何从数据文件中读取timestamp列。其中涉及阅读PyTables的来源。

看起来该列实际上是作为HDF5类型H5T_UNIX_D64LE编写的。还有一些比特转移。

以下(rtbl.py)是用于转储文件time64-example.h5的python版本:

#!/usr/env/bin python

import tables as T
import time

exampleTableColumns = {
    'id': T.Int32Col(pos=0),
    'value': T.Float32Col(pos=1),
    'timestamp': T.Time64Col(pos=2),
    }
with T.openFile('time64-example.h5', 'r') as h5:
    for row in h5.root.example[:]:
        print "%d\t%.2f\t%s" %(row['id'], row['value'],
            time.ctime(row['timestamp']))

运行这个我们可以得到以下结果:

$ env TZ=UTC ./rtbl.py
0   0.00    Wed Apr  9 08:56:24 2014
1   1.00    Wed Apr  9 08:56:25 2014
2   4.00    Wed Apr  9 08:56:25 2014
3   9.00    Wed Apr  9 08:56:26 2014
4   16.00   Wed Apr  9 08:56:26 2014
5   25.00   Wed Apr  9 08:56:27 2014
6   36.00   Wed Apr  9 08:56:27 2014
7   49.00   Wed Apr  9 08:56:28 2014
8   64.00   Wed Apr  9 08:56:28 2014
9   81.00   Wed Apr  9 08:56:29 2014

然后在C(rtbl.c)中做同样的事情 - 请原谅所有硬编码并且没有错误检查。

#include <stdlib.h>
#include <stdio.h>
#include <hdf5.h>
#include <time.h>

struct row {
    int id;
    float value;
    double time;
};

double
convert(double d) {
    union {
        double d;
        long long i;
    } di;
    double f;

    di.d = d;
    f = 1e-6 * (int)di.i + (di.i >> 32);
    return f;
}


int
main(int argc, char **argv)
{

    hid_t f_id;
    hid_t d_id;
    hid_t m_type;
    herr_t err;
    int i = 0;
    struct row rows[10] = {0};
    time_t clock;

    f_id = H5Fopen("time64-example.h5", H5F_ACC_RDONLY, H5P_DEFAULT);

    m_type = H5Tcreate(H5T_COMPOUND, sizeof(struct row));
    err = H5Tinsert(m_type, "id",        HOFFSET(struct row, id),
            H5T_STD_I32LE);
    err = H5Tinsert(m_type, "value",     HOFFSET(struct row, value),
            H5T_IEEE_F32LE);
    err = H5Tinsert(m_type, "timestamp", HOFFSET(struct row, time),
            H5T_UNIX_D64LE);

    d_id = H5Dopen(f_id, "example", H5P_DEFAULT);
    err = H5Dread(d_id, m_type, H5S_ALL, H5S_ALL, H5P_DEFAULT, rows);

    for (i = 0; i < 10; ++i) {
        clock = (time_t)convert(rows[i].time);
        printf("%d: %d\t%.2f\t%s", i,
                rows[i].id, rows[i].value, ctime(&clock));
    }

    H5Dclose(d_id);
    H5Fclose(f_id);

    return(EXIT_SUCCESS);
}

这会产生相同的结果:

$ h5cc -o rtbl rtbl.c && env TZ=UTC ./rtbl
0   0.00    Wed Apr  9 08:56:24 2014
1   1.00    Wed Apr  9 08:56:25 2014
2   4.00    Wed Apr  9 08:56:25 2014
3   9.00    Wed Apr  9 08:56:26 2014
4   16.00   Wed Apr  9 08:56:26 2014
5   25.00   Wed Apr  9 08:56:27 2014
6   36.00   Wed Apr  9 08:56:27 2014
7   49.00   Wed Apr  9 08:56:28 2014
8   64.00   Wed Apr  9 08:56:28 2014
9   81.00   Wed Apr  9 08:56:29 2014

所以这一切都回到了convert例程和H5T_UNIX_D64LE。我敢说,如果在大端上完成任何一项,那么LE应该是BE

对不起,自从我使用IDL并且无法访问它以来已经有好几年了,但我希望这会有所帮助。