Disclaimer: These results are only presented for illustrating different features of tsprocess. The runs are some random simulations. They should not be used for any other purposes.
See Setting Up Environment section to set up the environment.
# import project module
from tsprocess import project as pr
# Let's start a new project
p1 = pr.Project("project_1")
Each project will connect to a database with project name + "_db.sqlite" database (in this example: project_1_db.sqlite). If the database is exist, it will use that database, otherwise new database will be generated.
# Let's take a look at a summary of the project database.
p1.database_summary()
* database tracker is used to track records of different incidents inside the database. You can ignore it.
# Each project needs a source hypocenter. These tests runs are conducted for 2014 Lahabra, CA, earthquake.
p1.add_source_hypocenter(33.933, -117.916, 5.1)
Please note that these folders are prepared according to Incidents preparation instructions.
Here are the description.txt
of these folders.
# folder herclules_1 description.txt:
incident_name = hercules101
incident_type = hercules
inputfiles_parameters = inputfiles/parameters.in
source_hypocenter = 33.933, -117.916, 5.1
hr_comp_orientation_1 = 39.9
hr_comp_orientation_2 = 129.9
ver_comp_orientation = down
incident_unit = m
# folder herclules_2 description.txt:
incident_name = hercules102
incident_type = hercules
inputfiles_parameters = inputfiles/parameters.in
source_hypocenter = 33.933, -117.916, 5.1
hr_comp_orientation_1 = 39.9
hr_comp_orientation_2 = 129.9
ver_comp_orientation = down
incident_unit = m
# let's add incidents to the project
h_folder_1 = 'hercules_1'
h_folder_2 = 'hercules_2'
p1.add_incident(h_folder_1)
p1.add_incident(h_folder_2)
Adding incident to the project connects the incident folder to project and loads its stations location. However, it does not load any record. Inside the description.txt
file there is a incident_name variable. It should be a unique value. Any attemp to load new incident with used names will be denied. For example, if we want to add incident for h_folder_1 again, it will be denied.
p1.add_incident(h_folder_1)
In tsprocess, the users are not allowed to directly process the records. However, they can define processing label. Each processing label has a unique name, a combination of the record and processing label generates a unique hash value which help us to track the processed records.
# let's take a look at valid processing labels
p1.valid_processing_labels()
Up to this point that I am preparing this report, there are 10 different processing labels and their types are self-explanatory. See API Reference page for more details.
# let's add some processing labels
# I want to add a lowpass filter with corner frequency at 2 Hz. Let's call it lpf2.
p1.add_processing_label('lpf2','lowpass_filter', {'fc':2, 'N':4})
Now, lpf2 is a reserved name and we cannot use it as a processing label name for other processing labels. For example, another attemp to reuse the name will be denied.
p1.add_processing_label('lpf2','highpass_filter', {'fc':0.1, 'N':4})
tsprocess merge the records from different incidents based on their geographical locations. At this point any record that are closer than 10 m will be estimated at the same location. In the future versions, we will make it adjustable by the user. Choosing station for any process are based on stations filter. There are several approach to choose stations. See API Reference page for more details.
# let's take a look at valid stations filter (Not to be confused with timeseries filtering)
p1.valid_station_filter_type()
# let's add some station filter. One can use several station filters.
# The final result will be the intersection of all used filters.
# For example, I want to study stations in less than 10 km from the source of earthquake.
# let's call it 'lesst10km'
p1.add_station_filter('lesst10km','epi_dist_lt',{'distance':10})
One can define station filter and processing label at any time of the processing (of course before using them). In this section, I define a couple of processing labels and station filters for future use.
p1.add_processing_label('stcm','set_unit',{'unit':'cm'}) # to convert all data to cm
p1.add_processing_label('hpf0.1','highpass_filter',{'fc':0.1, 'N':4}) # highpass filter with corner freq at 0.1 Hz.
p1.add_processing_label('bpf1_2','bandpass_filter',{'fcs':[1,2], 'N':4}) #bandpass filters with corner freqs 1,2 Hz.
p1.add_processing_label('taper_it','taper',{'flag':'all', 'm':100}) # tapers both side of the signal, 100 data samples each.
p1.add_station_filter('moret10km','epi_dist_gt',{'distance':10}) # stations at epicentral distance more than 10 km
p1.add_station_filter('lesst20km','epi_dist_lt',{'distance':20}) # stations at epicentral distance less than 20 km
p1.add_station_filter('azb0_90','azimuth_bt',{'azmth':[0,90]}) # stations at azimuth between 0 and 90 degrees.
p1.add_station_filter("select_stations", "include_stlist_by_incident",
{"incident_name":"hercules101",
"stations":['station.9','station.29','station.34']}) # select station location based on their names at one of incidents.
p1.add_station_filter("select_station", "include_stlist_by_incident",
{"incident_name":"hercules101",
"stations":['station.20']}) # select station location based on their names at one of incidents.
Now, we have enough materials to process data. At any time, that we need to add any processing labels or stations filters we can add them. let's take a look at those stations that are located between 10 and 20 km from the source of earthquake.
p1.show_stations_on_map2(['hercules101'],[[]],['moret10km','lesst20km'],{'llrtlatlon':[33.0,-119.5,35.5,-116.5]})
If we do not use any station filter, it will represent all available stations.
p1.show_stations_on_map2(['hercules101'],[[]],[],{'llrtlatlon':[33.0,-119.5,35.5,-116.5]})
We can take a look at the location of select stations.
p1.show_stations_on_map2(['hercules101'],[[]],['select_stations'],{'llrtlatlon':[33.0,-119.5,35.5,-116.5]})
We can take a look at the stations at azimuth between 0 and 90 degrees.
p1.show_stations_on_map2(['hercules101'],[[]],['azb0_90'],{'llrtlatlon':[33.0,-119.5,35.5,-116.5]})
Any processing with these station filters will be applied to those stations showed in the map.
# let's take a look at available processing labels.
p1.list_of_processing_labels()
# let's take a look at velocity timeseries at select station (station.20) for 'hercules101'.
p1.plot_velocity_records(['hercules101'],[[]],['select_station'],{})
# let's have both of them ('hercules101' and 'hercules102')
p1.plot_velocity_records(['hercules101','hercules102'],[[],[]],['select_station'],{})
# This two simulation are done for one earthquake, but they seem very different.
# Let's see what is the difference between these simulations.
import pandas as pd
table = p1.compare_incidents(['hercules101','hercules102'], only_differences=False)
with pd.option_context('display.max_rows', None, 'display.max_columns', None):
display(table)
# this is too much and most of them are the same.
# Just show the differences
p1.compare_incidents(['hercules101','hercules102'], only_differences=True)
# Ok, Now we can see the reason for very high amplitudes. Damping was not active at the first simulation.
# Let's take a look at the results, with applying lowpass filter (f=2)
p1.plot_velocity_records(['hercules101','hercules102'],[['lpf2'],['lpf2']],['select_station'],{})
# Now it makes sense, however, there is an artifact.
# let's first taper the signals then fitler them.
p1.plot_velocity_records(['hercules101','hercules102'],
[['taper_it','lpf2'],['taper_it','lpf2']],
['select_station'],
{})
# Can we take a closer look at the frequnecy content may be 0 - 4 ?
p1.plot_velocity_records(['hercules101','hercules102'],
[['taper_it','lpf2'],['taper_it','lpf2']],
['select_station'],
{'zoom_in_freq':[0,4]})
# How about time, can we take a look at between 5 and 12 seconds?
p1.plot_velocity_records(['hercules101','hercules102'],
[['taper_it','lpf2'],['taper_it','lpf2']],
['select_station'],
{'zoom_in_freq':[0,4], 'zoom_in_time':[5,12]})
# How is the acceleration timeseries look like?
p1.plot_acceleration_records(['hercules101','hercules102'],
[['taper_it','lpf2'],['taper_it','lpf2']],
['select_station'],
{})
# I wonder to know how much filter order can affect the results?
# Especifically, is there any difference between N=4, N=8, and N=16? Let's say for lowpass filter at 2 Hz.
p1.add_processing_label('lpf2_n8','lowpass_filter',{'fc': 2, 'N': 8})
p1.add_processing_label('lpf2_n16','lowpass_filter',{'fc': 2, 'N': 16})
p1.plot_velocity_records(['hercules101','hercules101','hercules101'],
[['taper_it','lpf2'],['taper_it','lpf2_n8'],['taper_it','lpf2_n16']],
['select_station'],
{'zoom_in_freq':[0,4]})
As we expected, higher filter order gives sharp cut at the corner frequency.
# And by the way, how is this station components orientation?
p1.plot_records_orientation(['hercules101','hercules102'],
[[],[]],
['select_station'],
{})
# Intersting! can we switch the vertical component to up?
p1.add_processing_label('v_up','set_vertical_or',{'ver_or':'up'})
p1.plot_records_orientation(['hercules101','hercules102'],
[[],['v_up']],
['select_station'],
{})
# I do not beleive you :). Can I see the timeseries?
p1.plot_velocity_records(['hercules101','hercules101'],
[['taper_it','lpf2'],['v_up','taper_it','lpf2']],
['select_station'],
{'zoom_in_freq':[0,4], 'zoom_in_time':[0,20]})
# That is right.
# Can I align the record to 0 and 90 degrees?
p1.add_processing_label('align_0_90','align_record',{'hc_or1':0, 'hc_or2':90, 'ver_or':'down'})
p1.plot_records_orientation(['hercules101','hercules101'],
[[],['align_0_90']],
['select_station'],
{})
# Great! I assume, 0,90, down and 180, 270, up should be in the upozit direction, right?
# let's try:
p1.add_processing_label('align_180_270','align_record',{'hc_or1':180, 'hc_or2':270, 'ver_or':'up'})
p1.plot_records_orientation(['hercules101','hercules101'],
[['align_0_90'],['align_180_270']],
['select_station'],
{})
p1.plot_velocity_records(['hercules101','hercules101'],
[['align_0_90','taper_it','lpf2'],['align_180_270','taper_it','lpf2']],
['select_station'],
{'zoom_in_time':[1,20],'zoom_in_freq':[0,4]})
# OK. Cool. Can we take a look at the same comparison, but on the select stations.
p1.plot_velocity_records(['hercules102','hercules102'],
[['align_0_90','taper_it','lpf2'],['align_180_270','taper_it','lpf2']],
['select_stations'],
{'zoom_in_time':[1,20], 'zoom_in_freq':[0,4]})
Here are some other processing that is possible to conduct on time series.
# Scaling
p1.add_processing_label('sc1.2','scale',{'factor':1.2})
p1.plot_velocity_records(['hercules101','hercules101'],
[['taper_it','lpf2','sc1.2'],['taper_it','lpf2']],
['select_station'],
{'zoom_in_time':[1,20],'zoom_in_freq':[0,4]})
# Zero-padding at the fron for one second.
p1.add_processing_label('zp1.0f','zero_pad',{'flag':'front', 'm':100, 't_diff':1})
p1.plot_velocity_records(['hercules101','hercules101'],
[['taper_it','lpf2','zp1.0f'],['taper_it','lpf2']],
['select_station'],
{'zoom_in_time':[0,30],'zoom_in_freq':[0,4]})
# rotate time series (45 degrees)
p1.add_processing_label('rt45','rotate',{'angle':45})
p1.plot_velocity_records(['hercules101','hercules101'],
[['taper_it','lpf2'],['taper_it','lpf2','rt45']],
['select_station'],
{'zoom_in_time':[0,30],'zoom_in_freq':[0,4]})
# Let's take a look at orientation
p1.plot_records_orientation(['hercules101','hercules101'],
[['taper_it','lpf2'],['taper_it','lpf2','rt45']],
['select_station'],
{})
# Let's define some other rotation angles.
p1.add_processing_label('rt10','rotate',{'angle':10})
p1.add_processing_label('rt90','rotate',{'angle':90})
p1.add_processing_label('rt180','rotate',{'angle':180})
p1.add_processing_label('rt360','rotate',{'angle':360})
# So, if I rotate the record 8 times by 45 degrees I should get the same results.
# let's see:
p1.plot_velocity_records(['hercules101','hercules101'],
[['taper_it','lpf2'],['taper_it','lpf2','rt45','rt45','rt45','rt45','rt45','rt45','rt45','rt45']],
['select_station'],
{'zoom_in_time':[0,30],'zoom_in_freq':[0,4]})
# So, if I rotate the record 4 times by 90 degreess we should get the same result.
# let's see:
p1.plot_velocity_records(['hercules101','hercules101'],
[['taper_it','lpf2'],['taper_it','lpf2','rt90','rt90','rt90','rt90']],
['select_station'],
{'zoom_in_time':[0,30],'zoom_in_freq':[0,4]})
# So, results of rotating the signla by 90 degrees, and twice by 45 degrees and 9 times by 10 degrees should be the same.
# let's see:
p1.plot_velocity_records(['hercules101','hercules101','hercules101'],
[['taper_it','lpf2','rt90'],
['taper_it','lpf2','rt45','rt45'],
['taper_it','lpf2','rt10','rt10','rt10','rt10','rt10','rt10','rt10','rt10','rt10']],
['select_station'],
{'zoom_in_time':[0,30],'zoom_in_freq':[0,4]})
p1.plot_records_orientation(['hercules101','hercules101','hercules101','hercules101','hercules101','hercules101'],
[['taper_it','lpf2','rt10'],
['taper_it','lpf2','rt10','rt10'],
['taper_it','lpf2','rt10','rt10','rt10','rt10'],
['taper_it','lpf2','rt10','rt10','rt10','rt10','rt10'],
['taper_it','lpf2','rt10','rt10','rt10','rt10','rt10','rt10'],
['taper_it','lpf2','rt10','rt10','rt10','rt10','rt10','rt10','rt10'],
],
['select_station'],
{'zoom_in_time':[0,30],'zoom_in_freq':[0,4]})
p1.plot_velocity_records(['hercules101','hercules101'],
[['taper_it','lpf2'],['taper_it','lpf2','rt360']],
['select_station'],
{'zoom_in_time':[0,30],'zoom_in_freq':[0,4]})
# We conducted many analyses. Are they stored in the database?
# Yes. We can take a look at a summary of the database:
p1.database_summary()
# I think this is enough for example 1. We close the database and close this page.
# Closing database makes sure that there is no pending data in the tracking buffer.
p1.close_database()