1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4#       Copyright (C) 2005-2007 Carabos Coop. V. All rights reserved
5#       Copyright (C) 2008-2019 Vicent Mas. All rights reserved
6#
7#       This program is free software: you can redistribute it and/or modify
8#       it under the terms of the GNU General Public License as published by
9#       the Free Software Foundation, either version 3 of the License, or
10#       (at your option) any later version.
11#
12#       This program is distributed in the hope that it will be useful,
13#       but WITHOUT ANY WARRANTY; without even the implied warranty of
14#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15#       GNU General Public License for more details.
16#
17#       You should have received a copy of the GNU General Public License
18#       along with this program.  If not, see <http://www.gnu.org/licenses/>.
19#
20#       Author:  Vicent Mas - vmas@vitables.org
21
22#
23#       This script is based on a set of scripts by Francesc Alted.
24
25"""Several simple Tables."""
26
27import sys
28
29import numpy
30import tables
31
32class Particle(tables.IsDescription):
33    """Description of a table record.
34    """
35    name        = tables.StringCol(16, pos=1)   # 16-character String
36    lati        = tables.Int32Col(pos=2)        # integer
37    longi       = tables.Int32Col(pos=3)        # integer
38    pressure    = tables.Float32Col(pos=4)      # float  (single-precision)
39    temperature = tables.Float64Col(pos=5)      # double (double-precision)
40
41# Open a file in "w"rite mode
42fileh = tables.open_file("table_samples.h5", mode = "w")
43
44root = fileh.root
45# Create a new group
46group = fileh.create_group(root, "newgroup")
47
48# Create a new table in newgroup group
49table = fileh.create_table(group, 'table', Particle, "A table",
50    tables.Filters(1))
51particle = table.row
52
53# Fill the table with 10 particles
54for i in range(10):
55    # First, assign the values to the Particle record
56    particle['name']  = 'Particle: %6d' % (i)
57    particle['lati'] = i
58    particle['longi'] = 10 - i
59    particle['pressure'] = float(i*i)
60    particle['temperature'] = float(i**2)
61    # This injects the row values.
62    particle.append()
63
64# We need to flush the buffers in table in order to get an
65# accurate number of records on it.
66table.flush()
67
68# Add a couple of user attrs
69table.attrs.user_attr1 = 1.023
70table.attrs.user_attr2 = "This is the second user attr"
71
72# Append several rows in only one call
73table.append([("Particle:     10", 10, 0, 10*10, 10**2),
74              ("Particle:     11", 11, -1, 11*11, 11**2),
75              ("Particle:     12", 12, -2, 12*12, 12**2)])
76table.flush()
77
78class Particle2(tables.IsDescription):
79    """Description of a table record.
80    """
81    name        = tables.StringCol(16, pos=1)   # 16-character String
82    lati        = tables.ComplexCol(itemsize=16, pos=2)
83    longi       = tables.ComplexCol(itemsize=8, pos=3)
84    vector      = tables.ComplexCol(itemsize=8, shape=(2,), pos=4)
85    matrix2D    = tables.ComplexCol(itemsize=16, shape=(2, 2), pos=5)
86
87# Open a file in "w"rite mode
88table1 = fileh.create_table(root, 'table1', Particle2, "A table")
89# Append several rows in only one call
90table1.append([("Particle:     10", 10j, 0, (10*9+1j, 1), [[10**2j, 11*3]]*2),
91              ("Particle:     11", 11j, -1, (11*10+2j, 2), [[11**2j, 10*3]]*2),
92              ("Particle:     12", 12j, -2, (12*11+3j, 3), [[12**2j, 9*3]]*2),
93              ("Particle:     13", 13j, -3, (13*11+4j, 4), [[13**2j, 8*3]]*2),
94              ("Particle:     14", 14j, -4, (14*11+5j, 5), [[14**2j, 7*3]]*2)])
95table1.flush()
96
97######
98class Particle3(tables.IsDescription):
99    ADCcount    = tables.Int16Col()              # signed short integer
100    TDCcount    = tables.UInt8Col()              # unsigned byte
101    grid_i      = tables.Int32Col()              # integer
102    grid_j      = tables.Int32Col()              # integer
103    idnumber    = tables.Int64Col()              # signed long long
104    name        = tables.StringCol(16, dflt="")  # 16-character String
105    pressure    = tables.Float32Col(shape=2)     # float  (single-precision)
106    temperature = tables.Float64Col()            # double (double-precision)
107
108Particle4 = {
109    # You can also use any of the atom factories, i.e. the one which
110    # accepts a PyTables type.
111    "ADCcount"    : tables.Col.from_type("int16"),    # signed short integer
112    "TDCcount"    : tables.Col.from_type("uint8"),    # unsigned byte
113    "grid_i"      : tables.Col.from_type("int32"),    # integer
114    "grid_j"      : tables.Col.from_type("int32"),    # integer
115    "idnumber"    : tables.Col.from_type("int64"),    # signed long long
116    "name"        : tables.Col.from_kind("string", 16),  # 16-character String
117    "pressure"    : tables.Col.from_type("float32", (2,)), # float  (single-precision)
118    "temperature" : tables.Col.from_type("float64"),  # double (double-precision)
119}
120
121# Create a new group under "/" (root)
122group = fileh.create_group("/", 'detector')
123
124# Create one table on it
125#table = h5file.create_table(group, 'table', Particle, "Title example")
126# You can choose creating a Table from a description dictionary if you wish
127table2 = fileh.create_table(group, 'table', Particle4, "Title example")
128
129# Create a shortcut to the table record object
130particle = table2.row
131
132# Fill the table with 10 particles
133for i in range(10):
134    # First, assign the values to the Particle record
135    particle['name']  = 'Particle: %6d' % (i)
136    particle['TDCcount'] = i % 256
137    particle['ADCcount'] = (i * 256) % (1 << 16)
138    particle['grid_i'] = i
139    particle['grid_j'] = 10 - i
140    particle['pressure'] = [float(i*i), float(i*2)]
141    particle['temperature'] = float(i**2)
142    particle['idnumber'] = i * (2 ** 34)  # This exceeds integer range
143    # This injects the Record values.
144    particle.append()
145
146# Flush the buffers for table
147table2.flush()
148
149# Create a new group to hold new arrays
150gcolumns = fileh.create_group("/", "columns")
151pressure = [ p['pressure'] for p in table2.iterrows() ]
152# Create an array with this info under '/columns' having a 'list' flavor
153fileh.create_array(gcolumns, 'pressure', pressure,
154                   "Pressure column")
155
156# Do the same with TDCcount, but with a numpy object
157TDC = [ p['TDCcount'] for p in table2.iterrows() ]
158fileh.create_array('/columns', 'TDC', numpy.array(TDC), "TDCcount column")
159
160# Do the same with name column
161names = [ p['name'] for p in table2.iterrows() ]
162fileh.create_array('/columns', 'name', names, "Name column")
163
164# Save a recarray object under detector
165r = numpy.rec.array("a"*300, formats='f4,3i4,a5,i2', shape=3)
166recarrt = fileh.create_table("/detector", 'recarray', r, "RecArray example")
167r2 = r[0:3:2]
168# Change the byteorder property
169recarrt = fileh.create_table("/detector", 'recarray2', r2,
170                             "Non-contiguous recarray")
171
172# Finally, append some new records to table
173table3 = fileh.root.detector.table
174
175# Append 5 new particles to table (yes, tables can be enlarged!)
176particle = table3.row
177for i in range(10, 15):
178    # First, assign the values to the Particle record
179    particle['name']  = 'Particle: %6d' % (i)
180    particle['TDCcount'] = i % 256
181    particle['ADCcount'] = (i * 256) % (1 << 16)
182    particle['grid_i'] = i
183    particle['grid_j'] = 10 - i
184    particle['pressure'] = [float(i*i), float(i*2)]
185    particle['temperature'] = float(i**2)
186    particle['idnumber'] = i * (2 ** 34)  # This exceeds integer range
187    # This injects the Row values.
188    particle.append()
189
190# Flush this table
191table3.flush()
192
193# Finally, close the file
194fileh.close()
195