Home
Curriculum (PDF)
Research
Publications
Software
Research Group
SeismoLinks
Teaching

 

 

 

 

 

 

NUEVO PROGRAMA GEOCIENCIAS UNIANDES 2011-01 (LINK)

Paper online:

factor_irf

Just published in BSSA, we quantify variations in source parameter estimates at closely spaced stations. Accurate estimates of course parameters and their uncertainties are essential, particularly when the results are used in the comparisons among different studies over a range of earthquake magnitudes and locations.

map_time

We use an empirical Green’s function method to spectra estimated using the seismic coda to investigate earthquake source scaling. Our data span a magnitude range from Mw 3.0–Mw 7.1. We find that a constant scaled energy provides a reasonable fit to the data, with no dependence of scaled energy on seismic moment. Published in JGR. g can be generated from ambient noise. Figure above shows the IRF of the Factor Building in UCLA at two different frequency bands.

 

The notes here describe the use of Antelope's Datascope database system with Fortran90. Antelope is a product of Boulder Real-Time technologies, Inc. www.brtt.com. Here I show some examples for using F90 and how you are supposed to write your codes.

How do I write a Makefile?
How do I define Antelope variables?
How do I open a database?
How do I open a specific table from a database?
How many records has my table?
How do I sort a table?
How do I make a subset of a table?
How do I join two tables?
How do I create a database out of my joined view?
How do I get some values from the tables?
How do I put some value in a given table?
How do I put new values (new line) in a table?
What if I want to delete a row from a table?

top
How do I write a Makefile?

This is sometimes difficult to do. Sometimes it can create all the problems in your coding.
 
   ------------- 	
   Example 1 	
   -------------
   
   BIN =  program_name 
   
   cflags = -g 	
   fflags = -g	
   ldlibs = $(STOCKLIBS) $(TRLIBS) $(DBLIBS)	
   
   include $(ANTELOPEMAKE) 
   DIRS=		
   
   OBJS =  program_name.o 	
   
   $(BIN) : $(OBJS)		
   $(RM) $@			
   $(FC) $(FFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LDLIBS)	
   
   ---------------------------------------------------------------------

   -------------	
   Example 2		
   -------------	
   
   BIN =  program_name2	
   
   cflags = -g	
   fflags = -g	
   ldlibs = $(STOCKLIBS) $(TRLIBS) $(DBLIBS)	
   
   include $(ANTELOPEMAKE) 	
   DIRS=			
   
   OBJS =  program_name1.o	
   
   $(BIN) : $(OBJS)	
           $(RM) $@	
           $(FC) $(FFLAGS) -o $@ $(OBJS) $(LDFLAGS) $(LDLIBS)	

   OBJS2 =  program_name2.o	
   
   program_name2 : $(OBJS2)	
           $(RM) $@		
           $(FC) $(FFLAGS) -o $@ $(OBJS2) $(LDFLAGS) $(LDLIBS)	
   
   ------------------------------------------------------------------------
   
top
How do I define Antelope variables?
   Using antelope, there are some issues defining variables

   1.- The db tables, or in this case, db pointers are defined

           integer :: db(4), db_origin(4), db_wfdisc

   2.- All reals in Antelope are real(8).

           real(8) :: yyyy, xxxxx

   3.- Include the appropiate libraries

      include "/home/gprieto/fortran/antelope/include/db.i"
      include "/home/gprieto/fortran/antelope/include/coords.i"

      Here, note that I'm not linking to the $ANTELOPE libraries for
      fortran, since they don't work with F90 (due to the last
      commented line starting with c ... ; where the date and
      copyright is typed). The copies I have here have the last line
      removed.

   4.- Use the appropiate length for characters. Very important.

      character (len=8)  :: net, phase
      character (len=6)  :: magtype, sta
      character (len=15) :: auth

   ---------------------------------------------------------------------
   
top
How do I open a database?

To open a database just use

   ----------
   
   if ( dbopen ( 'database_name',"r+", db) /= 0 ) then
      write(6,'(a)') 'Bad, problem when opening database'
   endif

   ----------
   

The value "db" will be the one used later in the code.

Note that dbopen is not called, as a subroutine. It returns an integer, which should be zero when it succeeds. A different number means an error.

This code prints out when there is a problem, but won't stop the program.

---------------------------------------------------------------------------

top
How do I open a specific table from a database?

This is quite simple, using this idea

   ----------

   call dblookup (db__origin, db, "", "origin", "","")
   call dblookup (db__stamag, db, "", "stamag", "","")
   call dblookup (db__xxxxxx, db, "", "xxxxxx", "","")

   ----------
   

Note all the empty spaces. ALL of them are needed.

In matlab there is a easier approach "dblookup_table", which I think its not available for Fortran.

---------------------------------------------------------------------------

top
How many records has my table?

These here is to get the number of lines in a given table (arrival, event, etc) or even subsetted or joined tables.

   ----------

   call dbquery(db_origin, dbRECORD_COUNT, nrecords)
   print *, 'Origin table with ', nrecords

   ----------

   --------------------------------------------------------------------------
   
top
How do I sort a table?

Here, one can sort tables using the default keys; or you could assign the keys to be used.

Also you have to chance to

   In general the syntax is

   integer :: db(4)
   integer :: keys, flag

   call dbsort(db,db, keys, flag,"comment")
   

The keys, when you leave them out (I think leave a zero) will use dbsort with standard keys. You should use, or define the keys anyway, to avoid problems.

The flag, is use to set the way dbsort works. When flag=0, the usual dbsort works. If flag=1, a reverse order dbsort is called, and if flag=2, a unique sort is used.

   -------------
   Example 1
   -------------
   
   Defining the Primary keys

      call dbquery ( db, dbPRIMARY_KEY, keys )
      call dbsort ( db, db, keys, 0, "sort_origin" )

   Note here, the Primary keys are used.

   ---------------------------------------------------------------------

   -------------
   Example 2
   -------------
   
   call strtbl (keys,"origin.time","origin.orid","origin.lat", &
                'origin.lon','origin.depth',0)
   call dbsort(dbj, db_origin, keys, 2,"") ! the 2 means unique sort


   Here, I fixed the keys that are going to be used to sort the table.

   ---------------------------------------------------------------------
   
top
How do I make a subset of a table?

Here is a simple example. Note that the syntax of the subset is the one of Antelope, not of Fortran. This means that not equal isn't .ne. or /=. In C syntax, this would be !=.

   -------------
   Example 1
   -------------

   character (len=XXX) == txtsubset
   integer :: db(4)

      write(txtsubset,*) trim(txtsubset)//' && prefor==orid'

      call dbsubset( db, db, trim(txtsubset), "comment")
      call dbquery(dbj, dbRECORD_COUNT, nrecords)
      print *, 'Lines after subsetting table with ', nrecords

   -------------
   Example 2
   -------------

   character (len=50) :: expression
   integer :: db(4)

      write ( expression, * ) "evid ==", evid
      call dbsubset ( db, db, expression , "event")

   ----------------------------------------------------------------------
   
top
How do I join two tables?

To join two tables, first one has to open them, of course, and use dbjoin

the syntax is
   integer :: dbout(4), db1(4), db2(4)
   integer :: keys1, keys2

   call strtbl(keys1,"sta","yyyyyyy.time",0)  ! keys for table db1
   call strtbl(keys2,"sta","xxxxxxx.time",0)  ! keys for table db2

   call dbjoin(dbout,db1,db1,keys1,keys2,0,0,"")
   

If you want Datascope to select the appropiate keys, set keys=0 like example 1.

   -------------
   Example 1
   -------------

   integer :: db_netmag(4), db_stamag(4), db_netsta(4), dbj(4)
   integer :: n_netsta

   !
   ! Open main table
   !

   if ( dbopen ( 'all_data',"r", db) /= 0 ) then
      write(6,'(a)') 'Bad, problem when opening database'
   endif

   !
   ! Open individual tables
   !

   call dblookup (db_stamag, db, "", "stamag", "","")
   call dblookup (db_netmag, db, "", "netmag", "","")

   !
   ! Join tables
   !

   call dbjoin(db_netsta,db_netmag,db_stamag,0,0,0,0,"")
   call dbquery(db_netsta, dbRECORD_COUNT, n_netsta)
   print *, 'Rows netmag table with ', n_netsta

   ----------------------------
   

However, sometimes, you want to join tables that are not symmetrical. For example, if you go

 
   event/origin/assoc/arrival/wfdisc
   
it might give you a different result than going
   wfdisc/arrival/assoc/origin/event
   

But you don't want to start with wfdisc, because it might be too big to handle. This discrepancy comes from the fact that since you start with event-origin the join KEYS are going to be origin.time and others. And when you want to join wfdisc, the origin.time isn't necessarily in the wfdisc.time::endtime range.

So it won't join.

To correct this, before you make the last join, you have to change the JOIN KEYS to arrival.time wfdisc.time::endtime. Note however, that if you set a new key, you have to set ALL keys again. If you do not do that it would join ONLY with the time keys, and you might want to use the station as well.

Here is the example to do this.

Assuming dbj is the join of

   event/origin/assoc/arrival

   -------------
   Example 2
   -------------

   call dbquery(dbj, dbRECORD_COUNT, nrecords)
   print *, 'Event/Origin/Assoc/Arrival table with ', nrecords

   !
   ! Define the parameter to do the last join
   !

   call strtbl(keys1,"sta","arrival.time",0)
   call strtbl(keys2,"sta","time::endtime",0)

   !
   ! Open wfdiisc table
   !

   call dblookup (db_wf, db, "", "wfdisc","","")
   call dbquery(db_wf, dbRECORD_COUNT, nrecords)
   print *, 'Lines in the wfdisc table ', nrecords

   !
   ! Do the final join, event/origin/assoc/arrival/wfdisc
   !

   call dbjoin(dboutput,dbj,db_wf, keys1, keys2,0,0,"")
   call dbquery(dboutput, dbRECORD_COUNT, nrecords)
   print *, 'Final join ev/or/assoc/arr,wfdisc table with ', nrecords

   ----------------------------------------------------------------------
   
top
How do I create a database out of my joined view?

If you want to save a database from a joined and subsetted view that comes from your fortran code, you use dbunjoin

Assuming dboutput is the joined and subsetted table you want to save

   -------------
   Example 1
   -------------
   
   integer :: dboutput(4)

   if (dbunjoin( dboutput, 'new_database',0) /= 0) then
      write (6,'(a)') 'Error saving the database table'
   endif

   ------------------------------------------------------------------------
   
top
How do I get some values from the tables?

This helps you to get values from db tables. It can be used in single tables or joined tables.

Remember that for C/Datascope the first line is actually the zeroth term

Remember to set all the values to the right denomination, remember reals are always real(8). If you would like to get a vector, like a matlab code would do, use this example.

Assuming you know the number of lines in your table
   -------------
   Example 1
   -------------
   
   integer :: db(4)
   integer :: iget, nrecords, i

   allocate(time(nrecords))
   allocate(lat(nrecords))
   allocate(lon(nrecords))
   allocate(depth(nrecords))
   allocate(orid(nrecords))
   allocate(evid(nrecords))
   allocate(ml(nrecords))
   allocate(mlid(nrecords))
   allocate(auth(nrecords))

   do i = 1,nrecords

      db(4) = i-1

      iget = dbgetv (db,0,                         & 
                        "origin.time",          time(i),       &
                        "origin.lat",           lat(i),        &
                        "origin.lon",           lon(i),        &
                        "origin.depth",         depth(i),      &
                        "origin.orid",          orid(i),       &
                        "origin.evid",          evid(i),       &
                        "origin.ml",            ml(i),         &
                        "origin.auth",          auth(i),       &
                               0)

   enddo

   ---------------------------------------------------------------------
   

If you actually don't want a vector of the values, and want to use the values inside the loop, use this code here. Remember the i-1 factor always.

   -------------
   Example 2
   -------------
   
   do i = 1,nrecords

      k = i-1

      db(4) = k

      iget = dbgetv (db,0,                          &
                        "origin.time",          time,       &
                        "origin.lat",           lat,        &
                        "origin.lon",           lon,        &
                        "origin.depth",         depth,      &
                        "origin.orid",          orid,       &
                        "origin.evid",          evid,       &
                        "origin.ml",            ml,         &
                        "origin.auth",          auth,       &
                               0)

      !!!! Do something with the individual values


   enddo

   ---------------------------------------------------------------------
   
top
How do I put some value in a given table?

If for example you measured a magnitude, say mb, ml, and you want to put that value in the database, because is -999.00 (the default), you use dbputv.

Be EXTREMELY careful, dbputv doesn't work very intuitevely if you use it on sorted tables.

dbputv only works in individual tables, and in the syntax you are supposed to especify whihc table you are editing.

Again, be extremely careful, this does NOT tell you if you are replacing an existing value. Do not use it on sorted tables.

Also, always use dbnextid to avoid repeating id values (mlid, wfid, etc)
   --------------
   Example 1
   --------------
   
   integer :: db(4)
   integer :: j, idml

   real(8) :: ml        ! remember real(8)

   ml = 5.0  (or any value from anywhere)

   do j = 1,nrecords

      idml = dbnextid(db, 'mlid')

      iput = dbputv (db,"origin",             &
                          "origin.ml",    ml,             &
                          "origin.mlid",  idml,           &
                          0)

   enddo

   ---------------------------------------------------------------------------
   
top
How do I put new values (new line) in a table?

Say you have a new waveform, or new netmag line, with couple of stamag lines. You need to add a new line at the end of the appropiate table. You use dbaddv.

dbaddv adds a NEW line, creating empty (actually the appropiate null values are put in with the dbSCRATCH).

The advantage of dbaddv is that it checks to ensure that you do not repeat Primary keys, and that id's are new (mlid, wfid, orid, etc).

   -------------------
   Example 1
   -------------------
   
   db(4) = dbaddv (db,"table_name",    &
                     "magid",                magid,       &
                     "sta",                  sta,         &
                     "arid",                 arid,        &
                     "orid",                 orid,        &
                     "evid",                 evid,        &
                     "phase",                phase,       &
                     "magtype",              magtype,     &
                     "magnitude",            magnitude,   &
                     "uncertainty",          uncertainty, &
                     "auth",                 auth,        &
                     "commid",               commid,      &
                            0)

   -----------------------------
   

Note, how dbaddv (as well as dbputv, dbgetv) returns an integer. Zero is success. Note also the pairwise syntax. Remember the real(8) and the appropiate description of each of the variables. Do not put a character in mlid (who knows what comes out).

"table_name" can be wfdisc, event, origin, stamag, netmag, etc. You can only put values that belong to that table, do not use in joined tables. This wouldn't work and it would give an error. This example is for the "stamag" table.

---------------------------------------------

top
What if I want to delete a row from a table?

Say for example, you would like to delete some rows of a given table. For example you only want a table with a given orid's, which are not sequential.

You can loop through each line (I don't know if this is the most efficient way to do it, but works for me) and test whether that orid is what you want, and if not, delete that row.

Remember you need to open the database with permission, or you save a new database with dbunjoin.

This works with single tables or joined ones. The idea is to use it on joined ones, or to later join the "chopped" table to others.

Note how the loop is read backwards. Everytime you remove a row, the rows move up one step. So you have to do it backwards to avoid removing lines you actually want, or making the ith loop to be larger than the number of lines in the chopped table.

   ----------
   Example 1
   ----------
   
   !
   !  Read the table in reverse order (Thus last entry is obeyed)
   !

   do i = nrecords, 1, -1
      dbj(4) = i - 1
      ievid = dbgetv(dbj,0,"evid",evidid,0)

      isave = 0
      do k = 1,nx
         if (evidid == evid(k)) then
            isave = 1
            exit
         endif
      enddo

      if (isave == 0) then
         idel = dbdelete(dbj)
      endif

   enddo

   call dbquery(dbj, dbRECORD_COUNT, nrecords)
   print *, 'Lines after event table subset ', nrecords

   if (dbunjoin( dbj, 'new_databse_name',0) /= 0) then
   write (6,'(a)') 'Error saving the database table'

   -------------------------------------------------------------------