1# This file is part of h5py, a Python interface to the HDF5 library. 2# 3# http://www.h5py.org 4# 5# Copyright 2008-2013 Andrew Collette and contributors 6# 7# License: Standard 3-clause BSD; see "license.txt" for full license terms 8# and contributor agreement. 9 10import numpy as np 11 12import h5py 13from h5py import h5t 14 15from .common import TestCase, ut 16 17 18class TestCompound(ut.TestCase): 19 20 """ 21 Feature: Compound types can be created from Python dtypes 22 """ 23 24 def test_ref(self): 25 """ Reference types are correctly stored in compound types (issue 144) 26 """ 27 dt = np.dtype([('a', h5py.ref_dtype), ('b', '<f4')]) 28 tid = h5t.py_create(dt, logical=True) 29 t1, t2 = tid.get_member_type(0), tid.get_member_type(1) 30 self.assertEqual(t1, h5t.STD_REF_OBJ) 31 self.assertEqual(t2, h5t.IEEE_F32LE) 32 self.assertEqual(tid.get_member_offset(0), 0) 33 self.assertEqual(tid.get_member_offset(1), h5t.STD_REF_OBJ.get_size()) 34 35 def test_out_of_order_offsets(self): 36 size = 20 37 type_dict = { 38 'names': ['f1', 'f2', 'f3'], 39 'formats': ['<f4', '<i4', '<f8'], 40 'offsets': [0, 16, 8] 41 } 42 43 expected_dtype = np.dtype(type_dict) 44 45 tid = h5t.create(h5t.COMPOUND, size) 46 for name, offset, dt in zip( 47 type_dict["names"], type_dict["offsets"], type_dict["formats"] 48 ): 49 tid.insert( 50 name.encode("utf8") if isinstance(name, str) else name, 51 offset, 52 h5t.py_create(dt) 53 ) 54 55 self.assertEqual(tid.dtype, expected_dtype) 56 self.assertEqual(tid.dtype.itemsize, size) 57 58 59class TestTypeFloatID(TestCase): 60 """Test TypeFloatID.""" 61 62 def test_custom_float_promotion(self): 63 """Custom floats are correctly promoted to standard floats on read.""" 64 65 # This test uses the low-level API, so we need names as byte strings 66 test_filename = self.mktemp().encode() 67 dataset = b'DS1' 68 dataset2 = b'DS2' 69 dataset3 = b'DS3' 70 dataset4 = b'DS4' 71 dataset5 = b'DS5' 72 73 dims = (4, 7) 74 75 wdata = np.array([[-1.50066626e-09, 1.40062184e-09, 1.81216819e-10, 76 4.01087163e-10, 4.27917257e-10, -7.04858394e-11, 77 5.74800652e-10], 78 [-1.50066626e-09, 4.86579665e-10, 3.42879503e-10, 79 5.12045517e-10, 5.10226528e-10, 2.24190444e-10, 80 3.93356459e-10], 81 [-1.50066626e-09, 5.24778443e-10, 8.19454726e-10, 82 1.28966349e-09, 1.68483894e-10, 5.71276360e-11, 83 -1.08684617e-10], 84 [-1.50066626e-09, -1.08343556e-10, -1.58934199e-10, 85 8.52196536e-10, 6.18456397e-10, 6.16637408e-10, 86 1.31694833e-09]], dtype=np.float32) 87 88 wdata2 = np.array([[-1.50066626e-09, 5.63886715e-10, -8.74251782e-11, 89 1.32558853e-10, 1.59161573e-10, 2.29420039e-10, 90 -7.24185156e-11], 91 [-1.50066626e-09, 1.87810656e-10, 7.74889486e-10, 92 3.95630195e-10, 9.42236511e-10, 8.38554115e-10, 93 -8.71978045e-11], 94 [-1.50066626e-09, 6.20275387e-10, 7.34871719e-10, 95 6.64840627e-10, 2.64662958e-10, 1.05319486e-09, 96 1.68256520e-10], 97 [-1.50066626e-09, 1.67347025e-10, 5.12045517e-10, 98 3.36513040e-10, 1.02545528e-10, 1.28784450e-09, 99 4.06089384e-10]], dtype=np.float32) 100 101 # Create a new file using the default properties. 102 fid = h5py.h5f.create(test_filename) 103 # Create the dataspace. No maximum size parameter needed. 104 space = h5py.h5s.create_simple(dims) 105 106 # create a custom type with larger bias 107 mytype = h5t.IEEE_F16LE.copy() 108 mytype.set_fields(14, 9, 5, 0, 9) 109 mytype.set_size(2) 110 mytype.set_ebias(53) 111 mytype.lock() 112 113 dset = h5py.h5d.create(fid, dataset, mytype, space) 114 dset.write(h5py.h5s.ALL, h5py.h5s.ALL, wdata) 115 116 del dset 117 118 # create a custom type with larger exponent 119 mytype2 = h5t.IEEE_F16LE.copy() 120 mytype2.set_fields(15, 9, 6, 0, 9) 121 mytype2.set_size(2) 122 mytype2.set_ebias(53) 123 mytype2.lock() 124 125 dset = h5py.h5d.create(fid, dataset2, mytype2, space) 126 dset.write(h5py.h5s.ALL, h5py.h5s.ALL, wdata2) 127 128 del dset 129 130 # create a custom type which reimplements 16-bit floats 131 mytype3 = h5t.IEEE_F16LE.copy() 132 mytype3.set_fields(15, 10, 5, 0, 10) 133 mytype3.set_size(2) 134 mytype3.set_ebias(15) 135 mytype3.lock() 136 137 dset = h5py.h5d.create(fid, dataset3, mytype3, space) 138 dset.write(h5py.h5s.ALL, h5py.h5s.ALL, wdata2) 139 140 del dset 141 142 # create a custom type with larger bias 143 mytype4 = h5t.IEEE_F16LE.copy() 144 mytype4.set_fields(15, 10, 5, 0, 10) 145 mytype4.set_size(2) 146 mytype4.set_ebias(258) 147 mytype4.lock() 148 149 dset = h5py.h5d.create(fid, dataset4, mytype4, space) 150 dset.write(h5py.h5s.ALL, h5py.h5s.ALL, wdata2) 151 152 del dset 153 154 # create a dataset with long doubles 155 dset = h5py.h5d.create(fid, dataset5, h5t.NATIVE_LDOUBLE, space) 156 dset.write(h5py.h5s.ALL, h5py.h5s.ALL, wdata2) 157 158 # Explicitly close and release resources. 159 del space 160 del dset 161 del fid 162 163 f = h5py.File(test_filename, 'r') 164 165 # ebias promotion to float32 166 values = f[dataset][:] 167 np.testing.assert_array_equal(values, wdata) 168 self.assertEqual(values.dtype, np.dtype('<f4')) 169 170 # esize promotion to float32 171 values = f[dataset2][:] 172 np.testing.assert_array_equal(values, wdata2) 173 self.assertEqual(values.dtype, np.dtype('<f4')) 174 175 # regular half floats 176 dset = f[dataset3] 177 try: 178 self.assertEqual(dset.dtype, np.dtype('<f2')) 179 except AttributeError: 180 self.assertEqual(dset.dtype, np.dtype('<f4')) 181 182 # ebias promotion to float64 183 dset = f[dataset4] 184 self.assertEqual(dset.dtype, np.dtype('<f8')) 185 186 # long double floats 187 dset = f[dataset5] 188 self.assertEqual(dset.dtype, np.longdouble) 189