+"""Storage docstrings"""
+
+import tables
+
+
+class HisparcEvent(tables.IsDescription):
+ # DISCUSS: use of signed (dflt -1) vs unsigned (labview code)
+ event_id = tables.UInt32Col(pos=0)
+ timestamp = tables.Time32Col(pos=1)
+ nanoseconds = tables.UInt32Col(pos=2)
+ ext_timestamp = tables.UInt64Col(pos=3)
+ data_reduction = tables.BoolCol(pos=4)
+ trigger_pattern = tables.UInt32Col(pos=5)
+ baseline = tables.Int16Col(shape=4, dflt=-1, pos=6)
+ std_dev = tables.Int16Col(shape=4, dflt=-1, pos=7)
+ n_peaks = tables.Int16Col(shape=4, dflt=-1, pos=8)
+ pulseheights = tables.Int16Col(shape=4, dflt=-1, pos=9)
+ integrals = tables.Int32Col(shape=4, dflt=-1, pos=10)
+ traces = tables.Int32Col(shape=4, dflt=-1, pos=11)
+ event_rate = tables.Float32Col(pos=12)
+
+
+class HisparcError(tables.IsDescription):
+ """HiSPARC Error messages tables"""
+
+ event_id = tables.UInt32Col(pos=0)
+ timestamp = tables.Time32Col(pos=1)
+ messages = tables.Int32Col(dflt=-1, pos=2)
+
+
+class HisparcConfiguration(tables.IsDescription):
+ event_id = tables.UInt32Col(pos=0)
+ timestamp = tables.Time32Col(pos=1)
+ gps_latitude = tables.Float64Col(pos=2)
+ gps_longitude = tables.Float64Col(pos=3)
+ gps_altitude = tables.Float64Col(pos=4)
+ mas_version = tables.Int32Col(dflt=-1, pos=5)
+ slv_version = tables.Int32Col(dflt=-1, pos=6)
+ trig_low_signals = tables.UInt32Col(pos=7)
+ trig_high_signals = tables.UInt32Col(pos=8)
+ trig_external = tables.UInt32Col(pos=9)
+ trig_and_or = tables.BoolCol(pos=10)
+ precoinctime = tables.Float64Col(pos=11)
+ coinctime = tables.Float64Col(pos=12)
+ postcoinctime = tables.Float64Col(pos=13)
+ detnum = tables.UInt16Col(pos=14)
+ password = tables.Int32Col(dflt=-1, pos=15)
+ spare_bytes = tables.UInt8Col(pos=16)
+ use_filter = tables.BoolCol(pos=17)
+ use_filter_threshold = tables.BoolCol(pos=18)
+ reduce_data = tables.BoolCol(pos=19)
+ buffer = tables.Int32Col(dflt=-1, pos=20)
+ startmode = tables.BoolCol(pos=21)
+ delay_screen = tables.Float64Col(pos=22)
+ delay_check = tables.Float64Col(pos=23)
+ delay_error = tables.Float64Col(pos=24)
+ mas_ch1_thres_low = tables.Float64Col(pos=25)
+ mas_ch1_thres_high = tables.Float64Col(pos=26)
+ mas_ch2_thres_low = tables.Float64Col(pos=27)
+ mas_ch2_thres_high = tables.Float64Col(pos=28)
+ mas_ch1_inttime = tables.Float64Col(pos=29)
+ mas_ch2_inttime = tables.Float64Col(pos=30)
+ mas_ch1_voltage = tables.Float64Col(pos=31)
+ mas_ch2_voltage = tables.Float64Col(pos=32)
+ mas_ch1_current = tables.Float64Col(pos=33)
+ mas_ch2_current = tables.Float64Col(pos=34)
+ mas_comp_thres_low = tables.Float64Col(pos=35)
+ mas_comp_thres_high = tables.Float64Col(pos=36)
+ mas_max_voltage = tables.Float64Col(pos=37)
+ mas_reset = tables.BoolCol(pos=38)
+ mas_ch1_gain_pos = tables.UInt8Col(pos=39)
+ mas_ch1_gain_neg = tables.UInt8Col(pos=40)
+ mas_ch2_gain_pos = tables.UInt8Col(pos=41)
+ mas_ch2_gain_neg = tables.UInt8Col(pos=42)
+ mas_ch1_offset_pos = tables.UInt8Col(pos=43)
+ mas_ch1_offset_neg = tables.UInt8Col(pos=44)
+ mas_ch2_offset_pos = tables.UInt8Col(pos=45)
+ mas_ch2_offset_neg = tables.UInt8Col(pos=46)
+ mas_common_offset = tables.UInt8Col(pos=47)
+ mas_internal_voltage = tables.UInt8Col(pos=48)
+ mas_ch1_adc_gain = tables.Float64Col(pos=49)
+ mas_ch1_adc_offset = tables.Float64Col(pos=50)
+ mas_ch2_adc_gain = tables.Float64Col(pos=51)
+ mas_ch2_adc_offset = tables.Float64Col(pos=52)
+ mas_ch1_comp_gain = tables.Float64Col(pos=53)
+ mas_ch1_comp_offset = tables.Float64Col(pos=54)
+ mas_ch2_comp_gain = tables.Float64Col(pos=55)
+ mas_ch2_comp_offset = tables.Float64Col(pos=56)
+ slv_ch1_thres_low = tables.Float64Col(pos=57)
+ slv_ch1_thres_high = tables.Float64Col(pos=58)
+ slv_ch2_thres_low = tables.Float64Col(pos=59)
+ slv_ch2_thres_high = tables.Float64Col(pos=60)
+ slv_ch1_inttime = tables.Float64Col(pos=61)
+ slv_ch2_inttime = tables.Float64Col(pos=62)
+ slv_ch1_voltage = tables.Float64Col(pos=63)
+ slv_ch2_voltage = tables.Float64Col(pos=64)
+ slv_ch1_current = tables.Float64Col(pos=65)
+ slv_ch2_current = tables.Float64Col(pos=66)
+ slv_comp_thres_low = tables.Float64Col(pos=67)
+ slv_comp_thres_high = tables.Float64Col(pos=68)
+ slv_max_voltage = tables.Float64Col(pos=69)
+ slv_reset = tables.BoolCol(pos=70)
+ slv_ch1_gain_pos = tables.UInt8Col(pos=71)
+ slv_ch1_gain_neg = tables.UInt8Col(pos=72)
+ slv_ch2_gain_pos = tables.UInt8Col(pos=73)
+ slv_ch2_gain_neg = tables.UInt8Col(pos=74)
+ slv_ch1_offset_pos = tables.UInt8Col(pos=75)
+ slv_ch1_offset_neg = tables.UInt8Col(pos=76)
+ slv_ch2_offset_pos = tables.UInt8Col(pos=77)
+ slv_ch2_offset_neg = tables.UInt8Col(pos=78)
+ slv_common_offset = tables.UInt8Col(pos=79)
+ slv_internal_voltage = tables.UInt8Col(pos=80)
+ slv_ch1_adc_gain = tables.Float64Col(pos=81)
+ slv_ch1_adc_offset = tables.Float64Col(pos=82)
+ slv_ch2_adc_gain = tables.Float64Col(pos=83)
+ slv_ch2_adc_offset = tables.Float64Col(pos=84)
+ slv_ch1_comp_gain = tables.Float64Col(pos=85)
+ slv_ch1_comp_offset = tables.Float64Col(pos=86)
+ slv_ch2_comp_gain = tables.Float64Col(pos=87)
+ slv_ch2_comp_offset = tables.Float64Col(pos=88)
+
+
+class HisparcComparator(tables.IsDescription):
+ event_id = tables.UInt32Col(pos=0)
+ timestamp = tables.Time32Col(pos=1)
+ nanoseconds = tables.UInt32Col(pos=2)
+ ext_timestamp = tables.UInt64Col(pos=3)
+ device = tables.UInt8Col(pos=4)
+ comparator = tables.UInt8Col(pos=5)
+ count = tables.UInt16Col(pos=6)
+
+
+class HisparcSingle(tables.IsDescription):
+ event_id = tables.UInt32Col(pos=0)
+ timestamp = tables.Time32Col(pos=1)
+ mas_ch1_low = tables.Int32Col(dflt=-1, pos=2)
+ mas_ch1_high = tables.Int32Col(dflt=-1, pos=3)
+ mas_ch2_low = tables.Int32Col(dflt=-1, pos=4)
+ mas_ch2_high = tables.Int32Col(dflt=-1, pos=5)
+ slv_ch1_low = tables.Int32Col(dflt=-1, pos=6)
+ slv_ch1_high = tables.Int32Col(dflt=-1, pos=7)
+ slv_ch2_low = tables.Int32Col(dflt=-1, pos=8)
+ slv_ch2_high = tables.Int32Col(dflt=-1, pos=9)
+
+
+class HisparcSatellite(tables.IsDescription):
+ event_id = tables.UInt32Col(pos=0)
+ timestamp = tables.Time32Col(pos=1)
+ min_n = tables.UInt16Col(pos=2)
+ mean_n = tables.Float32Col(pos=3)
+ max_n = tables.UInt16Col(pos=4)
+ min_signal = tables.UInt16Col(pos=5)
+ mean_signal = tables.Float32Col(pos=6)
+ max_signal = tables.UInt16Col(pos=7)
+
+
+class WeatherEvent(tables.IsDescription):
+ event_id = tables.UInt32Col(pos=0)
+ timestamp = tables.Time32Col(pos=1)
+ temp_inside = tables.Float32Col(pos=2)
+ temp_outside = tables.Float32Col(pos=3)
+ humidity_inside = tables.Int16Col(pos=4)
+ humidity_outside = tables.Int16Col(pos=5)
+ barometer = tables.Float32Col(pos=6)
+ wind_dir = tables.Int16Col(pos=7)
+ wind_speed = tables.Int16Col(pos=8)
+ solar_rad = tables.Int16Col(pos=9)
+ uv = tables.Int16Col(pos=10)
+ evapotranspiration = tables.Float32Col(pos=11)
+ rain_rate = tables.Float32Col(pos=12)
+ heat_index = tables.Int16Col(pos=13)
+ dew_point = tables.Float32Col(pos=14)
+ wind_chill = tables.Float32Col(pos=15)
+
+
+class WeatherError(tables.IsDescription):
+ event_id = tables.UInt32Col(pos=0)
+ timestamp = tables.Time32Col(pos=1)
+ messages = tables.Int32Col(dflt=-1, pos=2)
+
+
+class WeatherConfig(tables.IsDescription):
+ event_id = tables.UInt32Col(pos=0)
+ timestamp = tables.Time32Col(pos=1)
+ com_port = tables.UInt8Col(pos=2)
+ baud_rate = tables.Int16Col(pos=3)
+ station_id = tables.UInt32Col(pos=4)
+ database_name = tables.Int32Col(dflt=-1, pos=5)
+ help_url = tables.Int32Col(dflt=-1, pos=6)
+ daq_mode = tables.BoolCol(pos=7)
+ latitude = tables.Float64Col(pos=8)
+ longitude = tables.Float64Col(pos=9)
+ altitude = tables.Float64Col(pos=10)
+ temperature_inside = tables.BoolCol(pos=11)
+ temperature_outside = tables.BoolCol(pos=12)
+ humidity_inside = tables.BoolCol(pos=13)
+ humidity_outside = tables.BoolCol(pos=14)
+ barometer = tables.BoolCol(pos=15)
+ wind_direction = tables.BoolCol(pos=16)
+ wind_speed = tables.BoolCol(pos=17)
+ solar_radiation = tables.BoolCol(pos=18)
+ uv_index = tables.BoolCol(pos=19)
+ evapotranspiration = tables.BoolCol(pos=20)
+ rain_rate = tables.BoolCol(pos=21)
+ heat_index = tables.BoolCol(pos=22)
+ dew_point = tables.BoolCol(pos=23)
+ wind_chill = tables.BoolCol(pos=24)
+ offset_inside_temperature = tables.Float32Col(pos=25)
+ offset_outside_temperature = tables.Float32Col(pos=26)
+ offset_inside_humidity = tables.Int16Col(pos=27)
+ offset_outside_humidity = tables.Int16Col(pos=28)
+ offset_wind_direction = tables.Int16Col(pos=29)
+ offset_station_altitude = tables.Float32Col(pos=30)
+ offset_bar_sea_level = tables.Float32Col(pos=31)
+
+
+class LightningEvent(tables.IsDescription):
+ event_id = tables.UInt32Col(pos=0)
+ timestamp = tables.Time32Col(pos=1)
+ corr_distance = tables.Int16Col(pos=2)
+ uncorr_distance = tables.Int16Col(pos=3)
+ uncorr_angle = tables.Float32Col(pos=4)
+ corr_angle = tables.Float32Col(pos=5)
+
+
+class LightningError(tables.IsDescription):
+ event_id = tables.UInt32Col(pos=0)
+ timestamp = tables.Time32Col(pos=1)
+ messages = tables.Int32Col(dflt=-1, pos=2)
+
+
+class LightningConfig(tables.IsDescription):
+ event_id = tables.UInt32Col(pos=0)
+ timestamp = tables.Time32Col(pos=1)
+ com_port = tables.UInt8Col(pos=2)
+ baud_rate = tables.Int16Col(pos=3)
+ station_id = tables.UInt32Col(pos=4)
+ database_name = tables.Int32Col(dflt=-1, pos=5)
+ help_url = tables.Int32Col(dflt=-1, pos=6)
+ daq_mode = tables.BoolCol(pos=7)
+ latitude = tables.Float64Col(pos=8)
+ longitude = tables.Float64Col(pos=9)
+ altitude = tables.Float64Col(pos=10)
+ squelch_seting = tables.Int32Col(pos=11)
+ close_alarm_distance = tables.Int32Col(pos=12)
+ severe_alarm_distance = tables.Int32Col(pos=13)
+ noise_beep = tables.BoolCol(pos=14)
+ minimum_gps_speed = tables.Int32Col(pos=15)
+ angle_correction = tables.Float32Col(pos=16)
+
+
+class LightningStatus(tables.IsDescription):
+ event_id = tables.UInt32Col(pos=0)
+ timestamp = tables.Time32Col(pos=1)
+ close_rate = tables.Int16Col(pos=2)
+ total_rate = tables.Int16Col(pos=3)
+ close_alarm = tables.BoolCol(pos=4)
+ sever_alarm = tables.BoolCol(pos=5)
+ current_heading = tables.Float32Col(pos=6)
+
+
+class LightningNoise(tables.IsDescription):
+ event_id = tables.UInt32Col(pos=0)
+ timestamp = tables.Time32Col(pos=1)
+
+
+
+
[docs]
+
def open_or_create_file(data_dir, date):
+
"""Open an existing file or create a new one
+
+
This function opens an existing PyTables file according to the event
+
date. If the file does not yet exist, a new one is created.
+
+
:param data_dir: the directory containing all data files
+
:param date: the event date
+
+
"""
+
directory = data_dir / f'{date.year}/{date.month}'
+
file = directory / f'{date.year}_{date.month}_{date.day}.h5'
+
+
# Ensure dir and parent directories exist with mode rwxr-xr-x
+
directory.mkdir(mode=0o755, parents=True, exist_ok=True)
+
+
return tables.open_file(file, 'a')
+
+
+
+
+
[docs]
+
def get_or_create_station_group(file, cluster, station_id):
+
"""Get an existing station group or create a new one
+
+
:param file: the PyTables data file
+
:param cluster: the name of the cluster
+
:param station_id: the station number
+
+
"""
+
cluster = get_or_create_cluster_group(file, cluster)
+
node_name = f'station_{station_id}'
+
try:
+
station = file.get_node(cluster, node_name)
+
except tables.NoSuchNodeError:
+
station = file.create_group(cluster, node_name, f'HiSPARC station {station_id} data')
+
file.flush()
+
+
return station
+
+
+
+
+
[docs]
+
def get_or_create_cluster_group(file, cluster):
+
"""Get an existing cluster group or create a new one
+
+
:param file: the PyTables data file
+
:param cluster: the name of the cluster
+
+
"""
+
try:
+
hisparc = file.get_node('/', 'hisparc')
+
except tables.NoSuchNodeError:
+
hisparc = file.create_group('/', 'hisparc', 'HiSPARC data')
+
file.flush()
+
+
node_name = 'cluster_' + cluster.lower()
+
try:
+
cluster = file.get_node(hisparc, node_name)
+
except tables.NoSuchNodeError:
+
cluster = file.create_group(hisparc, node_name, f'HiSPARC cluster {cluster} data')
+
file.flush()
+
+
return cluster
+
+
+
+
+
[docs]
+
def get_or_create_node(file, cluster, node):
+
"""Get an existing node or create a new one
+
+
:param file: the PyTables data file
+
:param cluster: the parent (cluster) node
+
:param node: the node (e.g. events, blobs)
+
+
"""
+
try:
+
node = file.get_node(cluster, node)
+
except tables.NoSuchNodeError:
+
if node == 'events':
+
node = file.create_table(cluster, 'events', HisparcEvent, 'HiSPARC event data')
+
elif node == 'errors':
+
node = file.create_table(cluster, 'errors', HisparcError, 'HiSPARC error messages')
+
elif node == 'config':
+
node = file.create_table(cluster, 'config', HisparcConfiguration, 'HiSPARC configuration messages')
+
elif node == 'comparator':
+
node = file.create_table(cluster, 'comparator', HisparcComparator, 'HiSPARC comparator messages')
+
elif node == 'singles':
+
node = file.create_table(cluster, 'singles', HisparcSingle, 'HiSPARC single messages')
+
elif node == 'satellites':
+
node = file.create_table(cluster, 'satellites', HisparcSatellite, 'HiSPARC satellite messages')
+
elif node == 'blobs':
+
node = file.create_vlarray(cluster, 'blobs', tables.VLStringAtom(), 'HiSPARC binary data')
+
elif node == 'weather':
+
node = file.create_table(cluster, 'weather', WeatherEvent, 'HiSPARC weather data')
+
elif node == 'weather_errors':
+
node = file.create_table(cluster, 'weather_errors', WeatherError, 'HiSPARC weather error messages')
+
elif node == 'weather_config':
+
node = file.create_table(cluster, 'weather_config', WeatherConfig, 'HiSPARC weather configuration messages')
+
elif node == 'lightning':
+
node = file.create_table(cluster, 'lightning', LightningEvent, 'HiSPARC lightning data')
+
elif node == 'lightning_errors':
+
node = file.create_table(cluster, 'lightning_errors', LightningError, 'HiSPARC lightning error messages')
+
elif node == 'lightning_config':
+
node = file.create_table(
+
cluster,
+
'lightning_config',
+
LightningConfig,
+
'HiSPARC lightning configuration messages',
+
)
+
elif node == 'lightning_status':
+
node = file.create_table(cluster, 'lightning_status', LightningStatus, 'HiSPARC lightning status messages')
+
elif node == 'lightning_noise':
+
node = file.create_table(cluster, 'lightning_noise', LightningNoise, 'HiSPARC lightning noise messages')
+
file.flush()
+
+
return node
+
+