


Introduction to	Library	Functions			 QLIB2(3)



NAME
     qlib2 - Subroutine	library	for Quanterra data  and	 MiniSEED
     data manipulation

DATA STRUCTURES
     The qlib2 routines	are designed to	read and manipulate  Min-
     iSEED  data  record.   A  number  of  structures  have  been
     designed to facilite these	operations.

     #define   DH_STATION_LEN 5
     #define   DH_CHANNEL_LEN 3
     #define   DH_LOCATION_LEN	   2
     #define DH_NETWORK_LEN   2

     /*	Linked list structure for storing blockettes.		 */
     typedef struct _bs	{		/* blockette structure.	      */
	 char  *pb;	      /* ptr to	actual blockette.   */
	 unsigned short	int type;	/* blockette number.	      */
	 unsigned short	int len;	/* length of blockette in bytes.*/
	 unsigned short	int wordorder;	/* wordorder of	blockette.    */
	 struct	_bs *next;		/* ptr to next blockette struct.*/
     } BS;

     /*	Data header structure, containing SEED Fixed Data Header info */
     /*	as well	as other useful	info.			    */
     typedef struct data_hdr {
	 int	    seq_no;		/* sequence number	 */
	 char  station_id[DH_STATION_LEN+1]; /*	station	name	      */
	 char  location_id[DH_LOCATION_LEN+1];	  /* location id      */
	 char  channel_id[DH_CHANNEL_LEN+1]; /*	channel	name	      */
	 char  network_id[DH_NETWORK_LEN+1]; /*	network	id	 */
	 INT_TIME   begtime;	   /* begin time with corrections     */
	 INT_TIME   endtime;	   /* end time of packet	 */
	 INT_TIME   hdrtime;	   /* begin time in hdr		 */
	 int	    num_samples;	/* number of samples	      */
	 int	    num_data_frames;	/* number of data frames */
	 int	    sample_rate;	/* sample rate		 */
	 int	    sample_rate_mult;	/* sample rate multiplier.    */
	 int	    num_blockettes;	     /*	# of blockettes	(0)   */
	 int	    num_ticks_correction;    /*	time correction	in ticks*/
	 int	    first_data;		/* offset to first data	      */
	 int	    first_blockette;	/* offset of first blockette  */
	 BS	    *pblockettes;	/* ptr to blockette structures*/
	 int	    data_type;		/* data_type (for logs or data)*/
	 int	    blksize;	   /* blocksize	of record (bytes).    */
	 unsigned char activity_flags;	/* activity flags	 */
	 unsigned char io_flags;	/* i/o flags		 */
	 unsigned char data_quality_flags;   /*	data quality flags    */
	 unsigned char hdr_wordorder;	/* wordorder of	header.	      */
	 unsigned char data_wordorder;	/* wordorder of	data.	      */
	 char  record_type;	   /* record type ('D' or 'V')	 */
	 char  cextra[2];	   /* future expansion.		 */



BDSN		  Last change: 25 October 1996			1






Introduction to	Library	Functions			 QLIB2(3)



	 int	    x0;		   /* first value (STEIM compress)    */
	 int	    xn;		   /* last value (STEIM	compress)     */
	 int	    xm1;	   /* future expansion.		 */
	 int	    xm2;	   /* future expansion.		 */
	 int	    extra[1];	   /* future expansion.		 */
     } DATA_HDR;

     /*	Attribute structure for	a specific data_hdr and	blksize.      */
     typedef struct _ms_attr{
	 int sample_size;		/* # bytes for sampe (0=NA)   */
	 int   alignment;		/* alignment requirement (1 min)*/
	 int nframes;		   /* #	of frame in use	(0=NA)	 */
	 int framelimit;	   /* max # of frames  (0=NA)	 */
	 int nbytes;			/* # of	bytes in use	      */
	 int bytelimit;		   /* max # of bytes	    */
     } MS_ATTR;

     /*	  Time structures.			  */

     typedef struct _ext_time {
	 int	    year;	   /*  Year.	       */
	 int	    doy;      /*  Day of year (1-366)	    */
	 int	    month;	   /*  Month (1-12)	    */
	 int	    day;      /*  Day of month (1-31)	    */
	 int	    hour;	   /*  Hour (0-23)		 */
	 int	    minute;	   /*  Minute (0-59)	    */
	 int	    second;	   /*  Second (0-60 (leap)) */
	 int	    usec;	   /*  Microseconds (0-999999)	 */
     } EXT_TIME;

     typedef struct _int_time {
	 int	    year;	   /*  Year.	       */
	 int	    second;	   /*  Seconds in year (0-...)	 */
	 int	    usec;	   /*  Microseconds (0-999999)	 */
     } INT_TIME;


GENERAL	ROUTINES
     extern int	get_my_wordorder()

     The function get_my_wordorder() will determine the	wordorder
     of	 the  computer,	set the	external variable my_wordorder to
     the computer's wordorder, and return the  wordorder  as  the
     function  value.	If  the	 functions  set_hdr_wordorder and
     set_data_wordorder	have not been called  to  explicitly  set
     the  desired  hdr_wordorder  and data_wordorder for creating
     MiniSEED data, these functions will be initialized	appropri-
     ately.   Depending	 on  how  qlib2	 was compiled, these will
     either be initialized to the computer's wordorder	OR  to	a
     fixed  wordorder  such  as	 SEED_BIG_ENDIAN.   This function
     should be called before any other qlib2  function.	  If  the
     user  does	 not call this function, it will be called by the



BDSN		  Last change: 25 October 1996			2






Introduction to	Library	Functions			 QLIB2(3)



     required qlib2 functions.


     extern int	set_hdr_wordorder
	(int	    wordorder)	   /* desired wordorder	of MiniSEED hdr.*/

     The function set_hdr_wordorder() will set the  desired  wor-
     dorder  for  the fixed header of created MiniSEED records to
     the   specified	wordorder.     Valid	wordorders    are
     SEED_BIG_ENDIAN  or SEED_LITTLE_ENDIAN.  If this function is
     not called, it will be set	 appropriately	by  the	 function
     get_my_wordorder().   It  is  STRONGLY ENCOURAGED to use the
     same wordorder for	the header and data portions of	 MiniSEED
     records.  The function returns the	specified wordorder.


     extern int	set_data_wordorder
	(int	    wordorder)	   /* desired wordorder	of MiniSEED data.*/

     The function set_data_wordorder() will set	the desired  wor-
     dorder  for  the  data  of	 created  MiniSEED records to the
     specified wordorder.  Valid wordorders  are  SEED_BIG_ENDIAN
     or	 SEED_LITTLE_ENDIAN.   If this function	is not called, it
     will    be	   set	  appropriately	   by	 the	 function
     get_my_wordorder().   It  is  STRONGLY ENCOURAGED to use the
     same wordorder for	the header and data portions of	 MiniSEED
     records.  The function returns the	specified wordorder.


MINISEED READ ROUTINES
     extern int	read_ms
	(DATA_HDR   **phdr,	   /* pointer to pointer to DATA_HDR. */
	 void  *data_buffer,  /* pointer to output data	buffer.	 */
	 int	    max_num_points,	/* max # data points to	return.*/
	 FILE  *fp);	      /* FILE pointer for input	file.	      */

     The function read_ms will read the	next MiniSEED  record  in
     the  specified file, parse	the MiniSEED record header into	a
     DATA_HDR structure, unpack	 the  data  in	the  record,  and
     return at most max_num_pts	in the specified buffer.  The ptr
     *phdr will	be set to point	to a malloc-ed DATA_HDR	structure
     that  contains  the  pertinent  information  in the MiniSEED
     header, and should	be used	as an argument to f1ee	when  you
     are  finished  with the DATA_HDR.	Currently STEIM1, STEIM2,
     INT_16, INT_24, and INT_32	 datatypes  are	 supported.   The
     function  returns	the  number  of	 points	 returned  in the
     buffer, or	a negative  value  on  error.	If  the	 MiniSEED
     record  contains  more  than  max_num_pts	data  values, the
     remaining data points will	be discarded.


     extern int	read_ms_record



BDSN		  Last change: 25 October 1996			3






Introduction to	Library	Functions			 QLIB2(3)



	(DATA_HDR   **phdr,	   /* pointer to pointer to DATA_HDR. */
	 char  **pbuf,	      /* ptr to	buf ptr	for MiniSEED record.  */
	 FILE  *fp);	      /* FILE pointer for input	file.	      */

     The function read_ms_record  will	read  the  next	 MiniSEED
     record  in	 the  specified	 file,	parse the MiniSEED record
     header into a DATA_HDR structure, and return the raw  record
     in	 the  buffer  pointed  to  by *pbuf.  If *pbuf is NULL,	a
     buffer of sufficient size for the MiniSEED	 record	 will  be
     allocated	for  you, and *pbuf will be set	to the address of
     the buffer.  The ptr  *phdr  will	be  set	 to  point  to	a
     malloc-ed	DATA_HDR  structure  that  contains the	pertinent
     information in the	MiniSEED header, and should be used as an
     argument  to  free_data_hdr  when	you are	finished with the
     DATA_HDR.	The function returns the MiniSEED record size  as
     the  function  value,  EOF	 on  reaching EOF, or MS_ERROR on
     error.


     void free_data_hdr	(DATA_HDR *hdr)

     The function free_data_hdr	is used	to deallocate  all  space
     allocated for a DATA_HDR structure.  This function	should be
     used instead of free() since it will properly free	all allo-
     cated  data for blockettes	as well	as the DATA_HDR	structure
     itself.


MINISEED WRITE ROUTINES
     The following functions are  useful  for  creating	 MiniSEED
     records.


     DATA_HDR new_data_hdr ()

     The function new_data_hdr will create and initialize  a  new
     DATA_HDR  structure.  The structure elements that are filled
     in	are:	   hdr_wordorder      data_wordorder based on the
     preferred	 setting   set	 by  functions	get_my_wordorder,
     set_hdr_wordorder,	or set_data_wordorder.	You are	responsi-
     ble  for  setting	all other required values in the DATA_HDR
     structure.


     extern int	ms_pack_data
	(DATA_HDR   *hdr,	   /* ptr to initial data hdr.	      */
	 BS	    *init_bs, /* ptr to	onetime	blockettes.	 */
	 int	    num_samples,   /* number of	data samples.	      */
	 int	    *data,	   /* ptr to data buffer.	      */
	 int	    *n_blocks,	   /* #	MiniSEED blocks	(returned).   */
	 char  **pp_ms,	 /* ptr	**MiniSEED (returned).	    */
	 int	    ms_len,	   /* MiniSEED buffer len (if supplied).*/



BDSN		  Last change: 25 October 1996			4






Introduction to	Library	Functions			 QLIB2(3)



	 char  *p_errmsg)     /* ptr to	error msg buffer.	 */

     The function ms_pack_data will create MiniSEED records in	a
     memory buffer for the specified number of data samples.  The
     blocksize and MiniSEED data encoding must	be  specified  in
     the   blksize  and	 data_type  fields  respectively  in  the
     DATA_HDR structure.  All other required  attributes  of  the
     MiniSEED  records	(station,  channel,  network, start_time,
     sample_reate, etc)	must be	specified in the DATA_HDR  struc-
     ture.

     If	the ptr	*pp_ms is NULL,	the  ms_pack_data  function  will
     allocate  a  buffer  of  sufficient size to hold the created
     MiniSEED records, return the ptr to the  buffer  in  *pp_ms,
     and  ignore  the  value of	ms_len.	 If the	ptr *pp_ms is not
     NULL, it is assumed to be a buffer	of size	ms_len bytes into
     which the function	will write the MiniSEED	records.

     The function sets the  variable  *n_blocks	 to  contain  the
     number  of	 MiniSEED  records that	were created The function
     returns the total number of initial data samples  that  were
     packed  into  the	MiniSEED  records, which should	equal the
     total num_samples if there	was sufficient room in	the  Min-
     iSEED buffer for the required number of MiniSEED blocks.  If
     the function value	is less	than num_samples, you can  output
     the  created  MiniSEED  records,  adjust  the  DATA_HDR time
     value, and	call the function again	with an	adjusted  ptr  to
     the input data buffer and adjusted	num_samples.


TIME ROUTINES
     All of the	following time functions  properly  handle  leap-
     seconds provided a	leapsecond table is available on the sys-
     tem.  By default, the leapseconds table is	assumed	to be  in
     /usr/local/lib/leapseconds,  but  this can	be changed during
     compilation of qlib2.  In addition, the environment variable
     LEAPSECONDS  can be used to explicitly set	the pathname of	a
     leapsecond	table.


     INT_TIME ext_to_int (EXT_TIME et)

     The function ext_to_int converts an EXT_TIME structure  into
     an	INT_TIME structure, and	returns	as its value the INT_TIME
     structure.


     EXT_TIME int_to_ext (INT_TIME it)

     The function ext_to_int converts an INT_TIME structure  into
     an	EXT_TIME structure, and	returns	as its value the EXT_TIME
     structure.



BDSN		  Last change: 25 October 1996			5






Introduction to	Library	Functions			 QLIB2(3)



     void dy_to_mdy (int doy, int year,	int *month, int	*mday)

     The function dy_to_mdy converts a day_of_year and year  into
     a numeric month and day_of_month value, and stores	the month
     and day_of_month in the locations pointed to by the final	2
     arguments.


     int mdy_to_doy (int month,	int day, int year)

     The function mdy_to_doy computes  the  day_of_year	 for  the
     specified	month, day, and	year, and returns the day_of_year
     as	the function value.


     INT_TIME normalize_time (INT_TIME it)

     The function normalize_int	will normalize an INT_TIME struc-
     ture  and	return	the  normalize	structure as the function
     value.  A date is considered "normalized" if all of its date
     fields  fall  within  the valid ranges for	the year, seconds
     and fractional seconds.  If any component	exceeds	 the  the
     bounds  for  that	component  (eg	if  the	f1actional second
     exceeds 1 second),	it will	be "normalized"	by adding or sub-
     tracting  the  appropriate	 number	to bring it within range,
     and then adjusting	the next higher	field to compenstate  for
     the normalization.

     The structure is normalized in the	following order:  minute,
     hour,  day_of_year, year, and second.  Once the second field
     has been normalized, the minute, hour, day, month,	and  year
     are  normalized  again.   Once the	date has been normalized,
     the month and day_of_month	are calculated for the normalized
     field.

     This function can be used to compute a  new  normalize  time
     after  values  have  been	added  to field(s) of an INT_TIME
     structure.


     EXT_TIME normalize_ext (EXT_TIME et)

     The function normalize_ext	will normalize an EXT_TIME struc-
     ture  and	return	the  normalize	structure as the function
     value.  A date is considered "normalized" if all of its date
     fields  fall  within  the	valid ranges for the year, month,
     day, hour,	minute,	and seconds and	f1actional  seconds.   If
     any  component exceeds the	the bounds for that component (eg
     if	the minute is <	0 or > 59), it will  be	 "normalized"  by
     adding  or	 subtracting  the  appropriate number to bring it
     within range, and then adjusting the next	higher	field  to
     compenstate for the normalization.



BDSN		  Last change: 25 October 1996			6






Introduction to	Library	Functions			 QLIB2(3)



     The structure is normalized in the	following order:  minute,
     hour,  day_of_year, year, and second.  Once the second field
     has been normalized, the minute, hour, day, month,	and  year
     are  normalized  again.   Once the	date has been normalized,
     the month and day_of_month	are calculated for the normalized
     field.

     This function can be used to compute a  new  normalize  time
     after  values  have  been	added  to field(s) of an EXT_TIME
     structure.	 Note that the month and day_of_month  field  are
     never  normalized,	 but merely recomputed after the date has
     been normalized.	Therefore,  NEVER  change  the	month  or
     day_of_month field.


     INT_TIME add_time (INT_TIME it, int seconds, int usecs)

     The function add_time is used to add the specified	number of
     seconds  and  usecs to an INT_TIME	structure.  The	resulting
     normalize INT_TIME	structure is  returned	as  the	 function
     value.   The  seconds  and	 usecs	may be either positive or
     negative (to add or subtract time).  The  seconds	are  con-
     verted  into  usecs,  the total number of usecs are added to
     the structure, and	the  normalized	 resulting  structure  is
     returned.


     INT_TIME add_dtime	(INT_TIME it, double usecs)

     The function add_dtime is used to add the	specified  number
     of	 usecs to an INT_TIME structure.  The resulting	normalize
     INT_TIME structure	is returned as the function  value.   The
     usecs may be either positive or negative (to add or subtract
     time).  The usecs are added to the	structure, and	the  nor-
     malized resulting structure is returned.


     time_interval2 (int n, int	rate, int rate_mult, int *second, int *usecs)

     The function time_interval2 computes the time interval for	n
     points  at	 the  specified	 sample_rate and sample_rate_mult
     (taken from the data_hdr structure	and defined by SEED).  It
     returns the number	of seconds and usecs for that interval in
     the locations pointed to by the last 2 arguments.	The  rate
     is	  positive   for   samples_per_second  and  negative  for
     seconds_per_sample.


     double dsamples_in_time2 (int rate, int rate_mult,	int usecs)


     The function dsamples_in_time2 computes the  the  number  of



BDSN		  Last change: 25 October 1996			7






Introduction to	Library	Functions			 QLIB2(3)



     samples  that span	the specified time in usecs at the speci-
     fied sample rate.	Rate and rate_mult  are	 taken	from  the
     DATA_HDR  sample_rate  and	 sample_rate_mult  fields respec-
     tively and	are defined by SEED.  For example, at sample rate
     100  (rate=100, rate_mult=1, for 100 samples per second) the
     span of 1,500,000 usecs (1.5 seconds) would span 100.0  sam-
     ples of data.


     double tdiff (INT_TIME it1, INT_TIME it2)

     The function tdiff	computes the time difference  of  (it1	-
     it2)  in usecs, and returns the number of usecs.  It returns
     -DHUGE or +DHUGE if the returned value is in danger of over-
     flow.


     char *time_to_str (INT_TIME it, int fmt)

     The function time_to_str generates	a printable timestamp for
     the  specified  time in one of several format.  The value of
     format and	the resulting string format are	summarized below:

	  0    JULIAN_FMT:    yyyy.doy hh:mm:ss.ffff
	  1    JULIAN_FMT_1:  yyyy.doy,hh:mm:ss.ffff
	  2    MONTH_FMT:     yyyy.mm.dd hh:mm:ss.ffff
	  3    MONTH_FMT_1:   yyyy.mm.dd,hh:mm:ss.ffff
	  4    JULIANC_FMT:   yyyy,doy hh:mm:ss.ffff
	  5    JULIANC_FMT_1: yyyy,doy,hh:mm:ss.ffff
	  6    MONTHS_FMT:    yyyy/mm/dd hh:mm:ss.ffff
	  7    MONTHS_FMT_1:  yyyy/mm/dd,hh:mm:ss.ffff


     INT_TIME *parse_date(char *str)
     The function parse_date will parse	a date string and  return
     a	 POINTER   to	a  static  INT_TIME  structure	with  the
     corresponding date/time, or a NULL	pointer	on error.  If the
     pointer  is  non-NULL  the	 value pointed to by the INT_TIME
     pointer should be copied before the next call to parse_date.


     time_t unix_time_from_ext_time (EXT_TIME et)

     The function unix_time_from_ext_time returns a  Unix  time_t
     timestamp for the specified EXT_TIME.


     time_t unix_time_from_int_time (INT_TIME it)

     The function unix_time_from_ext_time returns a  Unix  time_t
     timestamp for the specified INT_TIME.




BDSN		  Last change: 25 October 1996			8






Introduction to	Library	Functions			 QLIB2(3)



     INT_TIME int_time_from_timeval (struct timeval *tv)

     The function int_time_from_timeval	converts  a  Unix  struct
     timeval  pointed  to  by  tv into an INT_TIME structure, and
     returns the INT_TIME structure.

FORTRAN	DATA STRUCTURES
     The following fortran data	structures are used with the for-
     tran version of the qlib2 routines	in qlib2.inc:

     c
     c Parameters for SEED data	header data structures
     c
	  integer DH_STATION_LEN, DH_CHANNEL_LEN, DH_LOCATION_LEN,
	  1	    DH_NETWORK_LEN
	  parameter (
	  1	    DH_STATION_LEN = 6,
	  2	    DH_CHANNEL_LEN = 4,
	  3	    DH_LOCATION_LEN	= 3,
	  4	    DH_NETWORK_LEN = 3 )
     c
     c Date/Time data structure	used for time calculations.
     c
	  structure /INT_TIME/
	       integer year
	       integer second
	       integer usec
	  end structure
     c
     c Date/Time data structure	used for external interface.
     c
	  structure /EXT_TIME/
	       integer year
	       integer doy
	       integer month
	       integer day
	       integer hour
	       integer minute
	       integer second
	       integer usec
	  end structure
     c
     c Data Header structure containing	data from SEED Fixed Data Header
     c WARNING - this assumes pointers take the	same space as an integer.
     c
	  structure /DATA_HDR/
	       integer seq_no
	       character*(DH_STATION_LEN) station_id
	       character*(DH_LOCATION_LEN) location_id
	       character*(DH_CHANNEL_LEN) channel_id
	       character*(DH_NETWORK_LEN) network_id
	       record /INT_TIME/ begtime



BDSN		  Last change: 25 October 1996			9






Introduction to	Library	Functions			 QLIB2(3)



	       record /INT_TIME/ endtime
	       record /INT_TIME/ hdrtime
	       integer num_samples
	       integer num_data_frames
	       integer sample_rate
	       integer sample_rate_mult
	       integer num_blockettes
	       integer num_ticks_correction
	       integer first_data
	       integer first_blockette
	       integer pblockettes
	       integer data_type
	       integer blksize
	       character activity_flags
	       character io_flags
	       character data_quality_flags
	       character hdr_wordorder
	       character data_wordorder
	       character record_type
	       character cextra(2)
	       integer x0
	       integer xn
	       integer xm1
	       integer xm2
	       integer extra(1)
	  end structure


FORTRAN	GENERAL	ROUTINES
     integer function f_get_my_wordorder()

     The function f_get_my_wordorder() will  determine	the  wor-
     dorder   of   the	 computer,   set  the  external	 variable
     my_wordorder to the computer's  wordorder,	 and  return  the
     wordorder	 as   the   function  value.   If  the	functions
     set_hdr_wordorder	and  set_data_wordorder	 have  not   been
     called  to	 explicitly  set  the  desired	hdr_wordorder and
     data_wordorder for	creating MiniSEED data,	 these	functions
     will  be  initialized appropriately.  Depending on	how qlib2
     was compiled,  these  will	 either	 be  initialized  to  the
     computer's	 wordorder  OR	to  a  fixed  wordorder	 such  as
     SEED_BIG_ENDIAN.  This function should be called before  any
     other  qlib2 function.  If	the user does not call this func-
     tion, it will be called by	the required qlib2 functions.


     integer function f_set_hdr_wordorder
	  integer wordorder

     The function f_set_hdr_wordorder()	will set the desired wor-
     dorder  for  the fixed header of created MiniSEED records to
     the   specified	wordorder.     Valid	wordorders    are



BDSN		  Last change: 25 October 1996		       10






Introduction to	Library	Functions			 QLIB2(3)



     SEED_BIG_ENDIAN  or SEED_LITTLE_ENDIAN.  If this function is
     not called, it will be set	 appropriately	by  the	 function
     f_get_my_wordorder().   It	is STRONGLY ENCOURAGED to use the
     same wordorder for	the header and data portions of	 MiniSEED
     records.  The function returns the	specified wordorder.


     extern int	f_set_data_wordorder
	  integer wordorder

     The function f_set_data_wordorder()  will	set  the  desired
     wordorder	for  the  data of created MiniSEED records to the
     specified wordorder.  Valid wordorders  are  SEED_BIG_ENDIAN
     or	 SEED_LITTLE_ENDIAN.   If this function	is not called, it
     will    be	   set	  appropriately	   by	 the	 function
     f_get_my_wordorder().   It	is STRONGLY ENCOURAGED to use the
     same wordorder for	the header and data portions of	 MiniSEED
     records.


FORTRAN	MINISEED READ ROUTINES
     The function f_read_ms requires an	argument fp  which  is	a
     file  handle  that	 is returned by	ifopen function.  See the
     fio routines for fortran-callable routines	 for  C	 buffered
     and unbufferd I/O.


     integer function f_read_ms	(hdr, data_buffer, maxpts, fp)
	  record /DATA_HDR/ hdr
	  integer maxpts
	  integer data(maxpts)
	  integer fp

     The function f_read_ms will read the next MiniSEED	record in
     the  specified  file,  and	return at most max_num_pts in the
     specified buffer.	The DATA_HDR record  will  be  filled  in
     with  all	of  the	appropriate information	from the MiniSEED
     header (with the exception	of any blockettes which	will  not
     be	 returned).   The  function  returns the number	of points
     returned in the buffer, or	a negative value  on  error.   If
     the  MiniSEED  record  contains  more  than max_num_pts data
     values, the remaining data	points will be discarded.


     integer function f_init_data_hdr (hdr)
	  record /DATA_HDR/ hdr

     The function f_init_data_hdr will	initialize  the	 DATA_HDR
     function to the appropriate values.  Most fields will be set
     to	 zero,	but  the   hdr_wordorder,   data_wordorder,   and
     record_type  will	be set appropriately.  If you are calling
     this function to re-initialize a  previously  used	 DATA_HDR



BDSN		  Last change: 25 October 1996		       11






Introduction to	Library	Functions			 QLIB2(3)



     structure,	 you should first call f_delete_blockette(hdr,-1)
     to	free any blockettes, since this	function  does	NOT  free
     any blockettes when initializing the DATA_HDR structure.



     integer function f_delete_blockette (hdr, n)
	  record /DATA_HDR/ hdr
	  integer n

     The function f_delete_blockette will delete  all  occurances
     of	 blockette  n  in the DATA_HDR's blockette list.  If n ==
     -1, all blockettes	 will  be  deleted  from  the  DATA_HDR's
     blockette	   list.      Fortran	  users	   should    call
     f_delete_blockette(hdr,-1)	after they have	finished  reading
     EACH   DATA_HDR   or   after   they   have	  finished   with
     f_ms_pack_data, since each	of these functions may add block-
     ettes  to	the DATA_HDR structure which will not be properly
     freed byt the f_init_data_hdr function.


FORTRAN	MINISEED WRITE ROUTINES
     The following functions are  useful  for  creating	 MiniSEED
     records.


     integer function f_ms_pack_data (hdr, num_samples,	data, n_blocks,	mseed, ms_len)
	  record /DATA_HDR/ hdr
	  integer num_samples
	  integer data(num_samples)
	  integer n_blocks
	  character mseed[ms_len]
	  integer ms_len

     The function f_ms_pack_data will pack num_samples of integer
     data  into	 the  required	number of MiniSEED records in the
     mseed string, and return  the  number  of	MiniSEED  records
     created  in  n_blocks.   The  function returns the	number of
     data samples packed into the MiniSEED records.  The DATA_HDR
     should  first  be initialized with	f_init_data_hdr, and must
     then be initialized with the station,channel,net, and  loca-
     tion information, the starting time of the	first sample, the
     sample rate, the desired blksize for the  MiniSEED	 records,
     and  the  desired data format.  If	the mseed buffer does not
     contain sufficient	space for all  of  the	MiniSEED  records
     required  to  hold	 num_samples of	data, not all of the data
     will be packed into MiniSEED.  The	caller should  check  the
     number of samples packed against the num_samples.

     The resulting MiniSEED records may	 be  written  to  a  file
     using  the	 fio routines for fortran-callable routines for	C
     buffered and unbufferd I/O.



BDSN		  Last change: 25 October 1996		       12






Introduction to	Library	Functions			 QLIB2(3)



FORTRAN	TIME ROUTINES
     subroutine	f_add_time (it,	seconds, usecs,	ot)
	  record /INT_TIME/ it
	  integer seconds
	  integer usec
	  record /INT_TIME/ ot

     The subroutine f_add_time	is  used  to  add  the	specified
     number  of	 seconds and usecs to an INT_TIME structure.  The
     resulting normalize INT_TIME structure is	returned  as  the
     value  ot.	  The seconds and usecs	may be either positive or
     negative (to add or subtract time).  The  seconds	are  con-
     verted  into  usecs,  the total number of usecs are added to
     the structure, and	the  normalized	 resulting  structure  is
     returned.


     subroutine	f_add_dtime (it, usecs,	ot)
	  record /INT_TIME/ it
	  integer seconds
	  double precision usec
	  record /INT_TIME/ ot

     The subroutine f_add_dtime	is  used  to  add  the	specified
     number  of	 usecs	to  an INT_TIME	structure.  The	resulting
     normalize INT_TIME	structure is returned as  the  value  ot.
     The usecs may be either positive or negative (to add or sub-
     tract time).  The usecs are added to the structure, and  the
     normalized	resulting structure is returned.


     subroutine	f_time_interval2 (n, rate, rate_mult, seconds, usecs)
	  integer n
	  integer rate
	  integer rate_mult
	  integer seconds
	  integer usecs

     The function f_time_interval2 computes the	time spanned by	n
     samples  of  data	at  the	 specified  data  rate.	 Rate and
     rate_mult	are  taken  from  the  DATA_HDR	 sample_rate  and
     sample_rate_mult field.  The resulting time span is returned
     in	the seconds and	usecs variables.  For example,	150  sam-
     ples  at sample rate 100 (100 samples per second) would span
     1 second and 500000 usecs (1.5 seconds).


     double precision function f_dsamples_in_time2 (rate, rate_mult, usecs)
	  integer rate
	  integer rate_mult
	  integer usecs




BDSN		  Last change: 25 October 1996		       13






Introduction to	Library	Functions			 QLIB2(3)



     The function f_dsamples_in_time2 computes the the number  of
     samples  that span	the specified time in usecs at the speci-
     fied sample rate.	Rate and rate_mult  are	 taken	from  the
     DATA_HDR  sample_rate  and	 sample_rate_mult  fields respec-
     tively and	are defined by SEED.  For example, at sample rate
     100  (rate=100, rate_mult=1, for 100 samples per second) the
     span of 1,500,000 usecs (1.5 seconds) would span 100.0  sam-
     ples of data.


     double precision function f_tdiff (it1, it2)
	  record /INT_TIME/ it1
	  record /INT_TIME/ it2

     The function f_tdiff computes the time difference of (it1	-
     it2)  in usecs, and returns the number of usecs.  It returns
     -DHUGE or +DHUGE if the returned value is in danger of over-
     flow.


     subroutine	f_dy_to_mdy (doy, year,	month, mday)
	  integer doy
	  integer year
	  integer month
	  integer mday

     The subroutine f_dy_to_mdy	takes  a  doy  (day_of_year)  and
     year and computes the month and day_of_month for that day.


     integer function f_mdy_to_doy (month, day,	year)
	  integer month
	  integer day
	  integer year

     The subroutine f_mdy_to_doy takes month,  day_of_month,  and
     year and computes the day_of_year for that	date.  It returns
     the day_of_year as	the function value.


     subroutine	f_ext_to_int (et, it)
	  record /EXT_TIME/ et
	  record /EXT_TIME/ it

     The subroutine f_ext_to_int converts an  EXT_TIME	structure
     into  an INT_TIME structure, and returns the INT_TIME struc-
     ture in the second	argument.


     subroutine	f_int_to_ext (it, et)
	  record /EXT_TIME/ it
	  record /EXT_TIME/ et



BDSN		  Last change: 25 October 1996		       14






Introduction to	Library	Functions			 QLIB2(3)



     The subroutine f_int_to_ext converts an  INT_TIME	structure
     into  an EXT_TIME structure, and returns the EXT_TIME struc-
     ture in the second	argument.


     subroutine	f_time_to_str (it, fmt,	str)
	  record /INT_TIME/ it
	  integer fmt
	  character*(*)	str

     The subroutine f_time_to_str generates a printable	timestamp
     for  the specified	time in	one of several format.	The value
     of	format and the resulting  string  format  are  summarized
     below:

	  0    JULIAN_FMT:    yyyy.doy hh:mm:ss.ffff
	  1    JULIAN_FMT_1:  yyyy.doy,hh:mm:ss.ffff
	  2    MONTH_FMT:     yyyy.mm.dd hh:mm:ss.ffff
	  3    MONTH_FMT_1:   yyyy.mm.dd,hh:mm:ss.ffff
	  4    JULIANC_FMT:   yyyy,doy hh:mm:ss.ffff
	  5    JULIANC_FMT_1: yyyy,doy,hh:mm:ss.ffff
	  6    MONTHS_FMT:    yyyy/mm/dd hh:mm:ss.ffff
	  7    MONTHS_FMT_1:  yyyy/mm/dd,hh:mm:ss.ffff
     The timestamp string is returned in the last argument str.


     integer function f_parse_date(it, str)

     The function f_parse_date will parse a date string	passed in
     the  str and return the corresponding date/time value in the
     INT_TIME structure	of the first argument.	If  the	 function
     is	 successful  it	 returns 1 as the function value.  If the
     function was unsuccessful in parsing the  date/time  string,
     it	returns	0 as the function value.


NOTES
     The time functions	make use of the	leapseconds file to  tell
     them  when	leapseconds have (and will) occur.  The	format of
     the leapseconds file is compatible	with that of Unix systems
     that  have	 leapseconds  file.   The  file	 must  either  be
     installed as /usr/local/lib/leapseconds or	 you  should  set
     the  environment variable LEAPSECONDS to the pathname of the
     leapseconds file to use.  If (for some reason)  you  do  not
     wish  to  use a leapseconds file, you may set LEAPSECONDS to
     /dev/null,	which will suppress any	error  messages	 about	a
     missing leapseconds file.








BDSN		  Last change: 25 October 1996		       15



