Skip to content

Commit 2dda878

Browse files
committed
Add demo script for telescope case. More documentation cleanups.
1 parent 389e6c0 commit 2dda878

File tree

7 files changed

+248
-11
lines changed

7 files changed

+248
-11
lines changed

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
tidas
2-
=====
3-
41
TIDAS (TImestream DAta Storage)
2+
=======================================
3+
4+
Full documentation is online here:
5+
6+
http://hpc4cmb.github.io/tidas/
57

docs/sphinx/dev.rst

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
Developer Documentation
55
=============================
66

7-
8-
7+
The goal of this section is to provide more background information for developers reading through the source code and making changes.
98

109

1110
Backends
1211
--------------------------
1312

13+
.. todo::
1414

15+
Talk here about implementing backend classes for group, intervals, and dict objects.
1516

1617

1718
.. doxygenenum:: tidas::data_type
@@ -29,12 +30,19 @@ Location Information
2930

3031
Each object has a "location" which represents its on-disk position relative to other objects in the hierarchy.
3132

32-
.. doxygenclass:: tidas::backend_path
33-
:members:
33+
.. todo::
3434

35+
Add more details...
3536

37+
.. doxygenclass:: tidas::backend_path
38+
:members:
3639

3740

3841
Indexing (Metadata Database)
3942
----------------------------------
4043

44+
.. todo::
45+
46+
Describe the 2 different metadata indices, how transactions are retrieved / replayed, etc.
47+
48+

docs/sphinx/example.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,12 @@ to it.
1717

1818
.. literalinclude:: ../../examples/demo_weather.py
1919

20+
21+
Fake Telescope
22+
-------------------------
23+
24+
In this example, we create several groups per day with data at very different
25+
sampling rates.
26+
27+
.. literalinclude:: ../../examples/demo_telescope.py
28+

docs/sphinx/index.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ Contents:
1818
utils
1919
dev
2020

21-
.. todolist::
22-
2321

2422
Indices and tables
2523
==================

docs/sphinx/intro.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ Data Organization
2323

2424
The highest-level object in TIDAS is a "volume". A volume contains a hierarchy of "blocks". Each block is a logical collection of data based on some common property. A block can contain data itself, and/or other blocks. The data inside a block is organized into one or more "groups". The timestreams in a group are sampled consistently. A block can optionally contain an "intervals" object which is a collection of smaller time ranges within the block. These intervals might describe sections of good (or bad) data, or specify time ranges that have some special property. The two objects which actually contain data (groups and intervals) also have an optional dictionary of arbitrary scalar properties. Putting this all together, here is a crude schematic of a simple TIDAS volume:
2525

26-
(insert figure here)
26+
.. todo::
27+
28+
A figure here showing nested blocks and groups of timestreams would be nice.
2729

2830

2931
Code Organization and Requirements

examples/demo_telescope.py

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
#!/usr/bin/env python3
2+
##
3+
## TImestream DAta Storage (TIDAS)
4+
## Copyright (c) 2014-2017, all rights reserved. Use of this source code
5+
## is governed by a BSD-style license that can be found in the top-level
6+
## LICENSE file.
7+
##
8+
9+
# WARNING: Running this script will generate a several GB of data...
10+
11+
# This is just a toy exercise. We assume continuous data collection with
12+
# no gaps. We use very simple types of detector and housekeeping data.
13+
# In a "real" dataset, we would be unpacking raw frame data from a data
14+
# acquisition system and would know how many samples we have for a given
15+
# observation. Here we just make these numbers up.
16+
17+
# THIS IS JUST AN EXAMPLE.
18+
19+
import os
20+
import sys
21+
import shutil
22+
23+
import numpy as np
24+
25+
import datetime
26+
import calendar
27+
28+
import tidas
29+
30+
# The name of the volume
31+
32+
path = "demo_telescope"
33+
34+
# Create the schemas for the data groups that we will have for each day
35+
36+
# ---- Data from a weather station ----
37+
38+
weather_schema = {
39+
"windspeed" : ("float32", "Meters / second"),
40+
"windangle" : ("float32", "Degrees"),
41+
"temperature" : ("float32", "Degrees Celsius"),
42+
"pressure" : ("float32", "Millibars"),
43+
"humidity" : ("float32", "Percent"),
44+
"PWV" : ("float32", "mm")
45+
}
46+
47+
# sampled every 10 seconds
48+
weather_rate = 1.0 / 10.0
49+
weather_daysamples = int(24.0 * 3600.0 * weather_rate)
50+
51+
# ---- Housekeeping data ----
52+
53+
hk_schema = {
54+
"thermo1" : ("float32", "Degrees Kelvin"),
55+
"thermo2" : ("float32", "Degrees Kelvin")
56+
}
57+
58+
# sampled once per minute
59+
hk_rate = 1.0 / 60.0
60+
hk_daysamples = int(24.0 * 3600.0 * hk_rate)
61+
62+
# ---- Pointing data ----
63+
64+
pointing_schema = {
65+
"az" : ("float32", "Radians"),
66+
"el" : ("float32", "Radians"),
67+
"psi" : ("float32", "Radians")
68+
}
69+
70+
# sampled at 20 Hz
71+
pointing_rate = 20.0
72+
pointing_daysamples = int(24.0 * 3600.0 * pointing_rate)
73+
74+
# ---- Detector data ----
75+
76+
ndet = 50
77+
78+
det_schema = {}
79+
80+
for d in range(ndet):
81+
detname = "det_{:04d}".format(d)
82+
det_schema[detname] = ("int16", "ADU")
83+
84+
# sampled at 100Hz
85+
det_rate = 100.0
86+
det_daysamples = int(24.0 * 3600.0 * det_rate)
87+
88+
day_seconds = 24 * 3600
89+
90+
# Remove the volume if it exists
91+
92+
if os.path.isdir(path):
93+
shutil.rmtree(path)
94+
95+
# Create the volume all at once. To keep the size of the volume
96+
# reasonable for this demo, only write 3 days of data.
97+
98+
with tidas.Volume(path, backend="hdf5") as vol:
99+
100+
# Get the root block of the volume
101+
root = vol.root()
102+
103+
volstart = datetime.datetime(2018, 1, 1)
104+
volstartsec = volstart.timestamp()
105+
106+
for year in ["2018",]:
107+
# Add a block for this year
108+
yb = root.block_add(year)
109+
110+
for monthnum in range(1, 2):
111+
# Add a block for the month
112+
month = calendar.month_abbr[monthnum]
113+
mb = yb.block_add(month)
114+
115+
weekday, nday = calendar.monthrange(int(year), monthnum)
116+
for dy in range(1, 4):
117+
118+
daystart = datetime.datetime(int(year), monthnum, dy)
119+
daystartsec = (daystart - volstart).total_seconds() \
120+
+ volstartsec
121+
122+
# Add a block for the day
123+
day = "{:02d}".format(dy)
124+
db = mb.block_add(day)
125+
126+
# Just fake some seed for now
127+
seed = int(year) * 1000000 + monthnum * 10000 + dy * 100
128+
np.random.seed(seed)
129+
130+
# Now we are going to add the data groups for this day.
131+
132+
print("{}-{}-{:02d}:".format(year, month, dy))
133+
134+
print(" writing weather data")
135+
136+
weather = tidas.Group(schema=weather_schema,
137+
size=weather_daysamples)
138+
weather = db.group_add("weather", weather)
139+
weather.write_times(np.linspace(daystartsec,
140+
daystartsec + day_seconds, num=weather_daysamples))
141+
142+
data = np.absolute(np.random.normal(loc=0.0, scale=5.0,
143+
size=weather_daysamples)).astype(np.float32)
144+
weather.write("windspeed", 0, data)
145+
146+
data = 360.0 * np.absolute(np.random.random(
147+
size=weather_daysamples)).astype(np.float32)
148+
weather.write("windangle", 0, data)
149+
150+
data = np.absolute(np.random.normal(loc=25.0, scale=5.0,
151+
size=weather_daysamples)).astype(np.float32)
152+
weather.write("temperature", 0, data)
153+
154+
data = np.absolute(np.random.normal(loc=1013.25, scale=30.0,
155+
size=weather_daysamples)).astype(np.float32)
156+
weather.write("pressure", 0, data)
157+
158+
data = np.absolute(np.random.normal(loc=30.0, scale=10.0,
159+
size=weather_daysamples)).astype(np.float32)
160+
weather.write("humidity", 0, data)
161+
162+
data = np.absolute(np.random.normal(loc=10.0, scale=5.0,
163+
size=weather_daysamples)).astype(np.float32)
164+
weather.write("PWV", 0, data)
165+
166+
print(" writing housekeeping data")
167+
168+
hk = tidas.Group(schema=hk_schema, size=hk_daysamples)
169+
hk = db.group_add("hk", hk)
170+
hk.write_times(np.linspace(daystartsec,
171+
daystartsec + day_seconds, num=hk_daysamples))
172+
173+
data = np.random.normal(loc=273.0, scale=5.0,
174+
size=hk_daysamples).astype(np.float32)
175+
hk.write("thermo1", 0, data)
176+
177+
data = np.random.normal(loc=77.0, scale=5.0,
178+
size=hk_daysamples).astype(np.float32)
179+
hk.write("thermo2", 0, data)
180+
181+
print(" writing pointing data")
182+
183+
pointing = tidas.Group(schema=pointing_schema,
184+
size=pointing_daysamples)
185+
pointing = db.group_add("pointing", pointing)
186+
pointing.write_times(np.linspace(daystartsec,
187+
daystartsec + day_seconds, num=pointing_daysamples))
188+
189+
data = 2.0 * np.pi * np.random.random(
190+
size=pointing_daysamples).astype(np.float32)
191+
pointing.write("az", 0, data)
192+
193+
data = 0.4 * np.pi * np.random.random(
194+
size=pointing_daysamples).astype(np.float32)
195+
pointing.write("el", 0, data)
196+
197+
data = np.random.normal(loc=0.0, scale=(0.01*np.pi),
198+
size=pointing_daysamples).astype(np.float32)
199+
pointing.write("psi", 0, data)
200+
201+
print(" writing detector data")
202+
203+
det = tidas.Group(schema=det_schema, size=det_daysamples)
204+
det = db.group_add("detectors", det)
205+
det.write_times(np.linspace(daystartsec,
206+
daystartsec + day_seconds, num=det_daysamples))
207+
208+
for d in range(ndet):
209+
detname = "det_{:04d}".format(d)
210+
data = np.random.normal(loc=32768, scale=2000,
211+
size=det_daysamples).astype(np.int16)
212+
det.write(detname, 0, data)
213+
214+
# Take a quick peek at organization:
215+
216+
with tidas.Volume(path) as vol:
217+
vol.info()
218+

examples/demo_weather.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
}
3333

3434
# sampled every 10 seconds
35-
wind_rate = 10.0 / 60.0
35+
wind_rate = 1.0 / 10.0
3636
wind_daysamples = int(24.0 * 3600.0 * wind_rate)
3737

3838
thermal_schema = {

0 commit comments

Comments
 (0)