diff --git a/fixhdr/LibTrace.py b/fixhdr/LibTrace.py
index 0aa5923ae379c056cc8dcd5efc5f3132d755ce4f..eebf3dbde0aa6a7350f17e9fe6b68c70ae8e5a49 100755
--- a/fixhdr/LibTrace.py
+++ b/fixhdr/LibTrace.py
@@ -4,8 +4,8 @@
 # LibTrace
 #
 # classes for Segy & Mseed
-#	identify file types
-#	read mseed headers
+#    identify file types
+#    read mseed headers
 #
 # author: bcb
 
@@ -24,8 +24,8 @@
 # Author: bcb
 #
 # MSEED
-#	created UbytetoStr to decompose Ubyte to bit fields
-#	modified blks 200, 201, 300, 310, 320, 390 and fixhdr to utilize
+#    created UbytetoStr to decompose Ubyte to bit fields
+#    modified blks 200, 201, 300, 310, 320, 390 and fixhdr to utilize
 
 ##########################
 # 2004.295
@@ -52,8 +52,8 @@
 # added check for endianess in Mseed & Segy classes, self.ByteOrder
 # changed all unpack formats to reflect above change in Mseed & Segy classes
 # NOTE: for mseed it is possible to have mixed endianess (e.g. little-endian headers
-# 		and big-endian data). At this time, this library does not handle data and makes
-#		the determination of endianess based soley on the header.
+#         and big-endian data). At this time, this library does not handle data and makes
+#        the determination of endianess based soley on the header.
 
 ##########################
 # 2005.138
@@ -114,1538 +114,1628 @@
 #
 # corrected typo from DHQaul to DHQual
 # added local variables to class Mseed
-
-import os, string, sys, struct, exceptions, time
+################################################################
+#
+# modification
+# version: 2019.025
+# author: Lan Dam
+# convert to py3
+# Bug fix: In Writeblk200/201/300/310/320/390/395/500 when unpack inblk to
+#   variables with time (Year, Day, Hour, Min, Sec, junk, Micro)
+
+import os, string, sys, struct, time
 SPACE = " "
 
-#VERSION = "2008.204"
+#VERSION = "2019.025"
 
 class futils:
-	"""
-	file utilities class
-	"""
-	def __init__(self,infile):
-		self.infile = open(infile, 'r+b')
+    """
+    file utilities class
+    """
+    def __init__(self,infile):
+        self.infile = open(infile, 'r+b')
 
-	def close(self):
-		self.infile.close()
+    def close(self):
+        self.infile.close()
 
-	def where(self):
-		return self.infile.tell()
+    def where(self):
+        return self.infile.tell()
 
 #########################################################
 class FixedHeader:
-	"""
-	mseed fixhdr 
-	"""
-	#first 20char
-	textblk=timeblk=sampblk=miscblk=[]
-	textblk=[]
-	Serial=DHQual=Res=Stat=Chan=Loc=Net=None
-	# 20:30
-	timeblk=[]
-	Year=Day=Hour=Min=Sec=Micro=None
-	# 30:36
-	sampblk=[]
-	NumSamp=SampFact=SampMult=None
-	# 36:48
-	miscblk=[]
-	act=io=DataDHQualFL=numblock=timcorr=bdata=bbblock=None
+    """
+    mseed fixhdr 
+    """
+    #first 20char
+    textblk=timeblk=sampblk=miscblk=[]
+    textblk=[]
+    Serial=DHQual=Res=Stat=Chan=Loc=Net=None
+    # 20:30
+    timeblk=[]
+    Year=Day=Hour=Min=Sec=Micro=None
+    # 30:36
+    sampblk=[]
+    NumSamp=SampFact=SampMult=None
+    # 36:48
+    miscblk=[]
+    act=io=DataDHQualFL=numblock=timcorr=bdata=bbblock=None
 #########################################################
 class Mseed(futils):
-	def __init__(self, infile):
-		"""
-		initialize file, determine byteorder, sizes, time, and load first fixed header
-		"""
-		self.type=self.rate=None
-		try:
-			futils.__init__(self,infile)
-			#local variable to class
-			self.infileseek=self.infile.seek
-			self.infilewrite=self.infile.write
-			self.infileread=self.infile.read
-			self.sunpack=struct.unpack
-			self.spack=struct.pack
-			
-			self.byteorder = self.ByteOrder()
-			if self.byteorder != "unknown":
-				#otherwise it might be mseed
-				self.type = "mseed"
-				# read 1st fixed header in file
-				hdrs=self.fixedhdr()
-				(self.filesize,self.blksize)=self.sizes()
-				(self.numblocks, odd_size)=divmod(self.filesize,self.blksize)
-				if odd_size:
-					pass
-				# starttime of trace
-				self.time = string.join(map(str, (self.FH.Year, self.FH.Day, self.FH.Hour, \
-								  self.FH.Min, self.FH.Sec)), ":")
-		except:
-			pass
+    def __init__(self, infile):
+        """
+        initialize file, determine byteorder, sizes, time, and load first fixed header
+        """
+        self.type=self.rate=None
+        try:
+            futils.__init__(self,infile)
+            #local variable to class
+            self.infileseek=self.infile.seek
+            self.infilewrite=self.infile.write
+            self.infileread=self.infile.read
+            self.sunpack=struct.unpack
+            self.spack=struct.pack
+
+            self.byteorder = self.ByteOrder()
+            if self.byteorder != "unknown":
+                #otherwise it might be mseed
+                self.type = "mseed"
+                # read 1st fixed header in file
+                hdrs=self.fixedhdr()
+                (self.filesize,self.blksize)=self.sizes()
+                (self.numblocks, odd_size)=divmod(self.filesize,self.blksize)
+                if odd_size:
+                    pass
+                # starttime of trace
+                self.time = ":".join(map(str, (self.FH.Year, self.FH.Day,
+                                               self.FH.Hour, self.FH.Min,
+                                               self.FH.Sec)))
+        except Exception as e:
+            pass
 
 #########################################################
-	def isMseed(self) :
-		"""
-		determines if processed file is mseed (return 1) or unknown type (return 0)
-		"""
-		#if we don't know byteorder it must not be mseed
-		if self.byteorder == "unknown": return 0
-		else: return 1
+    def isMseed(self) :
+        """
+        determines if processed file is mseed (return 1) or unknown type (return 0)
+        """
+        #if we don't know byteorder it must not be mseed
+        if self.byteorder == "unknown": return 0
+        else: return 1
 
 #########################################################
-	def idhdr(self):
-		"""
-		trace id info
-		"""
-		return self.type, self.FH.Stat, self.FH.Chan, self.FH.Loc, self.FH.Net, self.time, self.rate
+    def idhdr(self):
+        """
+        trace id info
+        """
+        return self.type, self.FH.Stat, self.FH.Chan, self.FH.Loc, self.FH.Net, self.time, self.rate
 
 #########################################################
-	def FirstLastTime(self):
-		"""
-		returns first and last block times in epoch 
-		"""
-		try :
-			#get first fixed header and calculate beginning epoch
-			btime_str = time.strptime(self.time, '%Y:%j:%H:%M:%S')
-			bepoch = time.mktime(btime_str) + (self.FH.Micro * 0.0001)
-			#figure out where the end of the file is and read the last fixed header
-			# and calculate eepoch
-			(numblocks, odd_size)=divmod(self.filesize, self.blksize)
-			self.infileseek(-self.blksize,2)
-			loc = self.infile.tell()
-			etime=self.btime2time(loc)
-			etime_str = time.strptime(etime, '%Y:%j:%H:%M:%S')
-			eepoch = time.mktime(etime_str) + (self.FH.Micro * 0.0001)
-	# 
-			return bepoch, eepoch
-		except StandardError, e:
-			return e
+    def FirstLastTime(self):
+        """
+        returns first and last block times in epoch 
+        """
+        try :
+            #get first fixed header and calculate beginning epoch
+            btime_str = time.strptime(self.time, '%Y:%j:%H:%M:%S')
+            bepoch = time.mktime(btime_str) + (self.FH.Micro * 0.0001)
+            #figure out where the end of the file is and read the last fixed header
+            # and calculate eepoch
+            (numblocks, odd_size)=divmod(self.filesize, self.blksize)
+            self.infileseek(-self.blksize,2)
+            loc = self.infile.tell()
+            etime=self.btime2time(loc)
+            etime_str = time.strptime(etime, '%Y:%j:%H:%M:%S')
+            eepoch = time.mktime(etime_str) + (self.FH.Micro * 0.0001)
+    # 
+            return bepoch, eepoch
+        except Exception as e:
+            return e
 #########################################################
-	def tracelength(self):
-		"""
-		returns tracelength in seconds
-		"""
-		try :
-			#get first fixed header and calculate beginning epoch
-			(bepoch, eepoch)=self.FirstLastTime()
-
-#			#here I have to get the last few samples and calculate how much time is accounted for
-			self.infileseek(-self.blksize+30,2)
-			sampblock=self.infileread(2)
-			fmtstr = self.fmt_order + "H"
-			numsamp = self.sunpack(fmtstr, sampblock)[0]
-			lastsamples=(numsamp-1)/self.rate
-			return ((eepoch+lastsamples) - bepoch )
-		except:
-			pass
+    def tracelength(self):
+        """
+        returns tracelength in seconds
+        """
+        try :
+            #get first fixed header and calculate beginning epoch
+            (bepoch, eepoch)=self.FirstLastTime()
+
+#            #here I have to get the last few samples and calculate how much time is accounted for
+            self.infileseek(-self.blksize+30,2)
+            sampblock=self.infileread(2)
+            fmtstr = self.fmt_order + "H"
+            numsamp = self.sunpack(fmtstr, sampblock)[0]
+            lastsamples=(numsamp-1)/self.rate
+            return ((eepoch+lastsamples) - bepoch )
+        except Exception as e:
+            pass
 #########################################################
-	def btime2time(self, seekval=0) :
-		"""
-		reads file fixed header and returns time string from btime
-		"""
-		try :
-			hdrs=self.fixedhdr(seekval)
-			time = string.join(map(str, (self.FH.Year, self.FH.Day, self.FH.Hour, \
-								  self.FH.Min, self.FH.Sec)), ":")
-			return time
-		except:
-			pass
+    def btime2time(self, seekval=0) :
+        """
+        reads file fixed header and returns time string from btime
+        """
+        try :
+            hdrs=self.fixedhdr(seekval)
+            time = ":".join(map(str, (self.FH.Year, self.FH.Day, self.FH.Hour,
+                                      self.FH.Min, self.FH.Sec)))
+            return time
+        except Exception as e:
+            pass
 #########################################################
-	def idread(self, seekval=0) :
-		"""
-		read file as if it is mseed just pulling necessary info
-		from fixed header
-		"""
-		try :
-			hdrs=self.fixedhdr(seekval)
-
-			return self.FH.Stat, self.FH.Chan, self.FH.Loc, self.FH.Net,\
-			       self.rate, self.FH.Year, self.FH.Day, self.FH.Hour, self.FH.Min, self.FH.Sec, self.FH.Micro
-		except :
-			return
+    def idread(self, seekval=0) :
+        """
+        read file as if it is mseed just pulling necessary info
+        from fixed header
+        """
+        try :
+            hdrs=self.fixedhdr(seekval)
+
+            return self.FH.Stat, self.FH.Chan, self.FH.Loc, self.FH.Net,\
+                   self.rate, self.FH.Year, self.FH.Day, self.FH.Hour, self.FH.Min, self.FH.Sec, self.FH.Micro
+        except :
+            return
 #########################################################
-	def calcrate(self):
-		"""
-		this routine assumes that idread has been called first
-
-		calculate the sample rate of mseed data
-		If Sample rate factor > 0 and Sample rate Multiplier > 0,
-			rate = Sampfact X Sampmult
-		If Sample rate factor > 0 and Sample rate Multiplier < 0,
-			rate = -1 X Sampfact/Sampmult
-		If Sample rate factor < 0 and Sample rate Multiplier > 0,
-			rate = -1 X Sampmult/Sampfact
-		If Sample rate factor < 0 and Sample rate Multiplier < 0,
-			rate = 1/(Sampfact X Sampmult)
-		"""
-		sampFact=float(self.FH.SampFact)
-		sampMult=float(self.FH.SampMult)
-		if sampFact > 0 and sampMult > 0 :
-			rate = sampFact * sampMult
-		elif sampFact > 0 and sampMult < 0 :
-			rate = -1.0 * (sampFact/sampMult)
-		elif sampFact < 0 and sampMult > 0 :
-			rate = -1.0 * (sampMult/sampFact)
-		elif sampFact < 0 and sampMult < 0 :
-			rate = 1.0/(sampFact * sampMult)
-		else :
-			rate = sampFact
-		return rate
+    def calcrate(self):
+        """
+        this routine assumes that idread has been called first
+
+        calculate the sample rate of mseed data
+        If Sample rate factor > 0 and Sample rate Multiplier > 0,
+            rate = Sampfact X Sampmult
+        If Sample rate factor > 0 and Sample rate Multiplier < 0,
+            rate = -1 X Sampfact/Sampmult
+        If Sample rate factor < 0 and Sample rate Multiplier > 0,
+            rate = -1 X Sampmult/Sampfact
+        If Sample rate factor < 0 and Sample rate Multiplier < 0,
+            rate = 1/(Sampfact X Sampmult)
+        """
+        sampFact=float(self.FH.SampFact)
+        sampMult=float(self.FH.SampMult)
+        if sampFact > 0 and sampMult > 0 :
+            rate = sampFact * sampMult
+        elif sampFact > 0 and sampMult < 0 :
+            rate = -1.0 * (sampFact/sampMult)
+        elif sampFact < 0 and sampMult > 0 :
+            rate = -1.0 * (sampMult/sampFact)
+        elif sampFact < 0 and sampMult < 0 :
+            rate = 1.0/(sampFact * sampMult)
+        else :
+            rate = sampFact
+        return rate
 #########################################################
-	def ByteOrder(self, seekval=20) :
-		"""
-		read file as if it is mseed just pulling time info
-		from fixed header and determine if it makes sense unpacked
-		as big endian or little endian
-		"""
-		Order = "unknown"
-		try :
-			#seek to timeblock and read
-			self.infileseek(seekval)
-			timeblock=self.infileread(10)
-	#			timeblock=self.TraceBuffer[seekval:seekval+10]
-
-			#assume big endian
-			(Year, Day, Hour, Min, Sec, junk, Micro)=\
-			 self.sunpack('>HHBBBBH',timeblock)
-			#test if big endian read makes sense
-			if 1950 <= Year <= 2050 and \
-			   1 <= Day <= 366 and \
-			   0 <= Hour <= 23 and \
-			   0 <= Min <= 59 and \
-			   0 <= Sec <= 59:
-				Order = "big"
-				self.fmt_order = ">"
-			else:
-				#try little endian read
-				(Year, Day, Hour, Min, Sec, junk, Micro)=\
-				 self.sunpack('<HHBBBBH',timeblock)
-				#test if little endian read makes sense
-				if 1950 <= Year <= 2050 and \
-				   1 <= Day <= 366 and \
-				   0 <= Hour <= 23 and \
-				   0 <= Min <= 59 and \
-				   0 <= Sec <= 59:
-					Order = "little"
-					self.fmt_order = "<"
-		except :
-			pass
-
-		return Order
+    def ByteOrder(self, seekval=20) :
+        """
+        read file as if it is mseed just pulling time info
+        from fixed header and determine if it makes sense unpacked
+        as big endian or little endian
+        """
+        Order = "unknown"
+        try :
+            #seek to timeblock and read
+            self.infileseek(seekval)
+            timeblock=self.infileread(10)
+    #            timeblock=self.TraceBuffer[seekval:seekval+10]
+
+            #assume big endian
+            (Year, Day, Hour, Min, Sec, junk, Micro) = \
+                    self.sunpack('>HHBBBBH',timeblock)
+            #test if big endian read makes sense
+            if 1950 <= Year <= 2050 and \
+               1 <= Day <= 366 and \
+               0 <= Hour <= 23 and \
+               0 <= Min <= 59 and \
+               0 <= Sec <= 59:
+                Order = "big"
+                self.fmt_order = ">"
+            else:
+                #try little endian read
+                (Year, Day, Hour, Min, Sec, junk, Micro)=\
+                        self.sunpack('<HHBBBBH',timeblock)
+                #test if little endian read makes sense
+                if 1950 <= Year <= 2050 and \
+                   1 <= Day <= 366 and \
+                   0 <= Hour <= 23 and \
+                   0 <= Min <= 59 and \
+                   0 <= Sec <= 59:
+                    Order = "little"
+                    self.fmt_order = "<"
+        except :
+            pass
+
+        return Order
 #########################################################
-	def sizes(self, seekval=0):
-		"""
-		Finds Blockette 1000 and returns file size & Data Record Length
-		"""
-		try:
-			#determine file size
-			self.infileseek(0,2)
-			filesize=self.infile.tell()
-			#proceed to seekval
-			self.infileseek(seekval)
-			#self.infileseek(39)
-			#assign number of blockettes and offset to next blockette
-			nblock=self.FH.miscblk[3]
-			nextblock=self.FH.miscblk[6]
-			n=0
-			#find blockette 1000
-			while n < nblock:
-				self.infileseek(nextblock)
-				(blktype, newblock)=self.typenxt(nextblock)
-				if not blktype:
-					return None, None
-				if blktype == 1000:
-					(type, next, encode,order,length,res)=self.blk1000(nextblock)
-					return filesize, 2**length
-				nextblock=newblock
-				n+=1
-		except:
-			return None, None
+    def sizes(self, seekval=0):
+        """
+        Finds Blockette 1000 and returns file size & Data Record Length
+        """
+        try:
+            #determine file size
+            self.infileseek(0,2)
+            filesize=self.infile.tell()
+            #proceed to seekval
+            self.infileseek(seekval)
+            #self.infileseek(39)
+            #assign number of blockettes and offset to next blockette
+            nblock=self.FH.miscblk[3]
+            nextblock=self.FH.miscblk[6]
+            n=0
+            #find blockette 1000
+            while n < nblock:
+                self.infileseek(nextblock)
+                (blktype, newblock)=self.typenxt(nextblock)
+                if not blktype:
+                    return None, None
+                if blktype == 1000:
+                    (type, next, encode,order,length,res)=self.blk1000(nextblock)
+                    return filesize, 2**length
+                nextblock=newblock
+                n+=1
+        except Exception as e:
+            return None, None
 
 #########################################################
-	def typenxt(self, seekval=0):
-		"""
-		Reads first 4 bytes of blockette
-		Returns blockette type and next blockette offset
-		"""
-		try:
-			self.infileseek(seekval)
-			fmtstr = self.fmt_order + "HH"
-			(type, next)=self.sunpack(fmtstr, self.infileread(4))
-
-			#reset back to beginning of blockette
-			self.infileseek(-4,1)
-			return type, next
-		except:
-			return None, None
+    def typenxt(self, seekval=0):
+        """
+        Reads first 4 bytes of blockette
+        Returns blockette type and next blockette offset
+        """
+        try:
+            self.infileseek(seekval)
+            fmtstr = self.fmt_order + "HH"
+            (type, next)=self.sunpack(fmtstr, self.infileread(4))
+
+            #reset back to beginning of blockette
+            self.infileseek(-4,1)
+            return type, next
+        except Exception as e:
+            return None, None
 
 #########################################################
-	def setEndian(self, endianess=""):
-		"""
-		set format string for endian type
-		"""
-		if endianess == "big":
-			fmtorderstr=">"
-		elif endianess == "little":
-			fmtorderstr="<"
-		else:
-			fmtorderstr=self.fmt_order
-		return fmtorderstr
+    def setEndian(self, endianess=""):
+        """
+        set format string for endian type
+        """
+        if endianess == "big":
+            fmtorderstr=">"
+        elif endianess == "little":
+            fmtorderstr="<"
+        else:
+            fmtorderstr=self.fmt_order
+        return fmtorderstr
 
 #########################################################
 #
 # for blockette descriptions below
 # from SEED manual
 #
-# Field		nbits	Description
-# UBYTE		8		Unsigned quantity
-# BYTE		8		Two's complement signed quantity
-# UWORD		16		Unsigned quantity
-# WORD		16		Two's complement signed quantity
-# ULONG		32		Unsigned quantity
-# LONG		32		Two's complement signed quantity
-# CHAR*n		n*8		n characters, each 8 bit and each with
-# 						a 7-bit ASCII character (high bit always 0)
-# FLOAT		32		IEEE Floating point number
+# Field        nbits    Description
+# UBYTE        8        Unsigned quantity
+# BYTE        8        Two's complement signed quantity
+# UWORD        16        Unsigned quantity
+# WORD        16        Two's complement signed quantity
+# ULONG        32        Unsigned quantity
+# LONG        32        Two's complement signed quantity
+# CHAR*n        n*8        n characters, each 8 bit and each with
+#                         a 7-bit ASCII character (high bit always 0)
+# FLOAT        32        IEEE Floating point number
 #
 # BTIME
-#	UWORD	16	Year (e.g. 1987)
-#	UWORD	16	J-Day
-#	UBYTE	8	Hours of day (0-23)
-#	UBYTE	8	Minutes of hour (0-59)
-#	UBYTE	8	Seconds of minute (0-59, 60 for leap seconds)
-#	UBYTE	8	Unused for data (required for alignment)(
-#	UWORD	16	.0001 seconds (0-9999)
+#    UWORD    16    Year (e.g. 1987)
+#    UWORD    16    J-Day
+#    UBYTE    8    Hours of day (0-23)
+#    UBYTE    8    Minutes of hour (0-59)
+#    UBYTE    8    Seconds of minute (0-59, 60 for leap seconds)
+#    UBYTE    8    Unused for data (required for alignment)(
+#    UWORD    16    .0001 seconds (0-9999)
 #########################################################
-	def fixedhdr(self, seekval=0):
-		"""
-		Reads fixed header of 48 bytes (see SEED manual)
-		Returns four tuples
-			textblk (SeqNum, DHQual, res, Stat, Loc, Chan, Net)
-				Sequence Number (CHAR*6)
-				Data header/quality indicator (CHAR*1)
-				Reserved (CHAR*1)
-				Station identifier code (CHAR*5)
-				Location identifier (CHAR*2)
-				Channel identifier (CHAR*3)
-				Network Code (CHAR*2)
-			timeblk (Year, Day, Hour, Min, Sec, junk, Micro)
-				Year (UWORD, 2)
-				Jday (UWORD, 2)
-				Hour (UBYTE, 1)
-				Min (UBYTE, 1)
-				Sec (UBYTE, 1)
-				unused (UBYTE, 1)
-				.0001 seconds (0-9999) (UWORD, 2)
-			sampblk (NumSamp, SampFact, SampMult)
-				Number of samples (UWORD, 2)
-				Sample rate factor (see calcrate) (WORD, 2)
-				Sample rate multiplier (see calcrate) (WORD, 2)
-			miscblk (act, io, DataDHQualFl, numblock, timcorr, bdata, bblock)
-				Activity flags (UBYTE, 1)
-				I/O and clock flags (UBYTE, 1)
-				Data quality flags (UBYTE, 1)
-				Number of blockettes that follow (UBYTE, 1)
-				Time correction (LONG, 4)
-				Offset to beginning of data (UWORD, 2)
-				Offset to beginning of next blockette (UWORD, 2)
-		"""
-		#local variable
-#		self.sunpack=self.sunpack
-		try:
-			del self.FH
-		except:
-			pass
-		self.FH = FixedHeader()
-		try:
-			self.infileseek(seekval)
-			fhblk=self.infileread(48)
-			#station info
-			fmtstr = self.fmt_order + "6scc5s2s3s2s"
-			self.FH.textblk=self.sunpack(fmtstr,fhblk[0:20])
-
-			#time info
-			fmtstr = self.fmt_order + "HHBBBBH"
-			self.FH.timeblk=self.sunpack(fmtstr,fhblk[20:30])
-
-			#sample info
-			fmtstr = self.fmt_order + "Hhh"
-			self.FH.sampblk=self.sunpack(fmtstr, fhblk[30:36])
-
-			#misc info
-			fmtstr = self.fmt_order + "BBBBlHH"
-			tmpblk=self.sunpack(fmtstr,fhblk[36:48])
-			#decompose tmpblk[0-2] into bit fields, create miscblk
-			for i in range(3):
-				self.FH.miscblk = self.UbytetoStr(tmpblk, i)
-				tmpblk=self.FH.miscblk #recast tmpblk as list
-
-			(self.FH.Serial, self.FH.DHQual, res, self.FH.Stat, self.FH.Loc, self.FH.Chan, self.FH.Net)\
-			 =self.FH.textblk
-			(self.FH.Year, self.FH.Day, self.FH.Hour, self.FH.Min, self.FH.Sec, junk, self.FH.Micro)\
-			 =self.FH.timeblk
-			(self.FH.NumSamp, self.FH.SampFact, self.FH.SampMult)\
-			 =self.FH.sampblk
-			self.rate=self.calcrate()
-
-			return self.FH.textblk, self.FH.timeblk, self.FH.sampblk, self.FH.miscblk
-#			return textblk,timeblk,sampblk,miscblk
-
-		except:
-			print "error reading fixed header"
-			pass
+    def fixedhdr(self, seekval=0):
+        """
+        Reads fixed header of 48 bytes (see SEED manual)
+        Returns four tuples
+            textblk (SeqNum, DHQual, res, Stat, Loc, Chan, Net)
+                Sequence Number (CHAR*6)
+                Data header/quality indicator (CHAR*1)
+                Reserved (CHAR*1)
+                Station identifier code (CHAR*5)
+                Location identifier (CHAR*2)
+                Channel identifier (CHAR*3)
+                Network Code (CHAR*2)
+            timeblk (Year, Day, Hour, Min, Sec, junk, Micro)
+                Year (UWORD, 2)
+                Jday (UWORD, 2)
+                Hour (UBYTE, 1)
+                Min (UBYTE, 1)
+                Sec (UBYTE, 1)
+                unused (UBYTE, 1)
+                .0001 seconds (0-9999) (UWORD, 2)
+            sampblk (NumSamp, SampFact, SampMult)
+                Number of samples (UWORD, 2)
+                Sample rate factor (see calcrate) (WORD, 2)
+                Sample rate multiplier (see calcrate) (WORD, 2)
+            miscblk (act, io, DataDHQualFl, numblock, timcorr, bdata, bblock)
+                Activity flags (UBYTE, 1)
+                I/O and clock flags (UBYTE, 1)
+                Data quality flags (UBYTE, 1)
+                Number of blockettes that follow (UBYTE, 1)
+                Time correction (LONG, 4)
+                Offset to beginning of data (UWORD, 2)
+                Offset to beginning of next blockette (UWORD, 2)
+        """
+        #local variable
+#        self.sunpack=self.sunpack
+        try:
+            del self.FH
+        except Exception as e:
+            pass
+        self.FH = FixedHeader()
+        try:
+            self.infileseek(seekval)
+            fhblk=self.infileread(48)
+            #station info
+            fmtstr = self.fmt_order + "6scc5s2s3s2s"
+            self.FH.textblk=self.sunpack(fmtstr,fhblk[0:20])
+
+            #time info
+            fmtstr = self.fmt_order + "HHBBBBH"
+            self.FH.timeblk=self.sunpack(fmtstr,fhblk[20:30])
+
+            #sample info
+            fmtstr = self.fmt_order + "Hhh"
+            self.FH.sampblk=self.sunpack(fmtstr, fhblk[30:36])
+
+            #misc info
+            fmtstr = self.fmt_order + "BBBBlHH"
+            tmpblk=self.sunpack(fmtstr,fhblk[36:48])
+            #decompose tmpblk[0-2] into bit fields, create miscblk
+            for i in range(3):
+                self.FH.miscblk = self.UbytetoStr(tmpblk, i)
+                tmpblk=self.FH.miscblk #recast tmpblk as list
+
+            (self.FH.Serial, self.FH.DHQual, res, self.FH.Stat, self.FH.Loc, self.FH.Chan, self.FH.Net)\
+                    =self.FH.textblk
+            (self.FH.Year, self.FH.Day, self.FH.Hour, self.FH.Min, self.FH.Sec, junk, self.FH.Micro)\
+                    =self.FH.timeblk
+            (self.FH.NumSamp, self.FH.SampFact, self.FH.SampMult)\
+                    =self.FH.sampblk
+            self.rate=self.calcrate()
+
+            return self.FH.textblk, self.FH.timeblk, self.FH.sampblk, self.FH.miscblk
+#            return textblk,timeblk,sampblk,miscblk
+
+        except Exception as e:
+            print("error reading fixed header")
+            pass
 
 #########################################################
-	def WriteFixedHdr(self, hdrlist, seekval=0, endianess=""):
-		"""
-		Writes fixed header of 48 bytes (see SEED manual)
-		Requires four tuples (see self.fixedhdr)
-		"""
-
-		try:
-			self.infileseek(seekval)
-			fmtorderstr=self.setEndian(endianess)
-			#station info
-			#left justify values
-			#fmtstr0 = fmtorderstr + "6scc5s2s3s2s"
-
-			SeqNum=self.Pad(hdrlist[0][0], 6) #SeqNum
-			DQual=hdrlist[0][1] #DataQual
-			Res=hdrlist[0][2] #Reserved
-			Stat=self.Pad(hdrlist[0][3], 5) #Stat
-			Loc=self.Pad(hdrlist[0][4], 2) #Loc
-			Chan=self.Pad(hdrlist[0][5], 3) #Chan
-			Net=self.Pad(hdrlist[0][6], 2) #Net
-
-			#time info
-			#fmtstr1 = fmtorderstr + "HHBBBBH"
-			(Year, Day, Hour, Min, Sec, junk, Micro)=hdrlist[1]
-			Micro=int(Micro)		
-
-			#sample info
-			#fmtstr2 = fmtorderstr + "Hhh"
-			(NumSamp, SampFact, SampMult)=hdrlist[2]
-
-			#misc info
-			#fmtstr3 = fmtorderstr + "BBBBlHH"
-			(actFlags, ioFlags, dqFlags, numblk, timecor, offsetData, offsetBlktt)=hdrlist[3]
-			#convert flag string to integer
-			actFlags = self.FlagStrtoInt(actFlags)
-			ioFlags = self.FlagStrtoInt(ioFlags)
-			dqFlags = self.FlagStrtoInt(dqFlags)		
-
-			#pack fields
-			fmtstr= fmtorderstr + "6scc5s2s3s2sHHBBBBHHhhBBBBlHH"
-			pack_hdr=self.spack(fmtstr,SeqNum, DQual, Res, Stat, Loc, Chan, Net,\
-					     Year, Day, Hour, Min, Sec, junk, Micro,\
-					     NumSamp, SampFact, SampMult,\
-					     actFlags, ioFlags, dqFlags, numblk, timecor, offsetData, offsetBlktt)
-
-			#write header
-			self.infilewrite(pack_hdr)
-
-			return 48
-		except:
-			print "error writing fixed header"
-			return 0
+    def WriteFixedHdr(self, hdrlist, seekval=0, endianess=""):
+        """
+        Writes fixed header of 48 bytes (see SEED manual)
+        Requires four tuples (see self.fixedhdr)
+        """
+
+        try:
+            self.infileseek(seekval)
+            fmtorderstr=self.setEndian(endianess)
+            #station info
+            #left justify values
+            #fmtstr0 = fmtorderstr + "6scc5s2s3s2s"
+    
+            SeqNum = self.Pad(hdrlist[0][0], 6) #SeqNum
+            DQual = hdrlist[0][1] #DataQual
+            Res = hdrlist[0][2] #Reserved
+            try:
+                Stat = self.Pad(hdrlist[0][3], 5).encode() #Stat
+                Loc = self.Pad(hdrlist[0][4], 2).encode() #Loc
+                Chan = self.Pad(hdrlist[0][5], 3).encode() #Chan
+                Net = self.Pad(hdrlist[0][6], 2).encode() #Net
+            except AttributeError:
+                Stat = self.Pad(hdrlist[0][3], 5) #Stat
+                Loc = self.Pad(hdrlist[0][4], 2) #Loc
+                Chan = self.Pad(hdrlist[0][5], 3) #Chan
+                Net = self.Pad(hdrlist[0][6], 2) #Net
+    
+            #time info
+            #fmtstr1 = fmtorderstr + "HHBBBBH"
+            (Year, Day, Hour, Min, Sec, junk, Micro)=hdrlist[1]
+            Micro=int(Micro)
+    
+            #sample info
+            #fmtstr2 = fmtorderstr + "Hhh"
+            (NumSamp, SampFact, SampMult) = hdrlist[2]
+    
+            #misc info
+            #fmtstr3 = fmtorderstr + "BBBBlHH"
+            (actFlags, ioFlags, dqFlags, numblk, timecor, offsetData,
+             offsetBlktt)=hdrlist[3]
+            #convert flag string to integer
+            actFlags = self.FlagStrtoInt(actFlags)
+            ioFlags = self.FlagStrtoInt(ioFlags)
+            dqFlags = self.FlagStrtoInt(dqFlags)
+    
+            #pack fields
+            fmtstr = fmtorderstr + "6scc5s2s3s2sHHBBBBHHhhBBBBlHH"
+    
+            pack_hdr = self.spack(
+                fmtstr,SeqNum, DQual, Res, Stat, Loc, Chan, Net,
+                Year, Day, Hour, Min, Sec, junk, Micro,
+                NumSamp, SampFact, SampMult,actFlags, ioFlags, dqFlags,
+                numblk, timecor, offsetData, offsetBlktt)
+    
+            #write header
+            self.infilewrite(pack_hdr)
+    
+            return 48
+        except Exception as e:
+            print("error writing fixed header")
+            return 0
 
 #########################################################
-	def GetBlk(self, blknum, seekval=0):
-		ValidBlk=(100,200,201,300,310,320,390,395,400,405,500,1000,1001,2000)
-		if not blknum in ValidBlk:
-			return 0
-		else:
-			callcmd="blk=self.blk" + str(blknum) + "(" + str(seekval) + ")"
-			exec callcmd
-			return blk
+    def GetBlk(self, blknum, seekval=0):
+        ValidBlk=(100,200,201,300,310,320,390,395,400,405,500,1000,1001,2000)
+        if not blknum in ValidBlk:
+            return 0
+        else:
+            callcmd = "global blk; blk=self.blk%s(%s)" \
+                % (str(blknum), str(seekval))
+
+            exec(callcmd)
+            return blk
 #########################################################
-	def PutBlk(self, blknum, indata, endian, seekval=0):
-		"""
-		test for valid blockette, if true write blockette
-		"""
-		ValidBlk=(100,200,201,300,310,320,390,395,400,405,500,1000,1001,2000)
-		if not blknum in ValidBlk:
-			return 0
-		else:
-			callcmd="bytes_written=self.Writeblk" + str(blknum) + "(indata" + "," + str(seekval) + ", endian)"
-			exec callcmd
-			return bytes_written
+    def PutBlk(self, blknum, indata, endian, seekval=0):
+        """
+        test for valid blockette, if true write blockette
+        """
+        ValidBlk=(100,200,201,300,310,320,390,395,400,405,500,1000,1001,2000)
+        if not blknum in ValidBlk:
+            return 0
+        else:
+            callcmd = "global bytes_written; "\
+                "bytes_written=self.Writeblk%s(indata, %s, endian)"\
+                % (str(blknum), str(seekval))
+
+            exec(callcmd)
+            return bytes_written
 #########################################################
-	def blk100(self, seekval=0):
-		"""
-		Sample Rate Blockette 100 (12 bytes)
-		Returns tuple
-			blk
-				Blockette type (UWORD, 2)
-				Next blockette's byte offset relative to fixed section of header
-					(UWORD, 2)
-				Actual sample rate (FLOAT, 4)
-				Flags (BYTE, 1)
-				Reserved (UBYTE, 3)
-		"""
-		self.infileseek(seekval)
-		fmtstr = self.fmt_order + "HHfb3B"
-		blk=self.sunpack(fmtstr, self.infileread(12))
-		scrblk = self.UbytetoStr(blk, 3)
-		blk=scrblk
-		return blk
+    def blk100(self, seekval=0):
+        """
+        Sample Rate Blockette 100 (12 bytes)
+        Returns tuple
+            blk
+                Blockette type (UWORD, 2)
+                Next blockette's byte offset relative to fixed section of header
+                    (UWORD, 2)
+                Actual sample rate (FLOAT, 4)
+                Flags (BYTE, 1)
+                Reserved (UBYTE, 3)
+        """
+        self.infileseek(seekval)
+        fmtstr = self.fmt_order + "HHfb3B"
+        blk = self.sunpack(fmtstr, self.infileread(12))
+        scrblk = self.UbytetoStr(blk, 3)
+        blk = scrblk
+        return blk
 
 #########################################################
-	def Writeblk100(self, inblk, seekval=0, endianess=""):
-		"""
-		writes Sample Rate Blockette 100 (12 bytes)
-		requires tuple inblk=(blkette, nextblk, actrate, flags, res0, res1, res2)
-		"""
-
-		try:
-			self.infileseek(seekval)
-			fmtorderstr=self.setEndian(endianess)
-			fmtstr = fmtorderstr + "HHfb3B"
-			(blkette, nextblk, actrate, flags, res0, res1, res2) = inblk
-			flags=self.FlagStrtoInt(flags)
-			pack_blk=self.spack(fmtstr, blkette, nextblk, actrate, flags, res0, res1, res2)
-			self.infilewrite(pack_blk)
-			return 12
-		except:
-			print "error writing blockette 100"
-			return 0
+    def Writeblk100(self, inblk, seekval=0, endianess=""):
+        """
+        writes Sample Rate Blockette 100 (12 bytes)
+        requires tuple inblk=(blkette, nextblk, actrate, flags, res0, res1, res2)
+        """
+
+        try:
+            self.infileseek(seekval)
+            fmtorderstr=self.setEndian(endianess)
+            fmtstr = fmtorderstr + "HHfb3B"
+            (blkette, nextblk, actrate, flags, res0, res1, res2) = inblk
+            flags = self.FlagStrtoInt(flags)
+
+            pack_blk = self.spack(fmtstr, blkette, nextblk, actrate, flags,
+                                  res0, res1, res2)
+            self.infilewrite(pack_blk)
+            return 12
+        except Exception as e:
+            print("error writing blockette 100")
+            return 0
 
 
 #########################################################
-	def blk200(self, seekval=0):
-		"""
-		Generic Event Detection Blockette 200 (52 bytes)
-		Returns tuple
-			blk
-				Blockette type (UWORD, 2)
-				Next blockette's byte offset relative to fixed section of header
-					(UWORD, 2)
-				Signal amplitude (FLOAT, 4)
-				Signal period (FLOAT,4)
-				Background estimate (FLOAT,4)
-				Event detection flags (UBYTE, 1)
-				Reserved (UBYTE, 1)
-				Signal onset time (BTime expanded, 10)
-				Detector Name (CHAR*24)
-		"""
-		self.infileseek(seekval)
-		fmtstr = self.fmt_order + "HHfffBB"
-		blk1=self.sunpack(fmtstr, self.infileread(18))
-		fmtstr = self.fmt_order + "HHBBBBH"
-		timeblk=self.sunpack(fmtstr, self.infileread(10))
-		fmtstr = self.fmt_order + "24s"
-		blk2=self.sunpack(fmtstr, self.infileread(24))
-
-		# incorporate timeblk tuple into blk list
-		tmpblk = list(blk1)
-		tmpblk.append(timeblk)
-		tmpblk = tmpblk + list(blk2)
-
-		#apply bit mask to Ubyte
-		blk = self.UbytetoStr(tmpblk, 5)
-		return blk
+    def blk200(self, seekval=0):
+        """
+        Generic Event Detection Blockette 200 (52 bytes)
+        Returns tuple
+            blk
+                Blockette type (UWORD, 2)
+                Next blockette's byte offset relative to fixed section of header
+                    (UWORD, 2)
+                Signal amplitude (FLOAT, 4)
+                Signal period (FLOAT,4)
+                Background estimate (FLOAT,4)
+                Event detection flags (UBYTE, 1)
+                Reserved (UBYTE, 1)
+                Signal onset time (BTime expanded, 10)
+                Detector Name (CHAR*24)
+        """
+        self.infileseek(seekval)
+        fmtstr = self.fmt_order + "HHfffBB"
+        blk1 = self.sunpack(fmtstr, self.infileread(18))
+        fmtstr = self.fmt_order + "HHBBBBH"
+        timeblk = self.sunpack(fmtstr, self.infileread(10))
+        fmtstr = self.fmt_order + "24s"
+        blk2 = self.sunpack(fmtstr, self.infileread(24))
+
+        # incorporate timeblk tuple into blk list
+        tmpblk = list(blk1)
+        tmpblk.append(timeblk)
+        tmpblk = tmpblk + list(blk2)
+
+        #apply bit mask to Ubyte
+        blk = self.UbytetoStr(tmpblk, 5)
+        return blk
 
 #########################################################
-	def Writeblk200(self, inblk, seekval=0, endianess=""):
-		"""
-		writes Generic Event Detection Blockette 200 (52 bytes)
-		requires tuple inblk
-		inblk=(blkette, nextblk, amp, period, bg, flags, \
-			Year, Day, Hour, Min, Sec, junk, Micro, charstr)
-		"""
-
-		try:
-			self.infileseek(seekval)
-			fmtorderstr=self.setEndian(endianess)
-			fmtstr = fmtorderstr + "HHfffBBHHBBBBH24s"
-
-			(blkette, nextblk, amp, period, bg, flags, \
-			 Year, Day, Hour, Min, Sec, junk, Micro, charstr)=inblk
-			flags=FlagsStrtoInt(flags)
-			pack_blk=self.spack(fmtstr, blkette, nextblk, amp, period, bg, flags, \
-					     Year, Day, Hour, Min, Sec, junk, Micro, charstr)
-			self.infilewrite(pack_blk)
-			return 52
-
-		except:
-			print "error writing blockette 200"
-			return 0
+    def Writeblk200(self, inblk, seekval=0, endianess=""):
+        """
+        writes Generic Event Detection Blockette 200 (52 bytes)
+        requires tuple inblk
+        inblk=(blkette, nextblk, amp, period, bg, flags, \
+            Year, Day, Hour, Min, Sec, junk, Micro, charstr)
+        """
+
+        try:
+            self.infileseek(seekval)
+            fmtorderstr=self.setEndian(endianess)
+            fmtstr = fmtorderstr + "HHfffBBHHBBBBH24s"
+
+            (blkette, nextblk, amp, period, bg, flags,
+             (Year, Day, Hour, Min, Sec, junk, Micro), charstr) = inblk
+            flags = FlagsStrtoInt(flags)
+
+            pack_blk = self.spack(
+                fmtstr, blkette, nextblk, amp, period, bg, flags,
+                Year, Day, Hour, Min, Sec, junk, Micro, charstr)
+
+            self.infilewrite(pack_blk)
+            return 52
+
+        except Exception as e:
+            print("error writing blockette 200")
+            return 0
 
 
 #########################################################
-	def blk201(self, seekval=0):
-		"""
-		Murdock Event Detection Blockette 201 (60 bytes)
-		Returns tuple
-			blk
-				Blockette type (UWORD, 2)
-				Next blockette's byte offset relative to fixed section of header
-					(UWORD, 2)
-				Signal amplitude (FLOAT, 4)
-				Signal period (FLOAT,4)
-				Background estimate (FLOAT,4)
-				Event detection flags (UBYTE, 1)
-				Reserved (UBYTE, 1)
-				Signal onset time (BTime expanded, 10)
-				Signal-to-noise ration values (UBYTE*6)
-				Lookback value (UBYTE, 1)
-				Pick algorithym (UBYTE, 1)
-				Detector Name (CHAR*24)
-		"""
-		self.infileseek(seekval)
-		fmtstr = self.fmt_order + "HHfffBB"
-		blk1=self.sunpack(fmtstr, self.infileread(18))
-		fmtstr = self.fmt_order + "HHBBBBH"
-		timeblk=self.sunpack(fmtstr, self.infileread(10))
-		fmtstr = self.fmt_order + "6BBB24s"
-		blk2=self.sunpack(fmtstr, self.infileread(32))
-
-		# incorporate timeblk tuple into blk list
-		tmpblk = list(blk1)
-		tmpblk.append(timeblk)
-		tmpblk = tmpblk + list(blk2)
-
-		#apply bit mask to Ubyte
-		blk = self.UbytetoStr(tmpblk, 5)
-		return blk
+    def blk201(self, seekval=0):
+        """
+        Murdock Event Detection Blockette 201 (60 bytes)
+        Returns tuple
+            blk
+                Blockette type (UWORD, 2)
+                Next blockette's byte offset relative to fixed section of
+                  header (UWORD, 2)
+                Signal amplitude (FLOAT, 4)
+                Signal period (FLOAT,4)
+                Background estimate (FLOAT,4)
+                Event detection flags (UBYTE, 1)
+                Reserved (UBYTE, 1)
+                Signal onset time (BTime expanded, 10)
+                Signal-to-noise ration values (UBYTE*6)
+                Lookback value (UBYTE, 1)
+                Pick algorithym (UBYTE, 1)
+                Detector Name (CHAR*24)
+        """
+        self.infileseek(seekval)
+        fmtstr = self.fmt_order + "HHfffBB"
+        blk1 = self.sunpack(fmtstr, self.infileread(18))
+        fmtstr = self.fmt_order + "HHBBBBH"
+        timeblk = self.sunpack(fmtstr, self.infileread(10))
+        fmtstr = self.fmt_order + "6BBB24s"
+        blk2 = self.sunpack(fmtstr, self.infileread(32))
+
+        # incorporate timeblk tuple into blk list
+        tmpblk = list(blk1)
+        tmpblk.append(timeblk)
+        tmpblk = tmpblk + list(blk2)
+
+        #apply bit mask to Ubyte
+        blk = self.UbytetoStr(tmpblk, 5)
+        return blk
 
 #########################################################
-	def Writeblk201(self, inblk, seekval=0, endianess=""):
-		"""
-		writes Murdock Event Detection Blockette 201 (60 bytes)
-		requires tuple inblk
-		inblk=(blkette, nextblk, amp, period, bg, flags, res, 
-				Year, Day, Hour, Min, Sec, junk, Micro, SN0, SN1, SN2, SN3, SN4, SN5, loop, algo, Name)
-		"""
-
-		try:
-			self.infileseek(seekval)
-			fmtorderstr=self.setEndian(endianess)
-			fmtstr = fmtorderstr + "HHfffBBHHBBBBH6BBB24s"
-
-			(blkette, nextblk, amp, period, bg, flags, res, \
-			 Year, Day, Hour, Min, Sec, junk, Micro, SN0, SN1, SN2, SN3, SN4, SN5, \
-			 loop, algo, Name)=inblk
-			flags=self.FlagStrtoInt(flags)
-			pack_blk=self.spack(fmtstr, blkette, nextblk, amp, period, bg, flags, res, \
-					     Year, Day, Hour, Min, Sec, junk, Micro, SN0, SN1, SN2, SN3, SN4, SN5, loop, algo, Name)
-			self.infilewrite(pack_blk)
-			return 60
-
-		except:
-			print "error writing blockette 201"
-			return 0
+    def Writeblk201(self, inblk, seekval=0, endianess=""):
+        """
+        writes Murdock Event Detection Blockette 201 (60 bytes)
+        requires tuple inblk
+        inblk=(blkette, nextblk, amp, period, bg, flags, res,
+                Year, Day, Hour, Min, Sec, junk, Micro,
+                SN0, SN1, SN2, SN3, SN4, SN5, loop, algo, Name)
+        """
+
+        try:
+            self.infileseek(seekval)
+            fmtorderstr = self.setEndian(endianess)
+            fmtstr = fmtorderstr + "HHfffBBHHBBBBH6BBB24s"
+    
+            (blkette, nextblk, amp, period, bg, flags, res,
+             (Year, Day, Hour, Min, Sec, junk, Micro),
+             SN0, SN1, SN2, SN3, SN4, SN5, loop, algo, Name) = inblk
+    
+            flags = self.FlagStrtoInt(flags)
+    
+            pack_blk = self.spack(
+                fmtstr, blkette, nextblk, amp, period, bg, flags, res,
+                Year, Day, Hour, Min, Sec, junk, Micro,
+                SN0, SN1, SN2, SN3, SN4, SN5, loop, algo, Name)
+    
+            self.infilewrite(pack_blk)
+            return 60
+
+        except Exception as e:
+            print("error writing blockette 201")
+            return 0
 
 
 #########################################################
-	def blk300(self, seekval=0):
-		"""
-		Step Calibration Blockette 300 (60 bytes)
-		Returns tuple
-			blk
-				Blockette type (UWORD, 2)
-				Next blockette's byte offset relative to fixed section of header
-					(UWORD, 2)
-				Beginning of calibration time (BTime expanded, 10)
-				Number of step calibrations (UBYTE, 1)
-				Calibrations flags (UBYTE, 1)
-				Step duration (ULONG, 4)
-				Interval durations (ULONG, 4)
-				Calibration signal amplitude (FLOAT, 4)
-				Channel with calibration input (CHAR*3)
-				Reserved (UBYTE, 1)
-				Reference amplitude (ULONG, 4)
-				Coupling (CHAR*12)
-				Rolloff (CHAR*12)
-		"""
-		self.infileseek(seekval)
-		fmtstr = self.fmt_order + "HH"
-		blk1=self.sunpack(fmtstr, self.infileread(4))
-		fmtstr = self.fmt_order + "HHBBBBH"
-		timeblk=self.sunpack(fmtstr, self.infileread(10))
-		fmtstr = self.fmt_order + "BBIIf3sBI12s12s"
-		blk2=self.sunpack(fmtstr, self.infileread(46))
-
-		# incorporate timeblk tuple into blk list
-		tmpblk = list(blk1)
-		tmpblk.append(timeblk)
-		tmpblk = tmpblk + list(blk2)
-
-		#apply bit mask to Ubyte
-		blk = self.UbytetoStr(tmpblk, 4)
-		return blk
+    def blk300(self, seekval=0):
+        """
+        Step Calibration Blockette 300 (60 bytes)
+        Returns tuple
+            blk
+                Blockette type (UWORD, 2)
+                Next blockette's byte offset relative to fixed section of header
+                    (UWORD, 2)
+                Beginning of calibration time (BTime expanded, 10)
+                Number of step calibrations (UBYTE, 1)
+                Calibrations flags (UBYTE, 1)
+                Step duration (ULONG, 4)
+                Interval durations (ULONG, 4)
+                Calibration signal amplitude (FLOAT, 4)
+                Channel with calibration input (CHAR*3)
+                Reserved (UBYTE, 1)
+                Reference amplitude (ULONG, 4)
+                Coupling (CHAR*12)
+                Rolloff (CHAR*12)
+        """
+        self.infileseek(seekval)
+        fmtstr = self.fmt_order + "HH"
+        blk1=self.sunpack(fmtstr, self.infileread(4))
+        fmtstr = self.fmt_order + "HHBBBBH"
+        timeblk = self.sunpack(fmtstr, self.infileread(10))
+        fmtstr = self.fmt_order + "BBIIf3sBI12s12s"
+        blk2 = self.sunpack(fmtstr, self.infileread(46))
+
+        # incorporate timeblk tuple into blk list
+        tmpblk = list(blk1)
+        tmpblk.append(timeblk)
+        tmpblk = tmpblk + list(blk2)
+
+        #apply bit mask to Ubyte
+        blk = self.UbytetoStr(tmpblk, 4)
+        return blk
 
 #########################################################
-	def Writeblk300(self, inblk, seekval=0, endianess=""):
-		"""
-		writes Step Calibration Blockette 300 (60 bytes)
-		requires tuples inblk
-		inblk=(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, \
-			numst, flags, dur, interv, amp, chan, res, ref, couple, rolloff)
-		"""
-
-		try:
-			self.infileseek(seekval)
-			fmtorderstr=self.setEndian(endianess)
-			fmtstr = fmtorderstr + "HHHHBBBBHBBIIf3sBI12s12s"
-
-			(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, \
-			 numst, flags, dur, interv, amp, chan, res, ref, couple, rolloff)=inblk
-			flags=self.FlagStrtoInt(flags)
-			pack_blk=self.spack(fmtstr, blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, \
-					     numst, flags, dur, interv, amp, chan, res, ref, couple, rolloff)
-			self.infilewrite(pack_blk)
-			return 60
-
-		except:
-			print "error writing blockette 300"
-			return 0
+    def Writeblk300(self, inblk, seekval=0, endianess=""):
+        """
+        writes Step Calibration Blockette 300 (60 bytes)
+        requires tuples inblk
+        inblk=(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro,
+            numst, flags, dur, interv, amp, chan, res, ref, couple, rolloff)
+        """
+
+        try:
+            self.infileseek(seekval)
+            fmtorderstr=self.setEndian(endianess)
+            fmtstr = fmtorderstr + "HHHHBBBBHBBIIf3sBI12s12s"
+
+            (blkette, nextblk, (Year, Day, Hour, Min, Sec, junk, Micro),
+             numst, flags, dur, interv, amp, chan, res, ref,
+             couple, rolloff) = inblk
+            flags = self.FlagStrtoInt(flags)
+
+            pack_blk = self.spack(
+                fmtstr, blkette, nextblk,
+                Year, Day, Hour, Min, Sec, junk, Micro,
+                numst, flags, dur, interv, amp, chan,
+                res, ref, couple, rolloff)
+
+            self.infilewrite(pack_blk)
+            return 60
+
+        except Exception as e:
+            print("error writing blockette 300")
+            return 0
 
 #########################################################
-	def blk310(self, seekval=0):
-		"""
-		Sine Calibration Blockette 310 (60 bytes)
-		Returns tuple
-			blk
-				Blockette type (UWORD, 2)
-				Next blockette's byte offset relative to fixed section of header
-					(UWORD, 2)
-				Beginning of calibration time (BTime expanded, 10)
-				Reserved (UBYTE, 1)
-				Calibrations flags (UBYTE, 1)
-				Calibration duration (ULONG, 4)
-				Period of signal (FLOAT, 4)
-				Amplitude of signal (FLOAT, 4)
-				Channel with calibration input (CHAR*3)
-				Reserved (UBYTE, 1)
-				Reference amplitued (ULONG, 4)
-				Coupling (CHAR*12)
-				Rolloff (CHAR*12)
-
-		"""
-		self.infileseek(seekval)
-		fmtstr = self.fmt_order + "HH"
-		blk1=self.sunpack(fmtstr, self.infileread(4))
-		fmtstr = self.fmt_order + "HHBBBBH"
-		timeblk=self.sunpack(fmtstr, self.infileread(10))
-		fmtstr = self.fmt_order + "BBIff3sBI12s12s"
-		blk2=self.sunpack(fmtstr, self.infileread(46))
-
-		# incorporate timeblk tuple into blk list
-		tmpblk = list(blk1)
-		tmpblk.append(timeblk)
-		tmpblk = tmpblk + list(blk2)
-
-		#apply bit mask to Ubyte
-		blk = self.UbytetoStr(tmpblk, 4)
-		return blk
+    def blk310(self, seekval=0):
+        """
+        Sine Calibration Blockette 310 (60 bytes)
+        Returns tuple
+            blk
+                Blockette type (UWORD, 2)
+                Next blockette's byte offset relative to fixed section of header
+                    (UWORD, 2)
+                Beginning of calibration time (BTime expanded, 10)
+                Reserved (UBYTE, 1)
+                Calibrations flags (UBYTE, 1)
+                Calibration duration (ULONG, 4)
+                Period of signal (FLOAT, 4)
+                Amplitude of signal (FLOAT, 4)
+                Channel with calibration input (CHAR*3)
+                Reserved (UBYTE, 1)
+                Reference amplitued (ULONG, 4)
+                Coupling (CHAR*12)
+                Rolloff (CHAR*12)
+
+        """
+        self.infileseek(seekval)
+        fmtstr = self.fmt_order + "HH"
+        blk1 = self.sunpack(fmtstr, self.infileread(4))
+        fmtstr = self.fmt_order + "HHBBBBH"
+        timeblk = self.sunpack(fmtstr, self.infileread(10))
+        fmtstr = self.fmt_order + "BBIff3sBI12s12s"
+        blk2 = self.sunpack(fmtstr, self.infileread(46))
+
+        # incorporate timeblk tuple into blk list
+        tmpblk = list(blk1)
+        tmpblk.append(timeblk)
+        tmpblk = tmpblk + list(blk2)
+
+        #apply bit mask to Ubyte
+        blk = self.UbytetoStr(tmpblk, 4)
+        return blk
 
 #########################################################
-	def Writeblk310(self, inblk, seekval=0, endianess=""):
-		"""
-		writes Sine Calibration Blockette 310 (60 bytes)
-		requires tuples inblk
-		inblk=(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, \
-			res, flags, dura,per,ampsig,chan, res2,refamp,coup,rolloff)
-		"""
-
-		try:
-			self.infileseek(seekval)
-			fmtorderstr=self.setEndian(endianess)
-			fmtstr = fmtorderstr + "HHHHBBBBHBBIff3sBI12s12s"
-
-			(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, \
-			 res, flags, dura,per,ampsig,chan, res2,refamp,coup,rolloff)=inblk
-			flags=self.FlagStrtoInt(flags)
-			pack_blk=self.spack(fmtstr, blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, \
-					     res, flags, dura,per,ampsig,chan, res2,refamp,coup,rolloff)
-			self.infilewrite(pack_blk)
-			return 60
-
-		except:
-			print "error writing blockette 310"
-			return 0
+    def Writeblk310(self, inblk, seekval=0, endianess=""):
+        """
+        writes Sine Calibration Blockette 310 (60 bytes)
+        requires tuples inblk
+        inblk=(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro,
+            res, flags, dura,per,ampsig,chan, res2,refamp,coup,rolloff)
+        """
+
+        try:
+            self.infileseek(seekval)
+            fmtorderstr=self.setEndian(endianess)
+            fmtstr = fmtorderstr + "HHHHBBBBHBBIff3sBI12s12s"
+
+            (blkette, nextblk, (Year, Day, Hour, Min, Sec, junk, Micro),
+             res, flags, dura, per, ampsig, chan, res2,
+             refamp, coup, rolloff) = inblk
+            flags = self.FlagStrtoInt(flags)
+
+            pack_blk = self.spack(
+                fmtstr, blkette, nextblk,
+                Year, Day, Hour, Min, Sec, junk, Micro,
+                res, flags, dura,per,ampsig,chan, res2,refamp,coup,rolloff)
+
+            self.infilewrite(pack_blk)
+            return 60
+
+        except Exception as e:
+            print("error writing blockette 310")
+            return 0
 
 #########################################################
-	def blk320(self, seekval=0):
-		"""
-		Pseudo-random Calibraton Blockette 320 (64 bytes)
-		Returns tuple
-			blk
-				Blockette type (UWORD, 2)
-				Next blockette's byte offset relative to fixed section of header
-					(UWORD, 2)
-				Beginning of calibration time (BTime expanded, 10)
-				Reserved (UBYTE, 1)
-				Calibrations flags (UBYTE, 1)
-				Calibration duration (ULONG, 4)
-				Peak-to-peak amplitude of steps (FLOAT, 4)
-				Channel with calibration input (CHAR*3)
-				Reserved (UBYTE, 1)
-				Reference amplitued (ULONG, 4)
-				Coupling (CHAR*12)
-				Rolloff (CHAR*12)
-				Noise type (CHAR*8)
-		"""
-		self.infileseek(seekval)
-		fmtstr = self.fmt_order + "HH"
-		blk1=self.sunpack(fmtstr, self.infileread(4))
-		fmtstr = self.fmt_order + "HHBBBBH"
-		timeblk=self.sunpack(fmtstr, self.infileread(10))
-		fmtstr = self.fmt_order + "BBIf3sBI12s12s8s"
-		blk2=self.sunpack(fmtstr, self.infileread(50))
-
-		# incorporate timeblk tuple into blk list
-		tmpblk = list(blk1)
-		tmpblk.append(timeblk)
-		tmpblk = tmpblk + list(blk2)
-
-		#apply bit mask to Ubyte
-		blk = self.UbytetoStr(tmpblk, 4)
-		return blk
+    def blk320(self, seekval=0):
+        """
+        Pseudo-random Calibraton Blockette 320 (64 bytes)
+        Returns tuple
+            blk
+                Blockette type (UWORD, 2)
+                Next blockette's byte offset relative to fixed section of header
+                    (UWORD, 2)
+                Beginning of calibration time (BTime expanded, 10)
+                Reserved (UBYTE, 1)
+                Calibrations flags (UBYTE, 1)
+                Calibration duration (ULONG, 4)
+                Peak-to-peak amplitude of steps (FLOAT, 4)
+                Channel with calibration input (CHAR*3)
+                Reserved (UBYTE, 1)
+                Reference amplitued (ULONG, 4)
+                Coupling (CHAR*12)
+                Rolloff (CHAR*12)
+                Noise type (CHAR*8)
+        """
+        self.infileseek(seekval)
+        fmtstr = self.fmt_order + "HH"
+        blk1 = self.sunpack(fmtstr, self.infileread(4))
+        fmtstr = self.fmt_order + "HHBBBBH"
+        timeblk = self.sunpack(fmtstr, self.infileread(10))
+        fmtstr = self.fmt_order + "BBIf3sBI12s12s8s"
+        blk2 = self.sunpack(fmtstr, self.infileread(50))
+
+        # incorporate timeblk tuple into blk list
+        tmpblk = list(blk1)
+        tmpblk.append(timeblk)
+        tmpblk = tmpblk + list(blk2)
+
+        #apply bit mask to Ubyte
+        blk = self.UbytetoStr(tmpblk, 4)
+        return blk
 
 #########################################################
-	def Writeblk320(self, inblk, seekval=0, endianess=""):
-		"""
-		writes Pseudo-random Calibraton Blockette 320 (64 bytes)
-		requires tuples inblk
-		inblk=(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, \
-			res, flags, dura,ptop,chan, res2,refamp,coup,rolloff,noise)
-		"""
-
-		try:
-			self.infileseek(seekval)
-			fmtorderstr=self.setEndian(endianess)
-			fmtstr = fmtorderstr + "HHHHBBBBHBBIf3sBI12s12s8s"
-
-			(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, \
-			 res, flags, dura,ptop,chan, res2,refamp,coup,rolloff,noise)=inblk
-			flags=self.FlagStrtoInt(flags)
-			pack_blk=self.spack(fmtstr, blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, \
-					     res, flags, dura,ptop,chan, res2,refamp,coup,rolloff,noise)
-			self.infilewrite(pack_blk)
-			return 64
-
-		except:
-			print "error writing blockette 320"
-			return 0
+    def Writeblk320(self, inblk, seekval=0, endianess=""):
+        """
+        writes Pseudo-random Calibraton Blockette 320 (64 bytes)
+        requires tuples inblk
+        inblk=(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro,
+            res, flags, dura,ptop,chan, res2,refamp,coup,rolloff,noise)
+        """
+
+        try:
+            self.infileseek(seekval)
+            fmtorderstr=self.setEndian(endianess)
+            fmtstr = fmtorderstr + "HHHHBBBBHBBIf3sBI12s12s8s"
+
+            (blkette, nextblk, (Year, Day, Hour, Min, Sec, junk, Micro),
+             res, flags, dura, ptop, chan, res2,
+             refamp, coup, rolloff, noise) = inblk
+
+            flags = self.FlagStrtoInt(flags)
+            pack_blk = self.spack(
+                fmtstr, blkette, nextblk,
+                Year, Day, Hour, Min, Sec, junk, Micro,
+                res, flags, dura, ptop, chan, res2,
+                refamp, coup, rolloff, noise)
+
+            self.infilewrite(pack_blk)
+            return 64
+
+        except Exception as e:
+            print("error writing blockette 320")
+            return 0
 
 #########################################################
-	def blk390(self, seekval=0):
-		"""
-		Generic Calibraton Blockette 390 (28 bytes)
-		Returns tuple
-			blk
-				Blockette type (UWORD, 2)
-				Next blockette's byte offset relative to fixed section of header
-					(UWORD, 2)
-				Beginning of calibration time (BTime expanded, 10)
-				Reserved (UBYTE, 1)
-				Calibrations flags (UBYTE, 1)
-				Calibration duration (ULONG, 4)
-				Calibration signal amplitude (FLOAT, 4)
-				Channel with calibration input (CHAR*3)
-				Reserved (UBYTE, 1)
-		"""
-		self.infileseek(seekval)
-		fmtstr = self.fmt_order + "HH"
-		blk1=self.sunpack(fmtstr, self.infileread(4))
-		fmtstr = self.fmt_order + "HHBBBBH"
-		timeblk=self.sunpack(fmtstr, self.infileread(10))
-		fmtstr = self.fmt_order + "BBIf3sB"
-		blk2=self.sunpack(fmtstr, self.infileread(14))
-
-		# incorporate timeblk tuple into blk list
-		tmpblk = list(blk1)
-		tmpblk.append(timeblk)
-		tmpblk = tmpblk + list(blk2)
-
-		#apply bit mask to Ubyte
-		blk = self.UbytetoStr(tmpblk, 4)
-		return blk
+    def blk390(self, seekval=0):
+        """
+        Generic Calibraton Blockette 390 (28 bytes)
+        Returns tuple
+            blk
+                Blockette type (UWORD, 2)
+                Next blockette's byte offset relative to fixed section of header
+                    (UWORD, 2)
+                Beginning of calibration time (BTime expanded, 10)
+                Reserved (UBYTE, 1)
+                Calibrations flags (UBYTE, 1)
+                Calibration duration (ULONG, 4)
+                Calibration signal amplitude (FLOAT, 4)
+                Channel with calibration input (CHAR*3)
+                Reserved (UBYTE, 1)
+        """
+        self.infileseek(seekval)
+        fmtstr = self.fmt_order + "HH"
+        blk1 = self.sunpack(fmtstr, self.infileread(4))
+        fmtstr = self.fmt_order + "HHBBBBH"
+        timeblk = self.sunpack(fmtstr, self.infileread(10))
+        fmtstr = self.fmt_order + "BBIf3sB"
+        blk2 = self.sunpack(fmtstr, self.infileread(14))
+
+        # incorporate timeblk tuple into blk list
+        tmpblk = list(blk1)
+        tmpblk.append(timeblk)
+        tmpblk = tmpblk + list(blk2)
+
+        #apply bit mask to Ubyte
+        blk = self.UbytetoStr(tmpblk, 4)
+        return blk
 
 #########################################################
-	def Writeblk390(self, inblk, seekval=0, endianess=""):
-		"""
-		writes Generic Calibraton Blockette 390 (28 bytes)
-		requires tuples inblk
-		inblk=(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, \
-			res, flags, dura,amp,chan, res2)
-		"""
-
-		try:
-			self.infileseek(seekval)
-			fmtorderstr=self.setEndian(endianess)
-			fmtstr = fmtorderstr + "HHHHBBBBHBBIf3sB"
-
-			(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, \
-			 res, flags, dura,amp,chan, res2)=inblk
-			flags=self.FlagStrtoInt(flags)
-			pack_blk=self.spack(fmtstr, blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, \
-					     res, flags, dura,amp,chan, res2)
-			self.infilewrite(pack_blk)
-			return 28
-
-		except:
-			print "error writing blockette 390"
-			return 0
+    def Writeblk390(self, inblk, seekval=0, endianess=""):
+        """
+        writes Generic Calibraton Blockette 390 (28 bytes)
+        requires tuples inblk
+        inblk=(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro,
+            res, flags, dura,amp,chan, res2)
+        """
+
+        try:
+            self.infileseek(seekval)
+            fmtorderstr=self.setEndian(endianess)
+            fmtstr = fmtorderstr + "HHHHBBBBHBBIf3sB"
+
+            (blkette, nextblk, (Year, Day, Hour, Min, Sec, junk, Micro),
+             res, flags, dura, amp, chan, res2) = inblk
+            flags = self.FlagStrtoInt(flags)
+
+            pack_blk = self.spack(
+                fmtstr, blkette, nextblk,
+                Year, Day, Hour, Min, Sec, junk, Micro,
+                res, flags, dura,amp,chan, res2)
+
+            self.infilewrite(pack_blk)
+            return 28
+
+        except Exception as e:
+            print("error writing blockette 390")
+            return 0
 
 #########################################################
-	def blk395(self, seekval=0):
-		"""
-		Calibraton Abort Blockette 395 (16 bytes)
-		Returns tuple
-			blk
-				Blockette type (UWORD, 2)
-				Next blockette's byte offset relative to fixed section of header
-					(UWORD, 2)
-				End of calibration time (BTime expanded, 10)
-				Reserved (UBYTE, 2)
-		"""
-		self.infileseek(seekval)
-		fmtstr = self.fmt_order + "HHHHBBBBH2s"
-		blk=self.sunpack(fmtstr, self.infileread(16))
-		return list(blk)
+    def blk395(self, seekval=0):
+        """
+        Calibraton Abort Blockette 395 (16 bytes)
+        Returns tuple
+            blk
+                Blockette type (UWORD, 2)
+                Next blockette's byte offset relative to fixed section of header
+                    (UWORD, 2)
+                End of calibration time (BTime expanded, 10)
+                Reserved (UBYTE, 2)
+        """
+        self.infileseek(seekval)
+        fmtstr = self.fmt_order + "HHHHBBBBH2s"
+        blk = self.sunpack(fmtstr, self.infileread(16))
+        return list(blk)
 
 #########################################################
-	def Writeblk395(self, inblk, seekval=0, endianess=""):
-		"""
-		writes Calibraton Abort Blockette 395 (16 bytes)
-		requires tuples inblk
-		inblk=(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, res)
-		"""
-
-		try:
-			self.infileseek(seekval)
-			fmtorderstr=self.setEndian(endianess)
-			fmtstr = fmtorderstr + "HHHHBBBBH2s"
-
-			(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, res)=inblk
-			pack_blk=self.spack(fmtstr, blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, res)
-			self.infilewrite(pack_blk)
-			return 16
-
-		except:
-			print "error writing blockette 395"
-			return 0
+    def Writeblk395(self, inblk, seekval=0, endianess=""):
+        """
+        writes Calibraton Abort Blockette 395 (16 bytes)
+        requires tuples inblk
+        inblk=(blkette, nextblk, Year, Day, Hour, Min, Sec, junk, Micro, res)
+        """
+
+        try:
+            self.infileseek(seekval)
+            fmtorderstr=self.setEndian(endianess)
+            fmtstr = fmtorderstr + "HHHHBBBBH2s"
+
+            (blkette, nextblk,
+             (Year, Day, Hour, Min, Sec, junk, Micro), res) = inblk
+
+            pack_blk = self.spack(
+                fmtstr, blkette, nextblk,
+                Year, Day, Hour, Min, Sec, junk, Micro, res)
+
+            self.infilewrite(pack_blk)
+            return 16
+
+        except Exception as e:
+            print("error writing blockette 395")
+            return 0
 
 #########################################################
-	def blk400(self, seekval=0):
-		"""
-		Beam Blockette 400 (16 bytes)
-		Returns tuple
-			blk
-				Blockette type (UWORD, 2)
-				Next blockette's byte offset relative to fixed section of header
-					(UWORD, 2)
-				Beam azimuth (degrees) (FLOAT, 4)
-				Beam slowness (sec/degree) (FLOAT, 4)
-				Beam configuration (UWORD, 2)
-				Reserved (UBYTE, 2)
-		"""
-		self.infileseek(seekval)
-		fmtstr = self.fmt_order + "HHffH2B"
-		blk=self.sunpack(fmtstr, self.infileread(16))
-		return list(blk)
+    def blk400(self, seekval=0):
+        """
+        Beam Blockette 400 (16 bytes)
+        Returns tuple
+            blk
+                Blockette type (UWORD, 2)
+                Next blockette's byte offset relative to fixed section of header
+                    (UWORD, 2)
+                Beam azimuth (degrees) (FLOAT, 4)
+                Beam slowness (sec/degree) (FLOAT, 4)
+                Beam configuration (UWORD, 2)
+                Reserved (UBYTE, 2)
+        """
+        self.infileseek(seekval)
+        fmtstr = self.fmt_order + "HHffH2B"
+        blk=self.sunpack(fmtstr, self.infileread(16))
+        return list(blk)
 
 #########################################################
-	def Writeblk400(self, inblk, seekval=0, endianess=""):
-		"""
-		writes Beam Blockette 400 (16 bytes)
-		requires tuples inblk
-		inblk=(blkette, nextblk, baz,bslw,bconf,res0,res1)
-		"""
-
-		try:
-			self.infileseek(seekval)
-			fmtorderstr=self.setEndian(endianess)
-			fmtstr = fmtorderstr + "HHffH2B"
-
-			(blkette, nextblk, baz,bslw,bconf,res0,res1)=inblk
-			pack_blk=self.spack(fmtstr, blkette, nextblk, baz,bslw,bconf,res0,res1)
-			self.infilewrite(pack_blk)
-			return 16
-
-		except:
-			print "error writing blockette 400"
-			return 0
+    def Writeblk400(self, inblk, seekval=0, endianess=""):
+        """
+        writes Beam Blockette 400 (16 bytes)
+        requires tuples inblk
+        inblk=(blkette, nextblk, baz,bslw,bconf,res0,res1)
+        """
+
+        try:
+            self.infileseek(seekval)
+            fmtorderstr = self.setEndian(endianess)
+            fmtstr = fmtorderstr + "HHffH2B"
+
+            (blkette, nextblk, baz, bslw, bconf, res0, res1) = inblk
+
+            pack_blk=self.spack(
+                fmtstr, blkette, nextblk, baz, bslw, bconf, res0, res1)
+
+            self.infilewrite(pack_blk)
+            return 16
+
+        except Exception as e:
+            print("error writing blockette 400")
+            return 0
 
 #########################################################
-	def blk405(self, seekval=0):
-		"""
-		Beam Delay Blockette 405 (6 bytes)
-		Returns tuple
-			blk
-				Blockette type (UWORD, 2)
-				Next blockette's byte offset relative to fixed section of header
-					(UWORD, 2)
-				Array of delay values (UWORD, 2)
-		"""
-		self.infileseek(seekval)
-		fmtstr = self.fmt_order + "HHH"
-		blk=self.sunpack(fmtstr, self.infileread(6))
-		return list(blk)
+    def blk405(self, seekval=0):
+        """
+        Beam Delay Blockette 405 (6 bytes)
+        Returns tuple
+            blk
+                Blockette type (UWORD, 2)
+                Next blockette's byte offset relative to fixed section of header
+                    (UWORD, 2)
+                Array of delay values (UWORD, 2)
+        """
+        self.infileseek(seekval)
+        fmtstr = self.fmt_order + "HHH"
+        blk=self.sunpack(fmtstr, self.infileread(6))
+        return list(blk)
 
 #########################################################
-	def Writeblk405(self, inblk, seekval=0, endianess=""):
-		"""
-		writes Beam Delay Blockette 405 (6 bytes)
-		requires tuples inblk
-		inblk=(blkette, nextblk, delay)
-		"""
-
-		try:
-			self.infileseek(seekval)
-			fmtorderstr=self.setEndian(endianess)
-			fmtstr = fmtorderstr + "HHH"
-
-			(blkette, nextblk, delay)=inblk
-			pack_blk=self.spack(fmtstr, blkette, nextblk, delay)
-			self.infilewrite(pack_blk)
-			return 6
-
-		except:
-			print "error writing blockette 405"
-			return 0
+    def Writeblk405(self, inblk, seekval=0, endianess=""):
+        """
+        writes Beam Delay Blockette 405 (6 bytes)
+        requires tuples inblk
+        inblk=(blkette, nextblk, delay)
+        """
+
+        try:
+            self.infileseek(seekval)
+            fmtorderstr=self.setEndian(endianess)
+            fmtstr = fmtorderstr + "HHH"
+
+            (blkette, nextblk, delay) = inblk
+
+            pack_blk = self.spack(fmtstr, blkette, nextblk, delay)
+
+            self.infilewrite(pack_blk)
+            return 6
+
+        except Exception as e:
+            print("error writing blockette 405")
+            return 0
 
 #########################################################
-	def blk500(self, seekval=0):
-		"""
-		Timing Blockette 500 (200 bytes)
-		Returns tuple
-			blk
-				Blockette type (UWORD, 2)
-				Next blockette's byte offset relative to fixed section of header
-					(UWORD, 2)
-				VCO correction (FLOAT, 4)
-				Time of exception (BTime expanded, 10)
-				microsec (UBYTE, 1)
-				Reception quality (UBYTE, 1)
-				Exception count (ULONG, 4)
-				Exception type (CHAR*16)
-				Clock model (CHAR*32)
-				Clock status (CHAR*128)
-		"""
-		self.infileseek(seekval)
-		fmtstr = self.fmt_order + "HHf"
-		blk1=self.sunpack(fmtstr, self.infileread(8))
-		fmtstr = self.fmt_order + "HHBBBBH"
-		timeblk=self.sunpack(fmtstr,self.infileread(10))
-		fmtstr = self.fmt_order + "BBI16s32s128s"
-		blk2=self.sunpack(fmtstr, self.infileread(182))
-
-		# incorporate timeblk tuple into blk list
-		blk = list(blk1)
-		blk.append(timeblk)
-		blk = blk + list(blk2)
-
-		return blk
+    def blk500(self, seekval=0):
+        """
+        Timing Blockette 500 (200 bytes)
+        Returns tuple
+            blk
+                Blockette type (UWORD, 2)
+                Next blockette's byte offset relative to fixed section of header
+                    (UWORD, 2)
+                VCO correction (FLOAT, 4)
+                Time of exception (BTime expanded, 10)
+                microsec (UBYTE, 1)
+                Reception quality (UBYTE, 1)
+                Exception count (ULONG, 4)
+                Exception type (CHAR*16)
+                Clock model (CHAR*32)
+                Clock status (CHAR*128)
+        """
+        self.infileseek(seekval)
+        fmtstr = self.fmt_order + "HHf"
+        blk1 = self.sunpack(fmtstr, self.infileread(8))
+        fmtstr = self.fmt_order + "HHBBBBH"
+        timeblk = self.sunpack(fmtstr,self.infileread(10))
+        fmtstr = self.fmt_order + "BBI16s32s128s"
+        blk2=self.sunpack(fmtstr, self.infileread(182))
+
+        # incorporate timeblk tuple into blk list
+        blk = list(blk1)
+        blk.append(timeblk)
+        blk = blk + list(blk2)
+
+        return blk
 
 #########################################################
-	def Writeblk500(self, inblk, seekval=0, endianess=""):
-		"""
-		writes Timing Blockette 500 (200 bytes)
-		requires tuples inblk
-		inblk=(blkette, nextblk, vcocorr,Year, Day, Hour, Min, Sec, junk, Micro, Micro2, \
-			qual,cnt,type,mod,stat)
-		"""
-
-		try:
-			self.infileseek(seekval)
-			fmtorderstr=self.setEndian(endianess)
-			fmtstr = fmtorderstr + "HHfHHBBBBHBBI16s32s128s"
-
-			(blkette, nextblk, vcocorr,Year, Day, Hour, Min, Sec, junk, Micro, Micro2, \
-			 qual,cnt,type,mod,stat)=inblk
-			pack_blk=self.spack(fmtstr, blkette, nextblk, vcocorr,Year, Day, Hour, Min, Sec, junk, Micro, Micro2, \
-					     qual,cnt,type,mod,stat)
-			self.infilewrite(pack_blk)
-			return 200
-
-		except:
-			print "error writing blockette 500"
-			return 0
+    def Writeblk500(self, inblk, seekval=0, endianess=""):
+        """
+        writes Timing Blockette 500 (200 bytes)
+        requires tuples inblk
+        inblk=(blkette, nextblk, vcocorr,Year, Day, Hour, Min, Sec, junk,
+            Micro, Micro2, qual,cnt,type,mod,stat)
+        """
+
+        try:
+            self.infileseek(seekval)
+            fmtorderstr=self.setEndian(endianess)
+            fmtstr = fmtorderstr + "HHfHHBBBBHBBI16s32s128s"
+
+            (blkette, nextblk, vcocorr,
+             (Year, Day, Hour, Min, Sec, junk, Micro), Micro2,
+             qual, cnt, type, mod, stat) = inblk
+
+            pack_blk = self.spack(
+                fmtstr, blkette, nextblk, vcocorr,
+                Year, Day, Hour, Min, Sec, junk, Micro, Micro2,
+                qual, cnt, type, mod, stat)
+
+            self.infilewrite(pack_blk)
+            return 200
+
+        except Exception as e:
+            print("error writing blockette 500")
+            return 0
 
 #########################################################
-	def blk1000(self, seekval=0):
-		"""
-		Data Only SEED Blockette 1000 (8 bytes)
-		Returns tuple
-			blk
-				Blockette type (UWORD, 2)
-				Next blockette's byte offset relative to fixed section of header
-					(UWORD, 2)
-				Encoding Format (BYTE, 1)
-				Word Order (UBYTE, 1)
-				Data Record Length (UBYTE, 1)
-				Reserved (UBYTE, 1)
-		"""
-		self.infileseek(seekval)
-		fmtstr = self.fmt_order + "HHbBBB"
-		blk=self.sunpack(fmtstr, self.infileread(8))
-		return list(blk)
+    def blk1000(self, seekval=0):
+        """
+        Data Only SEED Blockette 1000 (8 bytes)
+        Returns tuple
+            blk
+                Blockette type (UWORD, 2)
+                Next blockette's byte offset relative to fixed section of
+                    header (UWORD, 2)
+                Encoding Format (BYTE, 1)
+                Word Order (UBYTE, 1)
+                Data Record Length (UBYTE, 1)
+                Reserved (UBYTE, 1)
+        """
+        self.infileseek(seekval)
+        fmtstr = self.fmt_order + "HHbBBB"
+
+        blk = self.sunpack(fmtstr, self.infileread(8))
+        return list(blk)
 
 #########################################################
-	def Writeblk1000(self, inblk, seekval=0, endianess=""):
-		"""
-		writes Data Only SEED Blockette 1000 (8 bytes)
-		requires tuples inblk
-		inblk=(blkette, nextblk, fmt,order,length,res)
-		"""
-
-		try:
-			self.infileseek(seekval)
-			fmtorderstr=self.setEndian(endianess)
-			fmtstr = fmtorderstr + "HHbBBB"
-
-			(blkette, nextblk, fmt,order,length,res)=inblk
-			pack_blk=self.spack(fmtstr, blkette, nextblk, fmt,order,length,res)
-			self.infilewrite(pack_blk)
-			return 8
-
-		except:
-			print "error writing blockette 1000"
-			return 0
+    def Writeblk1000(self, inblk, seekval=0, endianess=""):
+        """
+        writes Data Only SEED Blockette 1000 (8 bytes)
+        requires tuples inblk
+        inblk=(blkette, nextblk, fmt,order,length,res)
+        """
+
+        try:
+            self.infileseek(seekval)
+            fmtorderstr = self.setEndian(endianess)
+            fmtstr = fmtorderstr + "HHbBBB"
+
+            (blkette, nextblk, fmt,order,length,res) = inblk
+
+            pack_blk = self.spack(
+                fmtstr, blkette, nextblk, fmt,order,length,res)
+
+            self.infilewrite(pack_blk)
+            return 8
+
+        except Exception as e:
+            print("error writing blockette 1000")
+            return 0
 
 #########################################################
-	def blk1001(self, seekval=0):
-		"""
-		Data Extension Blockette 1001 (8 bytes)
-		Returns tuple
-			blk
-				Blockette type (UWORD, 2)
-				Next blockette's byte offset relative to fixed section of header
-					(UWORD, 2)
-				Timing Quality (UBYTE, 1)
-				microsec (UBYTE, 1)
-				Reserved (UBYTE, 1)
-				Frame count (UBYTE, 1)
-		"""
-		self.infileseek(seekval)
-		fmtstr = self.fmt_order + "HHBBBB"
-		blk=self.sunpack(fmtstr, self.infileread(8))
-		return list(blk)
+    def blk1001(self, seekval=0):
+        """
+        Data Extension Blockette 1001 (8 bytes)
+        Returns tuple
+            blk
+                Blockette type (UWORD, 2)
+                Next blockette's byte offset relative to fixed section of
+                    header (UWORD, 2)
+                Timing Quality (UBYTE, 1)
+                microsec (UBYTE, 1)
+                Reserved (UBYTE, 1)
+                Frame count (UBYTE, 1)
+        """
+        self.infileseek(seekval)
+        fmtstr = self.fmt_order + "HHBBBB"
+        blk = self.sunpack(fmtstr, self.infileread(8))
+        return list(blk)
 #########################################################
-	def Writeblk1001(self, inblk, seekval=0, endianess=""):
-		"""
-		writes Data Extension Blockette 1001 (8 bytes)
-		requires tuples inblk
-		inblk=(blkette, nextblk, tqual,micro,res,fcnt)
-		"""
-
-		try:
-			self.infileseek(seekval)
-			fmtorderstr=self.setEndian(endianess)
-			fmtstr = fmtorderstr + "HHBBBB"
-
-			(blkette, nextblk, tqual,micro,res,fcnt)=inblk
-			pack_blk=self.spack(fmtstr, blkette, nextblk, tqual,micro,res,fcnt)
-			self.infilewrite(pack_blk)
-			return 8
-
-		except:
-			print "error writing blockette 1001"
-			return 0
+    def Writeblk1001(self, inblk, seekval=0, endianess=""):
+        """
+        writes Data Extension Blockette 1001 (8 bytes)
+        requires tuples inblk
+        inblk=(blkette, nextblk, tqual,micro,res,fcnt)
+        """
+
+        try:
+            self.infileseek(seekval)
+            fmtorderstr=self.setEndian(endianess)
+            fmtstr = fmtorderstr + "HHBBBB"
+
+            (blkette, nextblk, tqual, micro, res, fcnt) = inblk
+
+            pack_blk = self.spack(
+                fmtstr, blkette, nextblk, tqual, micro, res, fcnt)
+
+            self.infilewrite(pack_blk)
+            return 8
+
+        except Exception as e:
+            print("error writing blockette 1001")
+            return 0
 
 #########################################################
-	def blk2000(self, seekval=0):
-		"""
-		Variable Length Opaque Data Blockette
-		Returns two tuples
-			blk, opaque
-				Blockette type (UWORD, 2)
-				Next blockette's byte offset relative to fixed section of header. Use 0 if no
-					more blockettes will follow. (UWORD, 2)
-				Total Blockette length kin Bytes (UWORD, 2)
-				Offset to Opaque Data (UWORD, 2)
-				Record number (ULONG, 4)
-				Data Word order (UBYTE, 1)
-					0 = little endian (VAX or 80x86 byte order).
-					1 = big endian (68000 or SPARC byte order).
-				Opaque Data flags (UBYTE, 1)
-					[bit 0] Opaque blockette orientation.
-						0 = record oriented.
-						1 = stream oriented.
-					[bit 1] Packaging bit.
-						0 = Blockette 2000s from multiple SEED data records with different timetags
-						may be packaged into a single SEED data record. The exact original
-						timetag in each SEED Fixed Data Header is not required for each
-						blockette 2000.
-						1= Blockette 2000s from multiple SEED data records with differing timetags
-						may NOT be repackaged into a single SEED data record. Set this bit
-						if the timetag in the SEED Fixed Data Header is required to properly
-						interpret the opaque data.
-					[bits 2-3] Opaque blockette fragmentation flags.
-						00 = opaque record identified by record number is completely contained in
-						this opaque blockette.
-						01 = first opaque blockette for record spanning multiple blockettes.
-						11 = continuation blockette 2...N-1 of record spanning N blockettes.
-						10 = final blockette for record spanning N blockettes.
-					[bits 4-5] File blockette information.
-						00 = not file oriented.
-						01 = first blockette of file.
-						10 = continuation of file.
-						11 = last blockette of file.
-				Number of Opaque Header fields (UBYTE, 1)
-				Opaque Data Header fields (VAR)
-					a Record type
-					b Vendor type
-					c Model type
-					d Software
-					e Firmware
-				Opaque Data Opaque - bytes of opaque data. Total length of opaque data 
-					in bytes is blockette_length-15-length (opaque_data_header_string)
-					(Opaque)
-		"""
-		self.infileseek(seekval)
-		fmtstr = self.fmt_order + "HHHHIBBB"
-		blk=self.sunpack(fmtstr, self.infileread(15))
-	#decompose tmpblk[6] into bit fields, create blk
-		tmpblk = self.UbytetoStr(blk, 6)
-		blk=tmpblk #recast blk as list
-
-	#Now decipher Opaque Header
-		charlist=[]
-		char=""
-		length_data_string = 0
-		NumOpaqueHeaders=int(blk[7])
-		fmtstr = self.fmt_order + "s"
-		for i in range(NumOpaqueHeaders):
-			tmpchar=""
-			while tmpchar != "~":
-				tupchar=self.sunpack(fmtstr, self.infileread(1))
-				tmpchar = str(tupchar[0])
-				if tmpchar != "~":
-					char = char + tmpchar
-				length_data_string += 1
-			charlist.append(char)
-		blk.append(charlist)
-# 		opaque = ""
-# 		rdbyte = int(tmpblk[2]) - 15 - length_data_string
-# 		fmt = "=%ds" % rdbyte
-# 		opaque=self.sunpack(fmt, self.infileread(rdbyte))
+    def blk2000(self, seekval=0):
+        """
+        Variable Length Opaque Data Blockette
+        Returns two tuples
+          blk, opaque
+            Blockette type (UWORD, 2)
+            Next blockette's byte offset relative to fixed section of header.
+              Use 0 if no more blockettes will follow.(UWORD, 2)
+            Total Blockette length kin Bytes (UWORD, 2)
+            Offset to Opaque Data (UWORD, 2)
+            Record number (ULONG, 4)
+            Data Word order (UBYTE, 1)
+              0 = little endian (VAX or 80x86 byte order).
+              1 = big endian (68000 or SPARC byte order).
+            Opaque Data flags (UBYTE, 1)
+              [bit 0] Opaque blockette orientation.
+                0 = record oriented.
+                1 = stream oriented.
+              [bit 1] Packaging bit.
+                0 = Blockette 2000s from multiple SEED data records with
+                  different timetags may be packaged into a single SEED data
+                  record. The exact original timetag in each SEED Fixed Data
+                  Header is not required for each blockette 2000.
+                1= Blockette 2000s from multiple SEED data records with
+                  differing timetags may NOT be repackaged into a single SEED
+                  data record. Set this bit if the timetag in the SEED Fixed
+                  Data Header is required to properly interpret the opaque
+                  data.
+              [bits 2-3] Opaque blockette fragmentation flags.
+                00 = opaque record identified by record number is completely
+                  contained in this opaque blockette.
+                01 = first opaque blockette for record spanning multiple
+                  blockettes.
+                11 = continuation blockette 2...N-1 of record spanning N
+                  blockettes.
+                10 = final blockette for record spanning N blockettes.
+              [bits 4-5] File blockette information.
+                00 = not file oriented.
+                01 = first blockette of file.
+                10 = continuation of file.
+                11 = last blockette of file.
+            Number of Opaque Header fields (UBYTE, 1)
+            Opaque Data Header fields (VAR)
+              a Record type
+              b Vendor type
+              c Model type
+              d Software
+              e Firmware
+            Opaque Data Opaque - bytes of opaque data. Total length of opaque
+              data in bytes is blockette_length-15-length
+              (opaque_data_header_string) (Opaque)
+        """
+        self.infileseek(seekval)
+        fmtstr = self.fmt_order + "HHHHIBBB"
+        blk=self.sunpack(fmtstr, self.infileread(15))
+    #decompose tmpblk[6] into bit fields, create blk
+        tmpblk = self.UbytetoStr(blk, 6)
+        blk=tmpblk #recast blk as list
+
+    #Now decipher Opaque Header
+        charlist = []
+        char = ""
+        length_data_string = 0
+        NumOpaqueHeaders=int(blk[7])
+        fmtstr = self.fmt_order + "s"
+        for i in range(NumOpaqueHeaders):
+            tmpchar = ""
+            while tmpchar != "~":
+                tupchar = self.sunpack(fmtstr, self.infileread(1))
+                tmpchar = str(tupchar[0])
+                if tmpchar != "~":
+                    char = char + tmpchar
+                length_data_string += 1
+            charlist.append(char)
+        blk.append(charlist)
+#         opaque = ""
+#         rdbyte = int(tmpblk[2]) - 15 - length_data_string
+#         fmt = "=%ds" % rdbyte
+#         opaque=self.sunpack(fmt, self.infileread(rdbyte))
 # 
 # #
-# 		print opaque
+#         print opaque
 # #
-		return blk
+        return blk
 #########################################################
-	def UbytetoStr(self, tup, offset):
-		"""
-		converts unsign byte to string values
-		"""
-		list=[]
-		strval = ""
-		# mask bit fields and build string
-		for i in range(8):
-			mask = 2**i
-			if tup[offset] & mask:
-				strval = "1" + strval
-			else:
-				strval = "0" + strval
-
-		# build new list with decomposed bit string
-		for i in range(len(tup)):
-			if i == offset:
-				list.append(strval)
-			else:
-				list.append(tup[i])
-		return list
+    def UbytetoStr(self, tup, offset):
+        """
+        converts unsign byte to string values
+        """
+        list=[]
+        strval = ""
+        # mask bit fields and build string
+        for i in range(8):
+            mask = 2**i
+            if tup[offset] & mask:
+                strval = "1" + strval
+            else:
+                strval = "0" + strval
+
+        # build new list with decomposed bit string
+        for i in range(len(tup)):
+            if i == offset:
+                list.append(strval)
+            else:
+                list.append(tup[i])
+        return list
 #########################################################
-	def FlagStrtoInt(self, flagstr):
-		"""
-		converts Flag String to Integer
-		"""
-		flagint=0
-		n=len(flagstr) - 1
-		for a in flagstr:
-			if int(a):
-				flagint = flagint + 2**n
-			n-=1
-		return flagint
+    def FlagStrtoInt(self, flagstr):
+        """
+        converts Flag String to Integer
+        """
+        flagint = 0
+        n = len(flagstr) - 1
+        for a in flagstr:
+            if int(a):
+                flagint = flagint + 2**n
+            n -= 1
+        return flagint
 
 #########################################################
-	def Pad(self, var, num):
-		"""
-		pad header values to specified length with blank space
-		right justified
-		"""
-		varlength=len(var)
-		if varlength == num:
-			return var
-		elif varlength < num:
-			pad=num-varlength
-			newvar= var + SPACE*pad
-			return newvar
+    def Pad(self, var, num):
+        """
+        pad header values to specified length with blank space
+        right justified
+        """
+        varlength=len(var)
+        if varlength == num:
+            return var
+        elif varlength < num:
+            pad = num-varlength
+            newvar = var + SPACE*pad
+            return newvar
 
 
 #########################################################
 ### END MSEED
 #########################################################
 class Segy(futils):
-	def __init__(self, infile):
-		self.type=self.serial=self.chan=self.time=self.rate=None
-		futils.__init__(self,infile)
-		# self.byteorder: byte order of input file. 
-		#    "big"
-		#    "little"
-		#    or "unknown"
-		self.byteorder = self.ByteOrder()
-		# self.fmt_order: companion to self.byteorder. Format string for stuct.pack
-		#    ">" big endian
-		#    "<" little endian
+    def __init__(self, infile):
+        self.type = self.serial = self.chan = self.time = self.rate = None
+        futils.__init__(self,infile)
+        # self.byteorder: byte order of input file. 
+        #    "big"
+        #    "little"
+        #    or "unknown"
+        self.byteorder = self.ByteOrder()
+        # self.fmt_order: companion to self.byteorder.
+        # Format string for struct.pack
+        #    ">" big endian
+        #    "<" little endian
 
 #########################################################
-	def isSegy(self) :
-		"""
-		determines if processed file is segy or unknown type
-		"""
-		#if we don't know byteorder it must not be segy
-		if self.byteorder == "unknown": return 0
-
-		#otherwise it might be segy
-		(Sserial, Schan, Srate, Syear, Sday, Shour, Smin, Ssec) = self.idread()
-		#we have already tested for a valid time in self.ByteOrder, this test is
-		#to ensure that we were able to read a complete idhdr header
-		if Sserial == Schan == Srate == Syear == Sday == Shour == \
-		   Smin == Ssec == None: return 0
-		#if we're this far it must be segy
-		self.type = "segy"
-		if Sserial < 36864:
-			self.serial = Sserial
-		else:
-			self.serial = self.to_hex(Sserial)
-		self.time = string.join(map(str, (Syear, Sday, Shour, Smin, Ssec)), ":")
-		self.chan = Schan
-		self.rate = Srate
-		return 1
+    def isSegy(self) :
+        """
+        determines if processed file is segy or unknown type
+        """
+        #if we don't know byteorder it must not be segy
+        if self.byteorder == "unknown": return 0
+
+        #otherwise it might be segy
+        (Sserial, Schan, Srate, Syear, Sday, Shour, Smin, Ssec) = self.idread()
+        #we have already tested for a valid time in self.ByteOrder, this test is
+        #to ensure that we were able to read a complete idhdr header
+        if Sserial == Schan == Srate == Syear == Sday == Shour == \
+           Smin == Ssec == None: return 0
+        #if we're this far it must be segy
+        self.type = "segy"
+        if Sserial < 36864:
+            self.serial = Sserial
+        else:
+            self.serial = self.to_hex(Sserial)
+        self.time = ":".join(map(str, (Syear, Sday, Shour, Smin, Ssec)))
+        self.chan = Schan
+        self.rate = Srate
+        return 1
 
 #########################################################
-	def idhdr(self):
-		return self.type, self.serial, self.chan, self.time, self.rate
+    def idhdr(self):
+        return self.type, self.serial, self.chan, self.time, self.rate
 
 #########################################################
-	def tracelength(self):
-		"""
-		returns trace length in seconds
-		"""
-		self.infile.seek(228)
-		fmtstr = self.fmt_order + "L"
-		numsamp=struct.unpack(fmtstr, self.infile.read(4))[0]
-		length=numsamp/self.rate
-		return length
+    def tracelength(self):
+        """
+        returns trace length in seconds
+        """
+        self.infile.seek(228)
+        fmtstr = self.fmt_order + "L"
+        numsamp=struct.unpack(fmtstr, self.infile.read(4))[0]
+        length=numsamp/self.rate
+        return length
 #########################################################
-	def idread(self) :
-		"""
-		Read file as if SEGY file trying to extract
-		channel, time block, sample rate, and serial number
-		"""
-		try :
-			self.infile.seek(0)
-			SH=self.infile.read(240)
-#			self.infile.seek(12)
-			fmtstr = self.fmt_order + "L"
-#			chan = struct.unpack(fmtstr, self.infile.read(4))[0]
-#			print chan
-			chan=struct.unpack(fmtstr, SH[12:16])[0]
-
-# 			self.infile.seek(156)
-# 			timeblock=self.infile.read(10)
-			fmtstr = self.fmt_order + "HHHHH"
-#			(year,day,hour,min,sec)=struct.unpack(fmtstr, timeblock)
-			(year,day,hour,min,sec)=struct.unpack(fmtstr, SH[156:166])
-
-#			self.infile.seek(200)
-			fmtstr = self.fmt_order + "L"
-#			samp=struct.unpack(fmtstr, self.infile.read(4))[0]
-#			print samp
-			samp=struct.unpack(fmtstr, SH[200:204])[0]
-			rate = int(1/(samp/1e6))
-
-#			self.infile.seek(224)
-			fmtstr = self.fmt_order + "H"
-#			serial = struct.unpack(fmtstr, self.infile.read(2))[0]
-			serial=struct.unpack(fmtstr, SH[224:226])[0]
-
-			return serial, chan, rate, year, day, hour, min, sec
-
-		except :
-			return None, None, None, None, None, None, None, None
+    def idread(self) :
+        """
+        Read file as if SEGY file trying to extract
+        channel, time block, sample rate, and serial number
+        """
+        try :
+            self.infile.seek(0)
+            SH=self.infile.read(240)
+#            self.infile.seek(12)
+            fmtstr = self.fmt_order + "L"
+#            chan = struct.unpack(fmtstr, self.infile.read(4))[0]
+#            print chan
+            chan = struct.unpack(fmtstr, SH[12:16])[0]
+
+#             self.infile.seek(156)
+#             timeblock=self.infile.read(10)
+            fmtstr = self.fmt_order + "HHHHH"
+#            (year,day,hour,min,sec)=struct.unpack(fmtstr, timeblock)
+            (year, day, hour, min, sec) = struct.unpack(fmtstr, SH[156:166])
+
+#            self.infile.seek(200)
+            fmtstr = self.fmt_order + "L"
+#            samp=struct.unpack(fmtstr, self.infile.read(4))[0]
+#            print samp
+            samp = struct.unpack(fmtstr, SH[200:204])[0]
+            rate = int(1/(samp/1e6))
+
+#            self.infile.seek(224)
+            fmtstr = self.fmt_order + "H"
+#            serial = struct.unpack(fmtstr, self.infile.read(2))[0]
+            serial = struct.unpack(fmtstr, SH[224:226])[0]
+
+            return serial, chan, rate, year, day, hour, min, sec
+
+        except :
+            return None, None, None, None, None, None, None, None
 
 #########################################################
-	def ByteOrder(self, seekval=156) :
-		"""
-		read file as if it is segy just pulling time info
-		from header and determine if it makes sense unpacked
-		as big endian or little endian
-		"""
-		Order = "unknown"
-		try :
-			#seek to timeblock and read
-			self.infile.seek(seekval)
-			timeblock=self.infile.read(10)
-
-			#assume big endian
-			(Year, Day, Hour, Min, Sec)=\
-			 struct.unpack('>HHHHH',timeblock)
-			#test if big endian read makes sense
-			if 1950 <= Year <= 2050 and \
-			   1 <= Day <= 366 and \
-			   0 <= Hour <= 23 and \
-			   0 <= Min <= 59 and \
-			   0 <= Sec <= 59:
-				Order = "big"
-				self.fmt_order = ">"
-			else:
-				#try little endian read
-				(Year, Day, Hour, Min, Sec)=\
-				 struct.unpack('<HHHHH',timeblock)
-				#test if little endian read makes sense
-				if 1950 <= Year <= 2050 and \
-				   1 <= Day <= 366 and \
-				   0 <= Hour <= 23 and \
-				   0 <= Min <= 59 and \
-				   0 <= Sec <= 59:
-					Order = "little"
-					self.fmt_order = "<"
-		except :
-			pass
-
-		return Order
+    def ByteOrder(self, seekval=156) :
+        """
+        read file as if it is segy just pulling time info
+        from header and determine if it makes sense unpacked
+        as big endian or little endian
+        """
+        Order = "unknown"
+        try :
+            #seek to timeblock and read
+            self.infile.seek(seekval)
+            timeblock=self.infile.read(10)
+
+            #assume big endian
+            (Year, Day, Hour, Min, Sec)=\
+                    struct.unpack('>HHHHH',timeblock)
+            #test if big endian read makes sense
+            if 1950 <= Year <= 2050 and \
+               1 <= Day <= 366 and \
+               0 <= Hour <= 23 and \
+               0 <= Min <= 59 and \
+               0 <= Sec <= 59:
+                Order = "big"
+                self.fmt_order = ">"
+            else:
+                #try little endian read
+                (Year, Day, Hour, Min, Sec)=\
+                        struct.unpack('<HHHHH',timeblock)
+                #test if little endian read makes sense
+                if 1950 <= Year <= 2050 and \
+                   1 <= Day <= 366 and \
+                   0 <= Hour <= 23 and \
+                   0 <= Min <= 59 and \
+                   0 <= Sec <= 59:
+                    Order = "little"
+                    self.fmt_order = "<"
+        except :
+            pass
+
+        return Order
 #########################################################
-	def to_int(self, input) :
-		"""
-		conversion routine from hex to integer
-		"""
-		HEXCHAR=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"]
-		hexnum=str(input)
-		retval=0
-		input_length=len(hexnum)
-		for i in range(input_length) :
-			for index in range(len(HEXCHAR)) :
-				if string.upper(hexnum[i]) == HEXCHAR[index] :
-					retval=retval + index*(16**(input_length-(1+i)))
-		return retval
+    def to_int(self, input) :
+        """
+        conversion routine from hex to integer
+        """
+        HEXCHAR=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"]
+        hexnum=str(input)
+        retval=0
+        input_length=len(hexnum)
+        for i in range(input_length) :
+            for index in range(len(HEXCHAR)) :
+                if hexnum[i].upper() == HEXCHAR[index] :
+                    retval=retval + index*(16**(input_length-(1+i)))
+        return retval
 
 #########################################################
-	def to_hex(self, number) :
-		"""
-		conversion routine from integer to hex
-		"""
-		retval=0
-		hexnum=hex(number)
-		return hexnum[2:]
+    def to_hex(self, number) :
+        """
+        conversion routine from integer to hex
+        """
+        retval=0
+        hexnum=hex(number)
+        return hexnum[2:]
 #########################################################
 ### END SEGY
 #########################################################
 if __name__ == "__main__" :
 
-	VERSION = "2008.204"
-	filecnt=0
+    VERSION = "2008.204"
+    filecnt=0
 # based on traverse routine in "python standard library", Lundh pg 34
-	def GetTrace(DataDir) :
-		global filecnt
-		stack = []
-		rwError=0
-		for k in range(len(DataDir)) :
-			stack.append(DataDir[k])
-		files = []
-		file_list = {}
-		errcnt=0
-		while stack :
-			directory = stack.pop()
-			if not os.path.isdir(directory):
-				print "\n***WARNING*** Directory \"%s\" not found.\n" % directory
-				continue
-	#		else :
-			for file in os.listdir(directory):
-				fullname = os.path.join(directory, file)
-				if not os.access(fullname, 6):
-					rwError+=1
-					continue					
-
-				if os.path.isfile(fullname) :
-					filecnt+=1
-					try:
-						newfile = Segy(fullname)
-						if newfile.isSegy():
-							(type, serial, chan, time, rate) = newfile.idhdr()
-							length = newfile.tracelength()
-	#						length = "NULL"
-							file_list[fullname] = (type, serial, chan, time, rate, length, newfile.ByteOrder())
-						newfile.close()
-					except:
-						rwError+=1
-						pass
-					else:
-						try:
-							newfile=Mseed(fullname)
-							if newfile.isMseed():
-								try:
-									#simple test to determine if correct size file
-									filesize=newfile.filesize
-									blksize=newfile.blksize
-									(numblocks, odd_size)=divmod(filesize, blksize)
-									if odd_size:
-										rwError+=1
-										continue
-								except:
-									rwError+=1
-									continue
-
-								type=newfile.type
-								serial=string.strip(newfile.FH.Stat)
-								chan=string.strip(newfile.FH.Chan)
-								loc=string.strip(newfile.FH.Loc)
-								net=string.strip(newfile.FH.Net)
-								time=newfile.time
-								rate=newfile.rate
-								length = newfile.tracelength()
-		#							length = "NULL"
-								file_list[fullname] = (type, serial, chan, time, rate, length, newfile.ByteOrder())
-								newfile.close()
-						except:
-							rwError+=1
-							pass
-	#			if os.path.isdir(fullname) and not os.path.islink(fullname) :
-				if os.path.isdir(fullname) or (os.path.islink(fullname) and not os.path.isfile(fullname)):
-					stack.append(fullname)
-		return file_list, rwError
-
-	if len(sys.argv) > 1 :
-		if sys.argv[1] == "-#" :
-			print VERSION
-			sys.exit(1)
-		else :
-			print "Unknown arguement %s" % sys.argv[1:]
-			sys.exit(1)
-
-	segynum = 0
-	mseednum = 0
-	unknownnum = 0
-	Dirs = []
-#	Dirs.append(",")
-	Dirs.append(".")
-#	Dirs.append("/Users/bruce/data/uniq")
-	(file_list,rwError) = GetTrace(Dirs)		
-	for file in file_list.keys() :
-		file_type = file_list[file][0]
-		if file_type == "segy" :
-			segynum += 1
-# 			print "\n SEGY \n"
-# 			print "segy: ", file_list[file][1], file_list[file][2], file_list[file][3], \
-# 				file_list[file][4], file_list[file][5], file_list[file][6]
-		elif file_type == "mseed" :
-#		if file_type == "mseed" :
-			mseednum += 1
-# 			print "\n MSEED \n"
-# 			print "mseed: ", file_list[file][1], file_list[file][2], file_list[file][3], \
-# 				file_list[file][4], file_list[file][5], file_list[file][6]
-
-		#else :
-			#unknownnum += 1
-			#print "\n Format Not Recognized \n"
-	print "\nTotal Files Found = %i " % filecnt
-	print "SEGY Files Processed = %i \nMSEED Files Processed = %i" % (segynum, mseednum)
-	print "Total RWErrors = %i " % rwError
-	print "Total Files Identified = %i" % len(file_list)
+    def GetTrace(DataDir) :
+        global filecnt
+        stack = []
+        rwError = 0
+        for k in range(len(DataDir)) :
+            stack.append(DataDir[k])
+        files = []
+        file_list = {}
+        errcnt = 0
+        while stack :
+            directory = stack.pop()
+            if not os.path.isdir(directory):
+                print("\n***WARNING*** Directory \"%s\" not found.\n"
+                      % directory)
+                continue
+    #        else :
+            for file in os.listdir(directory):
+                fullname = os.path.join(directory, file)
+                if not os.access(fullname, 6):
+                    rwError+=1
+                    continue                    
+
+                if os.path.isfile(fullname) :
+                    filecnt+=1
+                    try:
+                        newfile = Segy(fullname)
+                        if newfile.isSegy():
+                            (type, serial, chan, time, rate) = newfile.idhdr()
+                            length = newfile.tracelength()
+    #                        length = "NULL"
+                            file_list[fullname] = (
+                                type, serial, chan, time, rate, length,
+                                newfile.ByteOrder())
+                        newfile.close()
+                    except Exception as e:
+                        rwError+=1
+                        pass
+                    else:
+                        try:
+                            newfile=Mseed(fullname)
+                            if newfile.isMseed():
+                                try:
+                                    #simple test to determine if correct size file
+                                    filesize = newfile.filesize
+                                    blksize = newfile.blksize
+                                    (numblocks, odd_size) = \
+                                        divmod(filesize, blksize)
+                                    if odd_size:
+                                        rwError += 1
+                                        continue
+                                except Exception as e:
+                                    rwError += 1
+                                    continue
+
+                                type = newfile.type
+                                serial = newfile.FH.Stat.strip()
+                                chan = newfile.FH.Chan.strip()
+                                loc = newfile.FH.Loc.strip()
+                                net = newfile.FH.Net.strip()
+                                time = newfile.time
+                                rate = newfile.rate
+                                length = newfile.tracelength()
+        #                            length = "NULL"
+                                file_list[fullname] = (
+                                    type, serial, chan, time, rate, length,
+                                    newfile.ByteOrder())
+                                newfile.close()
+                        except Exception as e:
+                            rwError+=1
+                            pass
+    #            if os.path.isdir(fullname) and not os.path.islink(fullname) :
+                if os.path.isdir(fullname) or \
+                   (os.path.islink(fullname) \
+                    and not os.path.isfile(fullname)):
+                    stack.append(fullname)
+        return file_list, rwError
+
+    if len(sys.argv) > 1 :
+        if sys.argv[1] == "-#" :
+            print(VERSION)
+            sys.exit(1)
+        else :
+            print("Unknown arguement %s" % sys.argv[1:])
+            sys.exit(1)
+
+    segynum = 0
+    mseednum = 0
+    unknownnum = 0
+    Dirs = []
+#    Dirs.append(",")
+    Dirs.append(".")
+#    Dirs.append("/Users/bruce/data/uniq")
+    (file_list,rwError) = GetTrace(Dirs)
+    for file in file_list :
+        file_type = file_list[file][0]
+        if file_type == "segy" :
+            segynum += 1
+#             print "\n SEGY \n"
+#             print "segy: ", file_list[file][1], file_list[file][2], file_list[file][3], \
+#                 file_list[file][4], file_list[file][5], file_list[file][6]
+        elif file_type == "mseed" :
+#        if file_type == "mseed" :
+            mseednum += 1
+#             print "\n MSEED \n"
+#             print "mseed: ", file_list[file][1], file_list[file][2], file_list[file][3], \
+#                 file_list[file][4], file_list[file][5], file_list[file][6]
+
+        #else :
+            #unknownnum += 1
+            #print "\n Format Not Recognized \n"
+    print("\nTotal Files Found = %i " % filecnt)
+    print("SEGY Files Processed = %i \nMSEED Files Processed = %i"
+          % (segynum, mseednum))
+    print("Total RWErrors = %i " % rwError)
+    print("Total Files Identified = %i" % len(file_list))
diff --git a/fixhdr/fixhdr.py b/fixhdr/fixhdr.py
index 3c950610bcec5dd3a2c0430b0544f399efe31518..437db442b27264d88c47d144a590012f2e7756c4 100755
--- a/fixhdr/fixhdr.py
+++ b/fixhdr/fixhdr.py
@@ -38,8 +38,8 @@
 # added log notebook and ability to save
 # added ability to load and save templates of changes
 # added error handling when finding files to log exceptions
-#	to log notebook if directories are unreadable or files are not
-#	read/write by uid of process
+#        to log notebook if directories are unreadable or files are not
+#        read/write by uid of process
 #
 ##########################
 # modification
@@ -65,40 +65,40 @@
 # date 2005.143
 #
 # Added two new notebooks/functionalities
-#	Time Shift notebook
-#		allows user to apply bulk time shifts keyed to Stat:Loc:Net
-#		associated functions:
-# 			buildTimeShift
-# 			UpdateTimeShift
-# 			TimeSet
-# 			ApplyTimeCor
-# 			FillTime
-# 			ClearAllTime
-#			SetFlag
+#        Time Shift notebook
+#                allows user to apply bulk time shifts keyed to Stat:Loc:Net
+#                associated functions:
+#                         buildTimeShift
+#                         UpdateTimeShift
+#                         TimeSet
+#                         ApplyTimeCor
+#                         FillTime
+#                         ClearAllTime
+#                        SetFlag
 #
-#	Endianess notebook
-#		allows user to switch endianess of data headers
-#		associated functions:
-# 			buildEndian
-# 			ChangeEndian
+#        Endianess notebook
+#                allows user to switch endianess of data headers
+#                associated functions:
+#                         buildEndian
+#                         ChangeEndian
 #
-#	Added features:
+#        Added features:
 #
-#		Wait utility
-#			if something is running pops-up a window telling user to wait
-#			functions:
-#				WaitWidget
-#		Warn utility
-# 			notifies user if headers have been changed
-# 			functions:
-# 				WarnWidget
-# 				Ignore
-# 		Enhanced Logging functionality
-# 			user can now sort log on All, Headers, Time, Endian, or Summary
-# 			user can flush logs
-# 			functions:
-# 				FlushLogs
-# 				DisplayLogs
+#                Wait utility
+#                        if something is running pops-up a window telling user to wait
+#                        functions:
+#                                WaitWidget
+#                Warn utility
+#                         notifies user if headers have been changed
+#                         functions:
+#                                 WarnWidget
+#                                 Ignore
+#                 Enhanced Logging functionality
+#                         user can now sort log on All, Headers, Time, Endian, or Summary
+#                         user can flush logs
+#                         functions:
+#                                 FlushLogs
+#                                 DisplayLogs
 #
 ##########################
 # modification
@@ -142,7 +142,7 @@
 # date 2005.300
 #
 # bug fix in BuildEpoch in try/except that revealed itself if time format was
-#	incorrect.
+#        incorrect.
 # add ResetTimeShift
 # add CheckTimeFormat to ensure proper Time format entered
 #
@@ -175,15 +175,15 @@
 # changed method of handling batchmode, allows user to specify datadir, list time corrections
 #
 # new methods
-#	TimeDictSet, WildCardLoc, NewOnlyTime, LoadTimeSelect, DumpUpdateDicts, Usage, ExitWidget, GetTimeCor
-#	ListTimeCor, AddZero, LaunchUndoTimeCor, CancelWarnTL, RecalcStartEnd
+#        TimeDictSet, WildCardLoc, NewOnlyTime, LoadTimeSelect, DumpUpdateDicts, Usage, ExitWidget, GetTimeCor
+#        ListTimeCor, AddZero, LaunchUndoTimeCor, CancelWarnTL, RecalcStartEnd
 #
 # reworked methods
-#	LaunchApplyTimeCor, ApplyTimeCor, UpdateTimeShift, GetStartEnd, writeFile, LoadTemplate, ExitCheck
-#	wait, WriteLog, addTextInfoBar
+#        LaunchApplyTimeCor, ApplyTimeCor, UpdateTimeShift, GetStartEnd, writeFile, LoadTemplate, ExitCheck
+#        wait, WriteLog, addTextInfoBar
 #
 # removed methods
-#	WaitWidget, ModAndExit
+#        WaitWidget, ModAndExit
 #
 # fix bug whereby 'Save Header Template' ignored current entries on 'Trace Header' tab
 ##########################
@@ -192,8 +192,8 @@
 # date 2007.177
 #
 # bug fix in LoadTemplate
-#	when loading timelist if shift = NA or na then shift was left unassigned
-#	this caused Time_Shift_sec to be an invalid float later in processing
+#        when loading timelist if shift = NA or na then shift was left unassigned
+#        this caused Time_Shift_sec to be an invalid float later in processing
 ##########################
 # modification
 # author: bcb
@@ -245,3650 +245,3864 @@
 # author: Derick Hess
 # Updated cookiecutter version, added call to main(), etc.
 
-VERSION = "2018.176"
+################################################################
+#
+# modification
+# version: 2019.025
+# author: Lan Dam
+# convert to py3
+# bug fix: In GetStartEnd when no "Stat:Loc:Net" selected (timeid="")
+
+VERSION = "2019.025"
 
+import os, sys, string, time
 import Pmw
-from Tkinter import *
-from FileDialog import *
+if sys.version_info[0] == 3:
+    # for Python3
+    from tkinter import *   ## notice lowercase 't' in tkinter here
+    from tkinter.filedialog import *
+    #from tkinter.filedialog import askopenfilename
+else:
+    # for Python2
+    VERSION += " run in py2passoft"
+    from Tkinter import *   ## notice capitalized T in Tkinter
+    from FileDialog import *
+    from tkFileDialog import askopenfilename
 
 from operator import mod
 from struct import pack
 from getopt import getopt
-import os, sys, string, tkFileDialog, time
+
 from LibTrace import *
 #import threading
 from glob import glob
 
 SPACE = " "
-DATALOC=""
+DATALOC = ""
 
 #vars used for batchmode
-BatchFile=""
-Endianess=""
-RunHeaderBatch=0
-RunTimeBatch=0
-RunEndianBatch=0
-BATCHMODE=0
+BatchFile = ""
+Endianess = ""
+RunHeaderBatch = 0
+RunTimeBatch = 0
+RunEndianBatch = 0
+BATCHMODE = 0
 
 def Usage(err=''):
-	print err
-	print "Usage\nfixhdr \nfixhdr -#\nfixhdr -h\nfixhdr [-d DataDirs] [-m batch_file] [-t batch_file] [-e endianess]"
-	print "\n       Invoked with no arguements, fixhdr will launch the GUI\n"
-	print "       -d DataDirs - colon separated list of data directories [default: cwd]"
-	print "       -e endianess - convert trace headers to endianess [big or little]"
-	print "       -h - this usage page"
-	print "       -m batch_file - correct mseed headers in batch mode using batch_file"
-	print "       -t batch_file - correct trace timing in batch mode using batch_file"
-	print "       -# - print version number"
-	print "       NOTE: -m, -t & -e are mutually exclusive. If you wish to do"
-	print "             both timing and headers, run time corrections first."
-	os._exit(0)
+    print(err)
+    print("Usage\nfixhdr \nfixhdr -#\nfixhdr -h\nfixhdr [-d DataDirs] "
+          "[-m batch_file] [-t batch_file] [-e endianess]")
+    print("\n       Invoked with no arguements, fixhdr will launch the GUI\n")
+    print("       -d DataDirs - colon separated list of data directories "
+          "[default: cwd]")
+    print("       -e endianess - convert trace headers to endianess ["
+          "big or little]")
+    print("       -h - this usage page")
+    print("       -m batch_file - correct mseed headers in batch mode using "
+          "batch_file")
+    print("       -t batch_file - correct trace timing in batch mode using "
+          "batch_file")
+    print("       -# - print version number")
+    print("      NOTE: -m, -t & -e are mutually exclusive. If you wish to do")
+    print("             both timing and headers, run time corrections first.")
+    os._exit(0)
 
 # get commandline args
 try:
-	opts, pargs = getopt(sys.argv[1:], 'hd:t:m:e:#')
-except:
-	err="\nERROR: Invalid command line usage\n"
-	Usage(err)
+    opts, pargs = getopt(sys.argv[1:], 'hd:t:m:e:#')
+except Exception as e:
+    err = "\nERROR: Invalid command line usage\n"
+    Usage(err)
 else:
-	for flag, arg in opts:
-		if flag == "-h":
-			Usage()
-		if flag == "-d":
-			DATALOC=arg
-		if flag == "-e":
-			Endianess=arg
-			if Endianess != "big" and Endianess != "little":
-				err="\nError: Endianess must be either 'big' or 'little'"
-				Usage(err)
-			RunEndianBatch=1
-			BATCHMODE=1
-		if flag == "-m":
-			BatchFile=arg
-			RunHeaderBatch=1
-			BATCHMODE=1
-		if flag == "-t":
-			BatchFile=arg
-			RunTimeBatch=1
-			BATCHMODE=1
-		if flag == "-#":
-			print VERSION
-			os._exit(0)
-	if RunTimeBatch + RunHeaderBatch + RunEndianBatch > 1:
-		err="\nERROR: Cannot correct timing, headers and/or endianess simultaniously\n"
-		Usage(err)
-
-
-print "\n", os.path.basename(sys.argv[0]), VERSION
+    for flag, arg in opts:
+        if flag == "-h":
+            Usage()
+        if flag == "-d":
+            DATALOC=arg
+        if flag == "-e":
+            Endianess=arg
+            if Endianess != "big" and Endianess != "little":
+                err="\nError: Endianess must be either 'big' or 'little'"
+                Usage(err)
+            RunEndianBatch=1
+            BATCHMODE=1
+        if flag == "-m":
+            BatchFile=arg
+            RunHeaderBatch=1
+            BATCHMODE=1
+        if flag == "-t":
+            BatchFile = arg
+            RunTimeBatch = 1
+            BATCHMODE=1
+        if flag == "-#":
+            print(VERSION)
+            os._exit(0)
+    if RunTimeBatch + RunHeaderBatch + RunEndianBatch > 1:
+        err="\nERROR: Cannot correct timing, headers and/or endianess simultaniously\n"
+        Usage(err)
+
+
+print("\n", os.path.basename(sys.argv[0]), VERSION)
 
 #From "Python and Tkinter Programming", J.E. Grayson, pg.103
 class Command:
-	def __init__(self,func, *args, **kw):
-		self.func = func
-		self.args = args
-		self.kw = kw
-	def __call__(self, *args, **kw):
-		args = self.args + args
-		kw.update(self.kw)
-		apply(self.func, args, kw)
+    def __init__(self,func, *args, **kw):
+        self.func = func
+        self.args = args
+        self.kw = kw
+    def __call__(self, *args, **kw):
+        args = self.args + args
+        kw.update(self.kw)
+        self.func(*args, **kw)
 
 #
-#	Over ride some methods in FileDialog so we only select directories
-#	From TraceBuilder.py, auth Steve Azevedo & Lloyd Carothers
+#        Over ride some methods in FileDialog so we only select directories
+#        From TraceBuilder.py, auth Steve Azevedo & Lloyd Carothers
 #
 class DirectoryDialog (FileDialog) :
 
-	title="Directory Select"
-	def __init__ (self, root) :
-		FileDialog.__init__ (self, root)
-
-	#Only allow selection of directories (single click)
-	def files_select_event (self, e):
-		pass
-	#Double click
-	def files_double_event (self, e):
-		pass
-
-	#Make sure it's a directory and accessable
-	def ok_command (self) :
-		file = self.get_selection ()
-		if not os.path.isdir (file) :
-			if not os.access (file, R_OK) :
-				self.root.bell ()
-				file = None
-		self.quit (file)
+    title = "Directory Select"
+    def __init__ (self, root) :
+        FileDialog.__init__ (self, root)
+
+    #Only allow selection of directories (single click)
+    def files_select_event (self, e):
+        pass
+    #Double click
+    def files_double_event (self, e):
+        pass
+
+    #Make sure it's a directory and accessable
+    def ok_command (self) :
+        file = self.get_selection ()
+        if not os.path.isdir (file) :
+            if not os.access (file, R_OK) :
+                self.root.bell ()
+                file = None
+        self.quit (file)
 
 # main
 class MainWindow:
-	def __init__(self, title='', BatchFile=''):
-
-		self.root = Tk()
-		Pmw.initialise(self.root)
-		self.root.title(title)
-
-		#create balloon
-		self.balloon=Pmw.Balloon(self.root)
-
-		#set timezone to UTC
-		os.environ['TZ'] = 'GMT'
-		time.tzname = ('GMT', 'GMT')
-		time.timezone=0
-
-		#Start Global Variables
-		self.e_width = 24
-
-		#Variables, lists, dictionaries associated with traces and trace headers
-		self.OldSID = StringVar()
-		self.DataDirs = StringVar()
-		self.StatSel = StringVar()
-		self.StatSelList = []
-		self.TraceDict={}
-		self.UpdateHdrDict={}
-		self.StatChanList=[]
-		self.StationName = StringVar()
-		self.Station = StringVar()
-		self.NetCode = StringVar()
-		self.SampleRate = IntVar()
-		self.Channel = StringVar()
-		self.LocCode = StringVar()
-		self.StatChanListVars = [
-			["Stat:Chan:Loc:Net:Sps", self.StationName],
-			["Station_Name", self.Station],
-			["Channel", self.Channel],
-			["Location_Code", self.LocCode],
-			["Network_Code", self.NetCode],
-			["Sample_Rate", self.SampleRate]
-		]
-
-		#New Values on Trace Headers notebook
-		self.NStation = StringVar()
-		self.NChannel = StringVar()
-		self.NLocCode = StringVar()
-		self.NNetCode = StringVar()
-		self.NewVars = [
-			["Station_Name", self.NStation],
-			["Channel", self.NChannel],
-			["Location_Code", self.NLocCode],
-			["Network_Code", self.NNetCode]
-		]
-
-		#Modified button on Trace Headers notebook
-		#denote whether applied updates or not
-		self.SetStat = IntVar()
-		self.SetChan = IntVar()
-		self.SetLoc = IntVar()
-		self.SetNet = IntVar()
-		self.SetHdrVars = [
-			["Station_Name", self.SetStat],
-			["Channel", self.SetChan],
-			["Location_Code", self.SetLoc],
-			["Network_Code", self.SetNet]
-		]
-		self.SetHdrDict = {}
-
-		#vars used in global nb
-		self.GlobalStation = StringVar()
-		self.GlobalChannel = StringVar()
-		self.GlobalLocCode = StringVar()
-		self.GlobalSps = StringVar()
-		self.GlobalNetCode = StringVar()
-
-		#global update variables
-		self.GUStation = StringVar()
-		self.GUChannel = StringVar()
-		self.GULocCode = StringVar()
-		self.GUSps = StringVar()
-		self.GUNetCode = StringVar()
-
-		#lists for dropdown menus on Global Modify notebook
-		self.StationList=[]
-		self.ChannelList=[]
-		self.LocList=[]
-		self.NetList=[]
-		self.SpsList=[]
-
-		self.GlobalListVars = [
-			["Station_Name", self.GlobalStation, self.StationList, self.GUStation],
-			["Channel", self.GlobalChannel, self.ChannelList, self.GUChannel],
-			["Location_Code", self.GlobalLocCode, self.LocList, self.GULocCode],
-			["Network_Code", self.GlobalNetCode, self.NetList, self.GUNetCode],
-			["Sample_Rate", self.GlobalSps, self.SpsList, self.GUSps]
-		]
-
-		#vars used in TimeShift nb
-		self.TimeShiftName = StringVar()
-		self.OldShiftName = StringVar()
-		self.TSStartTime = StringVar()
-		self.TSEndTime = StringVar()
-		self.TSShift = DoubleVar()
-		self.TypeTimeCor = IntVar()
-		self.TypeTimeCor.set(0)
-		self.TimeTagQuest = StringVar()
-		self.TimeTagQuest.set("")
-		self.WildLoc = IntVar()
-		self.WildLoc.set(0)
-		self.PopUpHelp = IntVar()
-		self.PopUpHelp.set(1)
-		self.UpdateTimeDict={}
-		self.TraceTimeDict={}
-		self.SetTimeDict={}
-		self.TimeCorrectedFiles={}
-
-		self.ShiftVars = [
-			["Start_Time", self.TSStartTime],
-			["End_Time", self.TSEndTime],
-			["Time_Shift_sec", self.TSShift],
-			["Time_Tag_Quest", self.TimeTagQuest],
-			["Corr_Type", self.TypeTimeCor]
-
-		]
-
-		self.SetTime = IntVar()
-		self.SetTQuest = IntVar()
-		self.SetTimeVars = [
-			["Time_Shift_sec", self.SetTime],
-			["Time_Tag_Quest", self.SetTQuest]
-		]
-
-		#vars used in Endianess nb
-		self.Savefile = StringVar()
-		self.DataDirList = []
-		self.BigEndianList=[]
-		self.LittleEndianList=[]
-		self.NumLittleFiles=IntVar()
-		self.NumBigFiles=IntVar()
-		self.NumLittleFiles.set(0)
-		self.NumBigFiles.set(0)
-		self.ToEndian = StringVar()
-
-		#log vars and lists
-		self.LogList = [
-			["All", 0],
-			["Header", 1],
-			["Timing", 2],
-			["Endian", 3]
-		]
-
-		self.LogVar=IntVar()
-		self.LogVar.set(0)
-		self.LogAll=[]
-		self.LogHeader=[]
-		self.LogTime=[]
-		self.LogEndian=[]
-		self.LogSummary=[]
-
-		#activity and warning vars
-		self.ActiveText=StringVar()
-		self.ActiveText.set("")
-		self.AlteredText=StringVar()
-		self.AlteredText.set("")
-
-		#set of vars watched for active threading event
-		self.RunBuilddb=IntVar()
-		self.RunBuilddb.set(0)
-		self.RunModHdrs=IntVar()
-		self.RunModHdrs.set(0)
-		self.RunApplyTimeCor=IntVar()
-		self.RunApplyTimeCor.set(0)
-		self.RunChangeEndian=IntVar()
-		self.RunChangeEndian.set(0)
-		self.FoundFiles=IntVar()
-		self.RWErrors=IntVar()
-		self.CancelWarn=IntVar()
-		self.CancelWarn.set(0)
-		self.IgnoreWarn=IntVar()
-		self.IgnoreWarn.set(0)
-		self.UseNewOnlyTime=IntVar()
-		self.UseNewOnlyTime.set(0)
-
-		#if DATALOC not set on commandline set here
-		if DATALOC:
-			self.DataDirs.set(DATALOC)
-		else:
-			self.DataDirs.set(os.getcwd())
-
-		# if a batch file exists on the command line,
-		# we just run necessary processes for modifying headers
-		self.BatchFile=StringVar()
-		self.BatchFile.set(BatchFile)
-
-		# If batchmode then launch from here and exit
-		if BATCHMODE:
-			#address endian change first since unique i.e. no batchfile
-			print "Running in Batch Mode"
-			if RunEndianBatch:
-				print "Changing Endianess to: ", Endianess
-				self.ToEndian.set(Endianess)
-				self.RunChangeEndian.set(1)
-				print "Finding Files beneath directory: ", self.DataDirs.get()
-				self.BuildTrcList()
-				self.ChangeEndian()
-			else:
-				if RunTimeBatch: print "Correcting Timing"
-				if RunHeaderBatch: print "Correcting Headers"
-
-				print "Using Template: ", self.BatchFile.get()
-				self.LoadTemplate()
-				if RunTimeBatch:
-					if not self.UpdateTimeDict:
-						print "No Timing Corrections in Template.\nDone"
-						sys.exit(1)
-					print "Finding Files beneath directory: ", self.DataDirs.get()
-					self.BuildTrcList()
-					self.RunApplyTimeCor.set(1)
-					self.ApplyTimeCor()
-				if RunHeaderBatch:
-					if not self.UpdateHdrDict:
-						print "No Header Corrections in Template.\nDone"
-						sys.exit(1)
-					print "Finding Files beneath directory: ", self.DataDirs.get()
-					self.BuildTrcList()
-					self.RunModHdrs.set(1)
-					self.ModHdrs()
-			print "Done"
-			sys.exit(0)
-
-		# Build GUI
-		self.createMainButtons(self.root)
-		self.createNoteBooks(self.root)
+    def __init__(self, title='', BatchFile=''):
+
+        self.root = Tk()
+        Pmw.initialise(self.root)
+        self.root.title(title)
+
+        #create balloon
+        self.balloon=Pmw.Balloon(self.root)
+
+        #set timezone to UTC
+        os.environ['TZ'] = 'GMT'
+        time.tzname = ('GMT', 'GMT')
+        time.timezone = 0
+
+        #Start Global Variables
+        self.e_width = 24
+
+        #Variables, lists, dictionaries associated with traces and trace headers
+        self.OldSID = StringVar()
+        self.DataDirs = StringVar()
+        self.StatSel = StringVar()
+        self.StatSelList = []
+        self.TraceDict = {}
+        self.UpdateHdrDict = {}
+        self.StatChanList = []
+        self.StationName = StringVar()
+        self.Station = StringVar()
+        self.NetCode = StringVar()
+        self.SampleRate = IntVar()
+        self.Channel = StringVar()
+        self.LocCode = StringVar()
+        self.StatChanListVars = [
+            ["Stat:Chan:Loc:Net:Sps", self.StationName],
+            ["Station_Name", self.Station],
+            ["Channel", self.Channel],
+            ["Location_Code", self.LocCode],
+            ["Network_Code", self.NetCode],
+            ["Sample_Rate", self.SampleRate]
+        ]
+
+        #New Values on Trace Headers notebook
+        self.NStation = StringVar()
+        self.NChannel = StringVar()
+        self.NLocCode = StringVar()
+        self.NNetCode = StringVar()
+        self.NewVars = [
+            ["Station_Name", self.NStation],
+            ["Channel", self.NChannel],
+            ["Location_Code", self.NLocCode],
+            ["Network_Code", self.NNetCode]
+        ]
+
+        #Modified button on Trace Headers notebook
+        #denote whether applied updates or not
+        self.SetStat = IntVar()
+        self.SetChan = IntVar()
+        self.SetLoc = IntVar()
+        self.SetNet = IntVar()
+        self.SetHdrVars = [
+            ["Station_Name", self.SetStat],
+            ["Channel", self.SetChan],
+            ["Location_Code", self.SetLoc],
+            ["Network_Code", self.SetNet]
+        ]
+        self.SetHdrDict = {}
+
+        #vars used in global nb
+        self.GlobalStation = StringVar()
+        self.GlobalChannel = StringVar()
+        self.GlobalLocCode = StringVar()
+        self.GlobalSps = StringVar()
+        self.GlobalNetCode = StringVar()
+
+        #global update variables
+        self.GUStation = StringVar()
+        self.GUChannel = StringVar()
+        self.GULocCode = StringVar()
+        self.GUSps = StringVar()
+        self.GUNetCode = StringVar()
+
+        #lists for dropdown menus on Global Modify notebook
+        self.StationList = []
+        self.ChannelList = []
+        self.LocList = []
+        self.NetList = []
+        self.SpsList = []
+
+        self.GlobalListVars = [
+            ["Station_Name", self.GlobalStation, self.StationList,
+             self.GUStation],
+            ["Channel", self.GlobalChannel, self.ChannelList, self.GUChannel],
+            ["Location_Code", self.GlobalLocCode, self.LocList,
+             self.GULocCode],
+            ["Network_Code", self.GlobalNetCode, self.NetList,
+             self.GUNetCode],
+            ["Sample_Rate", self.GlobalSps, self.SpsList, self.GUSps]
+        ]
+
+        #vars used in TimeShift nb
+        self.TimeShiftName = StringVar()
+        self.OldShiftName = StringVar()
+        self.TSStartTime = StringVar()
+        self.TSEndTime = StringVar()
+        self.TSShift = DoubleVar()
+        self.TypeTimeCor = IntVar()
+        self.TypeTimeCor.set(0)
+        self.TimeTagQuest = StringVar()
+        self.TimeTagQuest.set("")
+        self.WildLoc = IntVar()
+        self.WildLoc.set(0)
+        self.PopUpHelp = IntVar()
+        self.PopUpHelp.set(1)
+        self.UpdateTimeDict = {}
+        self.TraceTimeDict = {}
+        self.SetTimeDict = {}
+        self.TimeCorrectedFiles = {}
+
+        self.ShiftVars = [
+            ["Start_Time", self.TSStartTime],
+            ["End_Time", self.TSEndTime],
+            ["Time_Shift_sec", self.TSShift],
+            ["Time_Tag_Quest", self.TimeTagQuest],
+            ["Corr_Type", self.TypeTimeCor]
+
+        ]
+
+        self.SetTime = IntVar()
+        self.SetTQuest = IntVar()
+        self.SetTimeVars = [
+            ["Time_Shift_sec", self.SetTime],
+            ["Time_Tag_Quest", self.SetTQuest]
+        ]
+
+        #vars used in Endianess nb
+        self.Savefile = StringVar()
+        self.DataDirList = []
+        self.BigEndianList = []
+        self.LittleEndianList = []
+        self.NumLittleFiles = IntVar()
+        self.NumBigFiles = IntVar()
+        self.NumLittleFiles.set(0)
+        self.NumBigFiles.set(0)
+        self.ToEndian = StringVar()
+
+        #log vars and lists
+        self.LogList = [
+            ["All", 0],
+            ["Header", 1],
+            ["Timing", 2],
+            ["Endian", 3]
+        ]
+
+        self.LogVar = IntVar()
+        self.LogVar.set(0)
+        self.LogAll = []
+        self.LogHeader = []
+        self.LogTime = []
+        self.LogEndian = []
+        self.LogSummary = []
+
+        #activity and warning vars
+        self.ActiveText = StringVar()
+        self.ActiveText.set("")
+        self.AlteredText = StringVar()
+        self.AlteredText.set("")
+
+        #set of vars watched for active threading event
+        self.RunBuilddb = IntVar()
+        self.RunBuilddb.set(0)
+        self.RunModHdrs = IntVar()
+        self.RunModHdrs.set(0)
+        self.RunApplyTimeCor = IntVar()
+        self.RunApplyTimeCor.set(0)
+        self.RunChangeEndian = IntVar()
+        self.RunChangeEndian.set(0)
+        self.FoundFiles = IntVar()
+        self.RWErrors = IntVar()
+        self.CancelWarn = IntVar()
+        self.CancelWarn.set(0)
+        self.IgnoreWarn = IntVar()
+        self.IgnoreWarn.set(0)
+        self.UseNewOnlyTime=IntVar()
+        self.UseNewOnlyTime.set(0)
+
+        #if DATALOC not set on commandline set here
+        if DATALOC:
+            self.DataDirs.set(DATALOC)
+        else:
+            self.DataDirs.set(os.getcwd())
+
+        # if a batch file exists on the command line,
+        # we just run necessary processes for modifying headers
+        self.BatchFile = StringVar()
+        self.BatchFile.set(BatchFile)
+
+        # If batchmode then launch from here and exit
+        if BATCHMODE:
+            #address endian change first since unique i.e. no batchfile
+            print("Running in Batch Mode")
+            if RunEndianBatch:
+                print("Changing Endianess to: ", Endianess)
+                self.ToEndian.set(Endianess)
+                self.RunChangeEndian.set(1)
+                print("Finding Files beneath directory: ",
+                      self.DataDirs.get())
+                self.BuildTrcList()
+                self.ChangeEndian()
+            else:
+                if RunTimeBatch:
+                    print("Correcting Timing")
+                if RunHeaderBatch:
+                    print("Correcting Headers")
+
+                print("Using Template: ", self.BatchFile.get())
+                self.LoadTemplate()
+                if RunTimeBatch:
+                    if not self.UpdateTimeDict:
+                        print("No Timing Corrections in Template.\nDone")
+                        sys.exit(1)
+                    print("Finding Files beneath directory: ",
+                          self.DataDirs.get())
+                    self.BuildTrcList()
+                    self.RunApplyTimeCor.set(1)
+                    self.ApplyTimeCor()
+                if RunHeaderBatch:
+                    if not self.UpdateHdrDict:
+                        print("No Header Corrections in Template.\nDone")
+                        sys.exit(1)
+                    print("Finding Files beneath directory: ",
+                          self.DataDirs.get())
+                    self.BuildTrcList()
+                    self.RunModHdrs.set(1)
+                    self.ModHdrs()
+            print("Done")
+            sys.exit(0)
+
+        # Build GUI
+        self.createMainButtons(self.root)
+        self.createNoteBooks(self.root)
 ########################################
-	def createMainButtons(self,master):
-		"""
-		Build buttons for root window
-		"""
-		#create info bar at bottom of root window
-		self.InfoString_l = Label(master,
-					  bg = "yellow",
-					  relief = "ridge")
-		self.InfoString_l.pack(side='bottom', fill='x')
-
-		#persistent buttons across all tabs
-		self.Button_fm = Frame(master, relief = 'groove', borderwidth = 2)
-		self.Button_fm.pack(side = 'bottom', pady=5, fill = 'x')
-
-		self.exit_b = Button(self.Button_fm,
-				     text = "Exit",
-				     relief = "ridge",
-				     cursor = 'pirate',
-				     command = Command(self.ExitCheck),
-				     activebackground= 'red',
-				     activeforeground='black')
-		self.exit_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.exit_b, "Exit Program")
-
-		self.save_b = Button(self.Button_fm,
-				     text='Save Template',
-				     relief = "ridge",
-				     activebackground='green',
-				     command=Command(self.saveWidget, master, "templ")
-				     )
-		self.save_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.save_b, "Export saved header & \ntiming corrections to file")
-
-		self.save_b = Button(self.Button_fm,
-				     text='Load Template',
-				     relief = "ridge",
-				     activebackground='green',
-				     command=Command(self.LoadTemplate)
-				     )
-		self.save_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.save_b, "Import saved header & \ntiming corrections file")
-
-
-		self.PopUpHelp_cb = Checkbutton(self.Button_fm,
-						text="PopUp Help",
-						command=self.ToggleBalloons,
-						variable=self.PopUpHelp
-						)
-		self.PopUpHelp_cb.pack(side='left')
-		self.balloon.bind(self.PopUpHelp_cb, "Toggles 'PopUp Help' on and off")
+    def createMainButtons(self,master):
+        """
+        Build buttons for root window
+        """
+        #create info bar at bottom of root window
+        self.InfoString_l = Label(master,
+                                  bg = "yellow",
+                                  relief = "ridge")
+        self.InfoString_l.pack(side='bottom', fill='x')
+
+        #persistent buttons across all tabs
+        self.Button_fm = Frame(master, relief = 'groove', borderwidth = 2)
+        self.Button_fm.pack(side = 'bottom', pady=5, fill = 'x')
+
+        self.exit_b = Button(self.Button_fm,
+                             text = "Exit",
+                             relief = "ridge",
+                             cursor = 'pirate',
+                             command = Command(self.ExitCheck),
+                             activebackground= 'red',
+                             activeforeground='black')
+        self.exit_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.exit_b, "Exit Program")
+
+        self.save_b = Button(self.Button_fm,
+                             text='Save Template',
+                             relief = "ridge",
+                             activebackground='green',
+                             command=Command(self.saveWidget, master, "templ")
+                             )
+        self.save_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.save_b, "Export saved header & \ntiming corrections to file")
+
+        self.save_b = Button(self.Button_fm,
+                             text='Load Template',
+                             relief = "ridge",
+                             activebackground='green',
+                             command=Command(self.LoadTemplate)
+                             )
+        self.save_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.save_b, "Import saved header & \ntiming corrections file")
+
+
+        self.PopUpHelp_cb = Checkbutton(self.Button_fm,
+                                        text="PopUp Help",
+                                        command=self.ToggleBalloons,
+                                        variable=self.PopUpHelp
+                                        )
+        self.PopUpHelp_cb.pack(side='left')
+        self.balloon.bind(self.PopUpHelp_cb, "Toggles 'PopUp Help' on and off")
 
 ########################################
-	def ToggleBalloons(self):
-		"""
-		turns balloon help on and off
-		"""
-		if self.PopUpHelp.get():
-			self.balloon.configure(state = 'balloon')
-		else:
-			self.balloon.configure(state = 'none')
+    def ToggleBalloons(self):
+        """
+        turns balloon help on and off
+        """
+        if self.PopUpHelp.get():
+            self.balloon.configure(state = 'balloon')
+        else:
+            self.balloon.configure(state = 'none')
 ########################################
-	def createNoteBooks(self,master):
-		"""
-		Set up notebooks in root window
-		"""
-		nb = Pmw.NoteBook(master)
-		self.buildHdrList(nb)
-		self.buildGlobal(nb)
-		self.buildTimeShift(nb)
-		self.buildEndian(nb)
-		self.buildLog(nb)
-		self.buildHelp(nb)
-		self.buildMSformat(nb)
-		nb.pack(padx=5, pady=5, fill='both', expand=1)
+    def createNoteBooks(self,master):
+        """
+        Set up notebooks in root window
+        """
+        nb = Pmw.NoteBook(master)
+        self.buildHdrList(nb)
+        self.buildGlobal(nb)
+        self.buildTimeShift(nb)
+        self.buildEndian(nb)
+        self.buildLog(nb)
+        self.buildHelp(nb)
+        self.buildMSformat(nb)
+        nb.pack(padx=5, pady=5, fill='both', expand=1)
 
 
 ##################################################################
-	def buildHdrList(self,master):
-		"""
-		Populate HdrList NoteBook
-		tab for selecting traces, building trace database, and correcting headers one key at a time
-		"""
-		self.StatChanList_nb = master.add('Trace Headers')
-
-		#buttons
-		self.Button_fm = Frame(self.StatChanList_nb, borderwidth = 2)
-		self.Button_fm.pack(side = 'bottom', padx= 5, pady=5, fill = 'x')
-		self.StatChanList_fm = Frame(self.StatChanList_nb, relief = 'groove', borderwidth = 2)
-
-		self.ClearUpdateDict_b = Button(self.Button_fm,
-						text = "Clear Update Dictionary",
-						relief = "ridge",
-						cursor = 'X_cursor',
-						command = Command(self.ClearAllTrace, 1),
-						activebackground= 'orange',
-						activeforeground='black')
-		self.ClearUpdateDict_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.ClearUpdateDict_b, "Clears all entries \nin 'Update Dictionary'")
-
-		self.clear_b = Button(self.Button_fm,
-				      text = "Clear Current",
-				      relief = "ridge",
-				      cursor = 'X_cursor',
-				      command = Command(self.ClearAllTrace),
-				      activebackground= 'orange',
-				      activeforeground='black')
-		self.clear_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.clear_b, \
-				  "Clears entries in 'Update Dictionary' \nfor selected Stat:Chan:Loc:Net:Sps")
-
-		self.ModHdr_b = Button(self.Button_fm,
-				       text = "Modify Headers",
-				       relief = "ridge",
-				       cursor = 'X_cursor',
-				       command = Command(self.LaunchModHdrs),
-				       background='lightblue',
-				       activebackground= 'green',
-				       activeforeground= 'black')
-		self.ModHdr_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.ModHdr_b, \
-				  "Modifies headers using current entries \nand all entries in 'Update Dictionary'")
-
-		self.listtrace_b = Button(self.Button_fm,
-					  text = "List Traces",
-					  relief = "ridge",
-					  cursor = 'X_cursor',
-					  command = Command(self.ListTrace, self.StatChanList_nb),
-					  activebackground= 'green',
-					  activeforeground= 'black')
-		self.listtrace_b.pack(side='left', anchor='e')
-		self.balloon.bind(self.listtrace_b, \
-				  "Lists traces for selected \nStat:Chan:Loc:Net:Sps")
-
-		#data directory find and clear buttons, and entry field
-		#button to build trace db
-		self.DataDirs_fm = Frame(self.StatChanList_nb, relief = 'groove', borderwidth = 2)
-		self.DataDirs_fm.pack(side = 'top', pady=5, fill = 'x')
-		self.DataDirs_l = Label(self.DataDirs_fm, text='Data Directories: ')
-		self.DataDirs_l.pack(side='left')
-		self.balloon.bind(self.DataDirs_l, \
-				  "Search path(s) for finding mseed files. \nColon separate multiple entries")
-
-		self.DataDirs_e = Entry(self.DataDirs_fm,
-					selectbackground = 'yellow',
-					textvariable = self.DataDirs)
-		self.DataDirs_e.pack(side='left', anchor='w',expand=1, fill='x')
-
-		self.ClearDataDir_b = Button(self.DataDirs_fm,
-					     activebackground = 'orange',
-					     relief = "ridge",
-					     text = "Clear",
-					     command = Command(self.setValue, self.DataDirs)
-					     )
-		self.ClearDataDir_b.pack(side='right')
-		self.balloon.bind(self.ClearDataDir_b, \
-				  "Clears 'Data Directories' entry")
-
-		self.FindDataDir_b = Button(self.DataDirs_fm,
-					    activebackground = 'green',
-					    relief = "ridge",
-					    text = "Find",
-					    command = Command(self.getPath, self.DataDirs, None)
-					    )
-		self.FindDataDir_b.pack(side='right')
-		self.balloon.bind(self.FindDataDir_b, \
-				  "Dialog window to \nselect Data Directories")
-
-		if not DATALOC: self.DataDirs.set(os.getcwd())
-
-		self.BuildTrcList_b = Button(self.DataDirs_fm,
-					     activebackground = 'green',
-					     relief = "ridge",
-					     background='lightblue',
-					     text = "Build Trace db",
-					     command = Command(self.BuildTrcList)
-					     )
-		self.BuildTrcList_b.pack(side='right')
-		self.balloon.bind(self.BuildTrcList_b, \
-				  "Build a Trace db using \n'Data Directories' \nas top level directories")
-
-		# station selection frame and entry box
-		self.StatSel_fm = Frame(self.StatChanList_nb, relief = 'groove', borderwidth = 2)
-		self.StatSel_fm.pack(side = 'top', pady=5, fill = 'x')
-		self.StatSel_l = Label(self.StatSel_fm, text='Find only stations (colon separated list): ')
-		self.StatSel_l.pack(side='left')
-		self.StatSel_e = Entry(self.StatSel_fm,
-				       selectbackground = 'yellow',
-				       textvariable = self.StatSel)
-		self.StatSel_e.pack(side='left', anchor='w',expand=1, fill='x')
-		self.balloon.bind(self.StatSel_e, "Filter trace search \nfor these stations")
-
-		self.ClearStatSel_b = Button(self.StatSel_fm,
-					     activebackground = 'orange',
-					     relief = "ridge",
-					     text = "Clear",
-					     command = Command(self.setValue, self.StatSel)
-					     )
-		self.ClearStatSel_b.pack(side='right')
-		self.balloon.bind(self.ClearStatSel_b, "Clear station filter")
-
-		#setup frame for station substitutions. to be filled later
-		self.StatChanList_fm.pack(side = 'top', pady = 5, fill = 'x')
+    def buildHdrList(self,master):
+        """
+        Populate HdrList NoteBook
+        tab for selecting traces, building trace database, and correcting headers one key at a time
+        """
+        self.StatChanList_nb = master.add('Trace Headers')
+
+        #buttons
+        self.Button_fm = Frame(self.StatChanList_nb, borderwidth = 2)
+        self.Button_fm.pack(side = 'bottom', padx= 5, pady=5, fill = 'x')
+        self.StatChanList_fm = Frame(self.StatChanList_nb, relief = 'groove', borderwidth = 2)
+
+        self.ClearUpdateDict_b = Button(self.Button_fm,
+                                        text = "Clear Update Dictionary",
+                                        relief = "ridge",
+                                        cursor = 'X_cursor',
+                                        command = Command(self.ClearAllTrace, 1),
+                                        activebackground= 'orange',
+                                        activeforeground='black')
+        self.ClearUpdateDict_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.ClearUpdateDict_b, "Clears all entries \nin 'Update Dictionary'")
+
+        self.clear_b = Button(self.Button_fm,
+                              text = "Clear Current",
+                              relief = "ridge",
+                              cursor = 'X_cursor',
+                              command = Command(self.ClearAllTrace),
+                              activebackground= 'orange',
+                              activeforeground='black')
+        self.clear_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.clear_b, \
+                          "Clears entries in 'Update Dictionary' \nfor selected Stat:Chan:Loc:Net:Sps")
+
+        self.ModHdr_b = Button(self.Button_fm,
+                               text = "Modify Headers",
+                               relief = "ridge",
+                               cursor = 'X_cursor',
+                               command = Command(self.LaunchModHdrs),
+                               background='lightblue',
+                               activebackground= 'green',
+                               activeforeground= 'black')
+        self.ModHdr_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.ModHdr_b, \
+                          "Modifies headers using current entries \nand all entries in 'Update Dictionary'")
+
+        self.listtrace_b = Button(self.Button_fm,
+                                  text = "List Traces",
+                                  relief = "ridge",
+                                  cursor = 'X_cursor',
+                                  command = Command(self.ListTrace, self.StatChanList_nb),
+                                  activebackground= 'green',
+                                  activeforeground= 'black')
+        self.listtrace_b.pack(side='left', anchor='e')
+        self.balloon.bind(self.listtrace_b, \
+                          "Lists traces for selected \nStat:Chan:Loc:Net:Sps")
+
+        #data directory find and clear buttons, and entry field
+        #button to build trace db
+        self.DataDirs_fm = Frame(self.StatChanList_nb, relief = 'groove', borderwidth = 2)
+        self.DataDirs_fm.pack(side = 'top', pady=5, fill = 'x')
+        self.DataDirs_l = Label(self.DataDirs_fm, text='Data Directories: ')
+        self.DataDirs_l.pack(side='left')
+        self.balloon.bind(self.DataDirs_l, \
+                          "Search path(s) for finding mseed files. \nColon separate multiple entries")
+
+        self.DataDirs_e = Entry(self.DataDirs_fm,
+                                selectbackground = 'yellow',
+                                textvariable = self.DataDirs)
+        self.DataDirs_e.pack(side='left', anchor='w',expand=1, fill='x')
+
+        self.ClearDataDir_b = Button(self.DataDirs_fm,
+                                     activebackground = 'orange',
+                                     relief = "ridge",
+                                     text = "Clear",
+                                     command = Command(self.setValue, self.DataDirs)
+                                     )
+        self.ClearDataDir_b.pack(side='right')
+        self.balloon.bind(self.ClearDataDir_b, \
+                          "Clears 'Data Directories' entry")
+
+        self.FindDataDir_b = Button(self.DataDirs_fm,
+                                    activebackground = 'green',
+                                    relief = "ridge",
+                                    text = "Find",
+                                    command = Command(self.getPath, self.DataDirs, None)
+                                    )
+        self.FindDataDir_b.pack(side='right')
+        self.balloon.bind(self.FindDataDir_b, \
+                          "Dialog window to \nselect Data Directories")
+
+        if not DATALOC: self.DataDirs.set(os.getcwd())
+
+        self.BuildTrcList_b = Button(self.DataDirs_fm,
+                                     activebackground = 'green',
+                                     relief = "ridge",
+                                     background='lightblue',
+                                     text = "Build Trace db",
+                                     command = Command(self.BuildTrcList)
+                                     )
+        self.BuildTrcList_b.pack(side='right')
+        self.balloon.bind(self.BuildTrcList_b, \
+                          "Build a Trace db using \n'Data Directories' \nas top level directories")
+
+        # station selection frame and entry box
+        self.StatSel_fm = Frame(self.StatChanList_nb, relief = 'groove', borderwidth = 2)
+        self.StatSel_fm.pack(side = 'top', pady=5, fill = 'x')
+        self.StatSel_l = Label(self.StatSel_fm, text='Find only stations (colon separated list): ')
+        self.StatSel_l.pack(side='left')
+        self.StatSel_e = Entry(self.StatSel_fm,
+                               selectbackground = 'yellow',
+                               textvariable = self.StatSel)
+        self.StatSel_e.pack(side='left', anchor='w',expand=1, fill='x')
+        self.balloon.bind(self.StatSel_e, "Filter trace search \nfor these stations")
+
+        self.ClearStatSel_b = Button(self.StatSel_fm,
+                                     activebackground = 'orange',
+                                     relief = "ridge",
+                                     text = "Clear",
+                                     command = Command(self.setValue, self.StatSel)
+                                     )
+        self.ClearStatSel_b.pack(side='right')
+        self.balloon.bind(self.ClearStatSel_b, "Clear station filter")
+
+        #setup frame for station substitutions. to be filled later
+        self.StatChanList_fm.pack(side = 'top', pady = 5, fill = 'x')
 
 ##################################################################
-	def buildGlobal(self,master):
-		"""
-		Populate Global NoteBook for making global changes to headers
-		"""
-		self.GlobalFix_nb = master.add('Global Modify')
-
-		self.Button_fm = Frame(self.GlobalFix_nb, borderwidth = 2)
-		self.Button_fm.pack(side = 'bottom', padx= 5, pady=5, fill = 'x')
-		self.GlobalFix_fm = Frame(self.GlobalFix_nb, relief = 'groove', borderwidth = 2)
-
-		#buttons
-		self.ClearUpdateDict_b = Button(self.Button_fm,
-						text = "Clear Update Dictionary",
-						relief = "ridge",
-						cursor = 'X_cursor',
-						command = Command(self.ClearAllTrace, 1),
-						activebackground= 'orange',
-						activeforeground='black')
-		self.ClearUpdateDict_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.ClearUpdateDict_b, "Clears all entries \nin 'Update Dictionary'")
-
-		self.clear_b = Button(self.Button_fm,
-				      text = "Clear Current",
-				      relief = "ridge",
-				      cursor = 'X_cursor',
-				      command = Command(self.ClearAllGlobal, self.GlobalListVars),
-				      activebackground= 'orange',
-				      activeforeground='black')
-		self.clear_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.clear_b, "Clears all \ncurrent entries")
-
-		self.GlobalSet_b = Button(self.Button_fm,
-					  text = "Global Set",
-					  relief = "ridge",
-					  cursor = 'X_cursor',
-					  command = Command(self.GlobalSet),
-					  background='lightblue',
-					  activebackground= 'green',
-					  activeforeground= 'black')
-		self.GlobalSet_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.GlobalSet_b, "Add current entries \nto 'Update Dictionary'")
-
-		#we let user see directory selection here but they don't have
-		#access to manipulation buttons found on Trace Headers notebook
-		self.DataDirs_fm = Frame(self.GlobalFix_nb, relief = 'groove', borderwidth = 2)
-		self.DataDirs_fm.pack(side = 'top', pady=5, fill = 'x')
-		self.DataDirs_l = Label(self.DataDirs_fm, text='Current Data Directories: ')
-		self.DataDirs_l.pack(side='left')
-		self.balloon.bind(self.DataDirs_l, "Traces located \nbeneath these \ndirectories")
-
-		self.DataDirs_e = Entry(self.DataDirs_fm,
-					selectbackground = 'yellow',
-					textvariable = self.DataDirs)
-		self.DataDirs_e.pack(side='left', anchor='w',expand=1, fill='x')
-
-		#setup frame for global substitutions. to be filled later
-		self.GlobalFix_fm.pack(side = 'top', pady = 5, fill = 'x')
+    def buildGlobal(self,master):
+        """
+        Populate Global NoteBook for making global changes to headers
+        """
+        self.GlobalFix_nb = master.add('Global Modify')
+
+        self.Button_fm = Frame(self.GlobalFix_nb, borderwidth = 2)
+        self.Button_fm.pack(side = 'bottom', padx= 5, pady=5, fill = 'x')
+        self.GlobalFix_fm = Frame(self.GlobalFix_nb, relief = 'groove', borderwidth = 2)
+
+        #buttons
+        self.ClearUpdateDict_b = Button(self.Button_fm,
+                                        text = "Clear Update Dictionary",
+                                        relief = "ridge",
+                                        cursor = 'X_cursor',
+                                        command = Command(
+                                            self.ClearAllTrace, 1),
+                                        activebackground= 'orange',
+                                        activeforeground='black')
+        self.ClearUpdateDict_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.ClearUpdateDict_b, "Clears all entries \nin 'Update Dictionary'")
+
+        self.clear_b = Button(self.Button_fm,
+                              text = "Clear Current",
+                              relief = "ridge",
+                              cursor = 'X_cursor',
+                              command = Command(
+                                  self.ClearAllGlobal, self.GlobalListVars),
+                              activebackground= 'orange',
+                              activeforeground='black')
+        self.clear_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.clear_b, "Clears all \ncurrent entries")
+
+        self.GlobalSet_b = Button(self.Button_fm,
+                                  text = "Global Set",
+                                  relief = "ridge",
+                                  cursor = 'X_cursor',
+                                  command = Command(self.GlobalSet),
+                                  background='lightblue',
+                                  activebackground= 'green',
+                                  activeforeground= 'black')
+        self.GlobalSet_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.GlobalSet_b,
+                          "Add current entries \nto 'Update Dictionary'")
+
+        #we let user see directory selection here but they don't have
+        #access to manipulation buttons found on Trace Headers notebook
+        self.DataDirs_fm = Frame(
+            self.GlobalFix_nb, relief = 'groove', borderwidth = 2)
+        self.DataDirs_fm.pack(side = 'top', pady=5, fill = 'x')
+        self.DataDirs_l = Label(
+            self.DataDirs_fm, text='Current Data Directories: ')
+        self.DataDirs_l.pack(side='left')
+        self.balloon.bind(self.DataDirs_l,
+                          "Traces located \nbeneath these \ndirectories")
+
+        self.DataDirs_e = Entry(self.DataDirs_fm,
+                                selectbackground = 'yellow',
+                                textvariable = self.DataDirs)
+        self.DataDirs_e.pack(side='left', anchor='w',expand=1, fill='x')
+
+        #setup frame for global substitutions. to be filled later
+        self.GlobalFix_fm.pack(side = 'top', pady = 5, fill = 'x')
 
 ##################################################################
-	def buildTimeShift(self,master):
-		"""
-		Populate Time Shift NoteBook for applying time corrections to headers
-		"""
-		self.TimeShift_nb = master.add('Time Shift')
-
-		self.Button_fm = Frame(self.TimeShift_nb, borderwidth = 2)
-		self.Button_fm.pack(side = 'bottom', padx= 5, pady=5, fill = 'x')
-		self.TimeShift_fm = Frame(self.TimeShift_nb, relief = 'groove', borderwidth = 2)
-
-		#buttons
-		self.clear_b = Button(self.Button_fm,
-				      text = "Clear All",
-				      relief = "ridge",
-				      cursor = 'X_cursor',
-				      command = Command(self.ResetTimeShift),
-				      activebackground= 'orange',
-				      activeforeground='black')
-		self.clear_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.clear_b, "Clears all \ncurrent entries")
-
-		self.ReCalc_b = Button(self.Button_fm,
-				       text = "Recalc Start/End",
-				       relief = "ridge",
-				       cursor = 'X_cursor',
-				       command = Command(self.RecalcStartEnd),
-				       background='lightblue',
-				       activebackground= 'green',
-				       activeforeground= 'black')
-		self.ReCalc_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.ReCalc_b, "Recalculate start and \nend times for selected traces")
-
-		self.TimeSet_b = Button(self.Button_fm,
-					text = "Time Set",
-					relief = "ridge",
-					cursor = 'X_cursor',
-					command = Command(self.TimeDictSet),
-					background='lightblue',
-					activebackground= 'green',
-					activeforeground= 'black')
-		self.TimeSet_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.TimeSet_b, "Add current entries \nto 'Update Dictionary'")
-
-		self.ApplyTime_b = Button(self.Button_fm,
-					  text = "Apply Time Correction",
-					  relief = "ridge",
-					  cursor = 'X_cursor',
-					  command = Command(self.LaunchApplyTimeCor),
-					  background='lightblue',
-					  activebackground= 'green',
-					  activeforeground= 'black')
-		self.ApplyTime_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.ApplyTime_b, \
-				  "Modifies trace times using current entries \nand all entries in 'Update Dictionary'")
-
-		self.listtimecor_b = Button(self.Button_fm,
-					    text = "List Time Corrections",
-					    relief = "ridge",
-					    cursor = 'X_cursor',
-					    command = Command(self.ListTimeCor, self.TimeShift_nb),
-					    activebackground= 'green',
-					    activeforeground= 'black')
-		self.listtimecor_b.pack(side='left', anchor='e')
-		self.balloon.bind(self.listtimecor_b, "List time corrections \ncurrently in trace headers \nfor select Stat:Loc:Net")
-
-		#we let user see directory selection here but they don't have
-		#access to manipulation buttons found on Trace Headers notebook
-		self.DataDirs_fm = Frame(self.TimeShift_nb, relief = 'groove', borderwidth = 2)
-		self.DataDirs_fm.pack(side = 'top', pady=5, fill = 'x')
-		self.DataDirs_l = Label(self.DataDirs_fm, text='Current Data Directories: ')
-		self.DataDirs_l.pack(side='left')
-		self.balloon.bind(self.DataDirs_l, "Traces located \nbeneath these \ndirectories")
-
-		self.DataDirs_e = Entry(self.DataDirs_fm,
-					selectbackground = 'yellow',
-					textvariable = self.DataDirs)
-		self.DataDirs_e.pack(side='left', anchor='w',expand=1, fill='x')
-
-		#time correction type buttons
-		self.RadButtons_fm = Frame(self.TimeShift_nb, relief = 'groove', borderwidth = 2)
-		self.RadButtons_fm.pack(side = 'top', pady=5, fill = 'x')
-
-		self.UndoTimeCor_b = Button(self.RadButtons_fm,
-					    text = "Undo Time Corrections",
-					    relief = "ridge",
-					    cursor = 'X_cursor',
-					    command = Command(self.LaunchUndoTimeCor),
-					    background='lightblue',
-					    activebackground= 'green',
-					    activeforeground= 'black')
-		self.UndoTimeCor_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.UndoTimeCor_b, "Reverse applied \ntime corrections")
-
-
-		self.TimeRad_l=Label(self.RadButtons_fm,
-				     text="How to Treat Existing Corrections:")
-		self.TimeRad_l.pack(side='left', anchor='e')
-		self.balloon.bind(self.TimeRad_l, "When applying time corrections: \nAdd to existing or \nZero and replace existing")
-		for text, value in (["Add To",0],["Replace",1]):
-			Radiobutton(self.RadButtons_fm,
-				    text=text,
-				    value=value,
-				    variable=self.TypeTimeCor).pack(side='left', anchor='e')
-
-		#setup frame for global substitutions. to be filled later
-		self.TimeShift_fm.pack(side = 'top', pady = 5, fill = 'x')
+    def buildTimeShift(self,master):
+        """
+        Populate Time Shift NoteBook for applying time corrections to headers
+        """
+        self.TimeShift_nb = master.add('Time Shift')
+
+        self.Button_fm = Frame(self.TimeShift_nb, borderwidth = 2)
+        self.Button_fm.pack(side = 'bottom', padx= 5, pady=5, fill = 'x')
+        self.TimeShift_fm = Frame(self.TimeShift_nb, relief = 'groove', borderwidth = 2)
+
+        #buttons
+        self.clear_b = Button(self.Button_fm,
+                              text = "Clear All",
+                              relief = "ridge",
+                              cursor = 'X_cursor',
+                              command = Command(self.ResetTimeShift),
+                              activebackground= 'orange',
+                              activeforeground='black')
+        self.clear_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.clear_b, "Clears all \ncurrent entries")
+
+        self.ReCalc_b = Button(self.Button_fm,
+                               text = "Recalc Start/End",
+                               relief = "ridge",
+                               cursor = 'X_cursor',
+                               command = Command(self.RecalcStartEnd),
+                               background='lightblue',
+                               activebackground= 'green',
+                               activeforeground= 'black')
+        self.ReCalc_b.pack(side='right', anchor='e')
+        self.balloon.bind(
+            self.ReCalc_b,
+            "Recalculate start and \nend times for selected traces")
+
+        self.TimeSet_b = Button(self.Button_fm,
+                                text = "Time Set",
+                                relief = "ridge",
+                                cursor = 'X_cursor',
+                                command = Command(self.TimeDictSet),
+                                background='lightblue',
+                                activebackground= 'green',
+                                activeforeground= 'black')
+        self.TimeSet_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.TimeSet_b,
+                          "Add current entries \nto 'Update Dictionary'")
+
+        self.ApplyTime_b = Button(self.Button_fm,
+                                  text = "Apply Time Correction",
+                                  relief = "ridge",
+                                  cursor = 'X_cursor',
+                                  command = Command(self.LaunchApplyTimeCor),
+                                  background='lightblue',
+                                  activebackground= 'green',
+                                  activeforeground= 'black')
+        self.ApplyTime_b.pack(side='right', anchor='e')
+        self.balloon.bind(
+            self.ApplyTime_b, "Modifies trace times using current entries "
+            "\nand all entries in 'Update Dictionary'")
+
+        self.listtimecor_b = Button(self.Button_fm,
+                                    text = "List Time Corrections",
+                                    relief = "ridge",
+                                    cursor = 'X_cursor',
+                                    command = Command(
+                                        self.ListTimeCor, self.TimeShift_nb),
+                                    activebackground= 'green',
+                                    activeforeground= 'black')
+        self.listtimecor_b.pack(side='left', anchor='e')
+        self.balloon.bind(
+            self.listtimecor_b, "List time corrections \ncurrently in trace "
+            "headers \nfor select Stat:Loc:Net")
+
+        #we let user see directory selection here but they don't have
+        #access to manipulation buttons found on Trace Headers notebook
+        self.DataDirs_fm = Frame(
+            self.TimeShift_nb, relief = 'groove', borderwidth = 2)
+        self.DataDirs_fm.pack(side = 'top', pady=5, fill = 'x')
+        self.DataDirs_l = Label(
+            self.DataDirs_fm, text='Current Data Directories: ')
+        self.DataDirs_l.pack(side='left')
+        self.balloon.bind(self.DataDirs_l,
+                          "Traces located \nbeneath these \ndirectories")
+
+        self.DataDirs_e = Entry(self.DataDirs_fm,
+                                selectbackground = 'yellow',
+                                textvariable = self.DataDirs)
+        self.DataDirs_e.pack(side='left', anchor='w',expand=1, fill='x')
+
+        #time correction type buttons
+        self.RadButtons_fm = Frame(
+            self.TimeShift_nb, relief = 'groove', borderwidth = 2)
+        self.RadButtons_fm.pack(side = 'top', pady=5, fill = 'x')
+
+        self.UndoTimeCor_b = Button(self.RadButtons_fm,
+                                    text = "Undo Time Corrections",
+                                    relief = "ridge",
+                                    cursor = 'X_cursor',
+                                    command = Command(self.LaunchUndoTimeCor),
+                                    background='lightblue',
+                                    activebackground= 'green',
+                                    activeforeground= 'black')
+        self.UndoTimeCor_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.UndoTimeCor_b,
+                          "Reverse applied \ntime corrections")
+
+
+        self.TimeRad_l=Label(self.RadButtons_fm,
+                             text="How to Treat Existing Corrections:")
+        self.TimeRad_l.pack(side='left', anchor='e')
+        self.balloon.bind(
+            self.TimeRad_l, "When applying time corrections: \nAdd to "
+            "existing or \nZero and replace existing")
+        for text, value in (["Add To",0],["Replace",1]):
+            Radiobutton(
+                self.RadButtons_fm, text=text,value=value,
+                variable=self.TypeTimeCor).pack(side='left', anchor='e')
+
+        #setup frame for global substitutions. to be filled later
+        self.TimeShift_fm.pack(side = 'top', pady = 5, fill = 'x')
 
 ##################################################################
-	def buildEndian(self,master):
-		"""
-		Populate Endian NoteBook for swapping endianess of headers
-		"""
-		self.Endian_nb = master.add('Endianess')
-
-		self.Endian_fm = Frame(self.Endian_nb, relief = 'groove', borderwidth = 2)
-
-		#buttons
-		self.ToBig_b = Button(self.Endian_fm,
-				      text = "Convert to Big",
-				      relief = "ridge",
-				      cursor = 'X_cursor',
-				      command = Command(self.LaunchChangeEndian, "big"),
-				      background='lightblue',
-				      activebackground= 'green',
-				      activeforeground= 'black')
-		self.ToBig_b.grid(row=1, column=3, sticky=W)
-		self.balloon.bind(self.ToBig_b, "Convert all little \nendian files to \nbig endian")
-
-		Label(self.Endian_fm, text="Little Endian Files Found: ").grid(row=1, column=1, sticky=W)
-		Entry(self.Endian_fm,
-		      width = 8,
-		      relief = "flat",
-		      justify = "right",
-		      background = 'yellow',
-		      textvariable = self.NumLittleFiles).grid(row=1, column=2, sticky=W)
-
-		self.ToLittle_b = Button(self.Endian_fm,
-					 text = "Convert to Little",
-					 relief = "ridge",
-					 cursor = 'X_cursor',
-					 command = Command(self.LaunchChangeEndian, "little"),
-					 background='lightblue',
-					 activebackground= 'green',
-					 activeforeground= 'black')
-		self.ToLittle_b.grid(row=2, column=3, sticky=W)
-		self.balloon.bind(self.ToLittle_b, "Convert all big \nendian files to \nlittle endian")
-
-		Label(self.Endian_fm, text="Big Endian Files Found: ").grid(row=2, column=1, sticky=W)
-		Entry(self.Endian_fm,
-		      width = 8,
-		      relief = "flat",
-		      justify = "right",
-		      background = 'yellow',
-		      textvariable = self.NumBigFiles).grid(row=2, column=2, sticky=W)
-
-		#we let user see directory selection here but they don't have
-		#access to manipulation buttons found on Trace Headers notebook
-		self.DataDirs_fm = Frame(self.Endian_nb, relief = 'groove', borderwidth = 2)
-		self.DataDirs_fm.pack(side = 'top', pady=5, fill = 'x')
-		self.DataDirs_l = Label(self.DataDirs_fm, text='Current Data Directories: ')
-		self.DataDirs_l.pack(side='left')
-		self.balloon.bind(self.DataDirs_l, "Traces located \nbeneath these \ndirectories")
-
-		self.DataDirs_e = Entry(self.DataDirs_fm,
-					selectbackground = 'yellow',
-					textvariable = self.DataDirs)
-		self.DataDirs_e.pack(side='left', anchor='w',expand=1, fill='x')
-
-		self.Endian_fm.pack(side = 'top', pady = 5, fill = 'x')
+    def buildEndian(self,master):
+        """
+        Populate Endian NoteBook for swapping endianess of headers
+        """
+        self.Endian_nb = master.add('Endianess')
+
+        self.Endian_fm = Frame(self.Endian_nb, relief = 'groove', borderwidth = 2)
+
+        #buttons
+        self.ToBig_b = Button(self.Endian_fm,
+                              text = "Convert to Big",
+                              relief = "ridge",
+                              cursor = 'X_cursor',
+                              command = Command(
+                                  self.LaunchChangeEndian, "big"),
+                              background='lightblue',
+                              activebackground= 'green',
+                              activeforeground= 'black')
+        self.ToBig_b.grid(row=1, column=3, sticky=W)
+        self.balloon.bind(self.ToBig_b,
+                          "Convert all little \nendian files to \nbig endian")
+
+        Label(self.Endian_fm, text="Little Endian Files Found: ").grid(
+            row=1, column=1, sticky=W)
+        Entry(self.Endian_fm,
+              width = 8,
+              relief = "flat",
+              justify = "right",
+              background = 'yellow',
+              textvariable = self.NumLittleFiles).grid(
+                  row=1, column=2, sticky=W)
+
+        self.ToLittle_b = Button(self.Endian_fm,
+                                 text = "Convert to Little",
+                                 relief = "ridge",
+                                 cursor = 'X_cursor',
+                                 command = Command(
+                                     self.LaunchChangeEndian, "little"),
+                                 background='lightblue',
+                                 activebackground= 'green',
+                                 activeforeground= 'black')
+        self.ToLittle_b.grid(row=2, column=3, sticky=W)
+        self.balloon.bind(self.ToLittle_b,
+                          "Convert all big \nendian files to \nlittle endian")
+
+        Label(self.Endian_fm, text="Big Endian Files Found: ").grid(
+            row=2, column=1, sticky=W)
+        Entry(self.Endian_fm,
+              width = 8,
+              relief = "flat",
+              justify = "right",
+              background = 'yellow',
+              textvariable = self.NumBigFiles).grid(row=2, column=2, sticky=W)
+
+        #we let user see directory selection here but they don't have
+        #access to manipulation buttons found on Trace Headers notebook
+        self.DataDirs_fm = Frame(
+            self.Endian_nb, relief = 'groove', borderwidth = 2)
+        self.DataDirs_fm.pack(side = 'top', pady=5, fill = 'x')
+        self.DataDirs_l = Label(
+            self.DataDirs_fm, text='Current Data Directories: ')
+        self.DataDirs_l.pack(side='left')
+        self.balloon.bind(self.DataDirs_l,
+                          "Traces located \nbeneath these \ndirectories")
+
+        self.DataDirs_e = Entry(self.DataDirs_fm,
+                                selectbackground = 'yellow',
+                                textvariable = self.DataDirs)
+        self.DataDirs_e.pack(side='left', anchor='w',expand=1, fill='x')
+
+        self.Endian_fm.pack(side = 'top', pady = 5, fill = 'x')
 
 ##################################################################
-	def buildLog(self,master):
-		"""
-		Populate Log NoteBook for keeping track of changes
-		"""
-		self.Log_nb = master.add('Log')
-		self.Log_fm = Frame(self.Log_nb, relief='groove', borderwidth=2)
-		self.Log_fm.pack(side='top', pady=5, fill='x')
-
-		self.LogText = Pmw.ScrolledText(self.Log_nb,
-						borderframe=1)
-
-		#log_filters
-		self.RadButtons_fm = Frame(self.Log_nb, relief = 'groove', borderwidth = 2)
-		self.RadButtons_fm.pack(side = 'top', pady=5, fill = 'x')
-		self.DisplayLog_l = Label(self.RadButtons_fm, text='Display messages for: ')
-		self.DisplayLog_l.pack(side='left')
-		self.balloon.bind(self.DisplayLog_l, "Filter log messages")
-
-		for text, value in self.LogList:
-			Radiobutton(self.RadButtons_fm,
-				    text=text,
-				    value=value,
-				    command=Command(self.DisplayLog),
-				    variable=self.LogVar).pack(side='left', anchor='e')
-
-		#buttons
-		self.Clear_b = Button(self.Log_fm,
-				      text='Clear Logs',
-				      relief='ridge',
-				      activebackground='red',
-				      command=Command(self.FlushLogs)
-				      )
-		self.Clear_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.Clear_b, "Delete all \nlog messages")
-
-		self.Save_b = Button(self.Log_fm,
-				     text='Save Log File',
-				     relief='ridge',
-				     activebackground='green',
-				     command=Command(self.saveWidget, self.Log_nb, "log")
-				     )
-		self.Save_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.Save_b, "Save log \nmessages to file")
-
-		self.dump_b = Button(self.Log_fm,
-				     text='Print Update Dict',
-				     relief='ridge',
-				     background='lightblue',
-				     activebackground='green',
-				     command=Command(self.DumpUpdateDicts, "dump")
-				     )
-		self.dump_b.pack(side='right', anchor='e')
-		self.balloon.bind(self.dump_b, "Print 'Update Dictionary' \nto log message window")
-
-		self.LogText.pack(side='bottom', fill='both', expand=1)
-
-		#tags used for highlighting log entries
-		self.LogText.tag_config('blue', foreground='blue')
-		self.LogText.tag_config('dkgreen', foreground='darkgreen')
-		self.LogText.tag_config('red', foreground='red')
-		self.LogText.tag_config('black', foreground='black')
+    def buildLog(self,master):
+        """
+        Populate Log NoteBook for keeping track of changes
+        """
+        self.Log_nb = master.add('Log')
+        self.Log_fm = Frame(self.Log_nb, relief='groove', borderwidth=2)
+        self.Log_fm.pack(side='top', pady=5, fill='x')
+
+        self.LogText = Pmw.ScrolledText(self.Log_nb,
+                                        borderframe=1)
+
+        #log_filters
+        self.RadButtons_fm = Frame(
+            self.Log_nb, relief = 'groove', borderwidth = 2)
+        self.RadButtons_fm.pack(side = 'top', pady=5, fill = 'x')
+        self.DisplayLog_l = Label(
+            self.RadButtons_fm, text='Display messages for: ')
+        self.DisplayLog_l.pack(side='left')
+        self.balloon.bind(self.DisplayLog_l, "Filter log messages")
+
+        for text, value in self.LogList:
+            Radiobutton(self.RadButtons_fm,
+                        text=text,
+                        value=value,
+                        command=Command(self.DisplayLog),
+                        variable=self.LogVar).pack(side='left', anchor='e')
+
+        #buttons
+        self.Clear_b = Button(self.Log_fm,
+                              text='Clear Logs',
+                              relief='ridge',
+                              activebackground='red',
+                              command=Command(self.FlushLogs)
+                              )
+        self.Clear_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.Clear_b, "Delete all \nlog messages")
+
+        self.Save_b = Button(self.Log_fm,
+                             text='Save Log File',
+                             relief='ridge',
+                             activebackground='green',
+                             command=Command(
+                                 self.saveWidget, self.Log_nb, "log")
+                             )
+        self.Save_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.Save_b, "Save log \nmessages to file")
+
+        self.dump_b = Button(self.Log_fm,
+                             text='Print Update Dict',
+                             relief='ridge',
+                             background='lightblue',
+                             activebackground='green',
+                             command=Command(self.DumpUpdateDicts, "dump")
+                             )
+        self.dump_b.pack(side='right', anchor='e')
+        self.balloon.bind(self.dump_b,
+                          "Print 'Update Dictionary' \nto log message window")
+
+        self.LogText.pack(side='bottom', fill='both', expand=1)
+
+        #tags used for highlighting log entries
+        self.LogText.tag_config('blue', foreground='blue')
+        self.LogText.tag_config('dkgreen', foreground='darkgreen')
+        self.LogText.tag_config('red', foreground='red')
+        self.LogText.tag_config('black', foreground='black')
 
 ##################################################################
-	def BuildLists(self):
-		"""
-		builds lists drop downs in global modify and timeshift notebook
-		"""
-
-		#clean any old entries
-		del self.StationList[:]
-		del self.ChannelList[:]
-		del self.LocList[:]
-		del self.NetList[:]
-		del self.SpsList[:]
-
-		#build lists for drop down selections
-		for key in self.TraceDict.keys() :
-			(stat,chan,loc,net,sps)= string.split(key, ":")
-			if stat not in self.StationList:
-				self.StationList.append(stat)
-			if not self.ChannelList.count(chan):
-				self.ChannelList.append(chan)
-			if not self.LocList.count(loc):
-				self.LocList.append(loc)
-			if not self.NetList.count(net):
-				self.NetList.append(net)
-			if not self.SpsList.count(sps):
-				self.SpsList.append(sps)
-
-		#add wildcard entry
-		self.StationList.append("*")
-		self.ChannelList.append("*")
-		self.LocList.append("*")
-		self.NetList.append("*")
-		self.SpsList.append("*")
-
-		#sort lists
-		self.StationList.sort()
-		self.ChannelList.sort()
-		self.LocList.sort()
-		self.NetList.sort()
-		self.SpsList.sort()
+    def BuildLists(self):
+        """
+        builds lists drop downs in global modify and timeshift notebook
+        """
+
+        #clean any old entries
+        del self.StationList[:]
+        del self.ChannelList[:]
+        del self.LocList[:]
+        del self.NetList[:]
+        del self.SpsList[:]
+
+        #build lists for drop down selections
+        for key in self.TraceDict :
+            (stat,chan,loc,net,sps) = key.split(":")
+            if stat not in self.StationList:
+                self.StationList.append(stat)
+            if not self.ChannelList.count(chan):
+                self.ChannelList.append(chan)
+            if not self.LocList.count(loc):
+                self.LocList.append(loc)
+            if not self.NetList.count(net):
+                self.NetList.append(net)
+            if not self.SpsList.count(sps):
+                self.SpsList.append(sps)
+
+        #add wildcard entry
+        self.StationList.append("*")
+        self.ChannelList.append("*")
+        self.LocList.append("*")
+        self.NetList.append("*")
+        self.SpsList.append("*")
+
+        #sort lists
+        self.StationList = sorted(self.StationList)
+        self.ChannelList = sorted(self.ChannelList)
+        self.LocList = sorted(self.LocList)
+        self.NetList = sorted(self.NetList)
+        self.SpsList = sorted(self.SpsList)
 
 #######################################
-	def BuildTrcList(self):
-		"""
-		build a trace list using DataDirList as base directories
-		"""
-		# clear infostring
-		self.addTextInfoBar()
-
-
-		#kill warn window if it exist (i.e. user got here from self.Ignore)
-		#this may not longer be necessary
-		try:
-			self.killWindow(self.WarnWidget_tl)
-		except:
-			pass
-
-		#initialize lists
-		self.DataDirList = []
-		self.StatSelList = []
-		self.BigEndianList=[]
-		self.LittleEndianList=[]
-		self.TimeCorrectedFiles={}
-		n=0
-
-		# split directory string & test they exist before launching into self.FindTrace
-		# populate DataDirList
-		for idir in string.split(self.DataDirs.get(), ":") :
-			dirlist = glob(idir)
-			for newdir in dirlist:
-				if not os.path.isdir(newdir):
-					err="***WARNING*** Directory " + newdir + " not found."
-					self.addTextInfoBar(err, "red")
-					return
-				self.DataDirList.append(newdir)
-
-		# split station select list if it exists
-		if self.StatSel.get() == "*" or self.StatSel.get() == "":
-			pass
-		else:
-			for statsel in string.split(self.StatSel.get(), ":") :
-				statsel=string.strip(statsel)
-				self.StatSelList.append(statsel)
-
-		# find & ID traces in DataDirList, setup various list for nb's
-		# first I set self.RunBuilddb so we know that this is running and I have
-		# a variable to watch status of process
-		# next I spawn a thread to FindTrace
-		self.RunBuilddb.set(1)
-		#tRun=threading.Thread(target=self.LaunchFindTrace)
-		self.LaunchFindTrace()
-		#tRun.start()
-		# stay here until thread dies
-		#tRun.join()
-
-		#fill/update notebooks if not running batch mode
-		if not BATCHMODE:
-			info="Building lists, updating frames"
-			self.addTextInfoBar(info)
-			self.UpdateHdrList(self.StatChanList_fm)
-			self.BuildLists()
-			self.UpdateTimeShift(self.TimeShift_fm)
-			self.UpdateGlobalList(self.GlobalFix_fm)
-			self.NumBigFiles.set(len(self.BigEndianList))
-			self.NumLittleFiles.set(len(self.LittleEndianList))
-			#clear any lingering updates
-			self.UpdateHdrDict={}
-			self.SetHdrDict={}
-			self.UpdateTimeDict={}
-			self.SetTimeDict={}
-		self.ClearAll(self.SetHdrVars)
-		self.ClearAll(self.NewVars)
-		text= "\n" + str(self.FoundFiles.get()) + " unique mseed files found. *** " \
-		    + str(self.RWErrors.get()) + " files with errors. See Log."
-		self.addTextInfoBar(text, "green")
-		self.root.bell()
-
-		#insert info on Log notebook
-		if not BATCHMODE:
-			self.WriteLog("\n<Build Trace db>", "All", "blue")
-			dirs = "Directories searched: " + self.DataDirs.get()
-			self.WriteLog(dirs,"All","black")
-			self.WriteLog(text,"All","black")
-			if self.StatChanList:
-				self.WriteLog("\t<Unique ID's found:>","All", "dkgreen")
-				for item in self.StatChanList:
-					self.WriteLog("\t"+item,"All", "black")
-				self.WriteLog("\t<end>","All", "dkgreen")
-			self.WriteLog("<end>","All", "blue")
-
-		#since we just rebuilt db no files have been altered
-		self.AlteredText.set("")
-		return
+    def BuildTrcList(self):
+        """
+        build a trace list using DataDirList as base directories
+        """
+        # clear infostring
+        self.addTextInfoBar()
+
+
+        #kill warn window if it exist (i.e. user got here from self.Ignore)
+        #this may not longer be necessary
+        try:
+            self.killWindow(self.WarnWidget_tl)
+        except Exception as e:
+            pass
+
+        #initialize lists
+        self.DataDirList = []
+        self.StatSelList = []
+        self.BigEndianList=[]
+        self.LittleEndianList=[]
+        self.TimeCorrectedFiles={}
+        n = 0
+
+        # split directory string & test they exist before launching into
+        # self.FindTrace
+        # populate DataDirList
+        for idir in self.DataDirs.get().split(":") :
+            dirlist = glob(idir)
+            for newdir in dirlist:
+                if not os.path.isdir(newdir):
+                    err="***WARNING*** Directory " + newdir + " not found."
+                    self.addTextInfoBar(err, "red")
+                    return
+                self.DataDirList.append(newdir)
+
+        # split station select list if it exists
+        if self.StatSel.get() == "*" or self.StatSel.get() == "":
+            pass
+        else:
+            for statsel in self.StatSel.get().split(":") :
+                statsel = statsel.strip()
+                self.StatSelList.append(statsel)
+
+        # find & ID traces in DataDirList, setup various list for nb's
+        # first I set self.RunBuilddb so we know that this is running and I
+        #    have a variable to watch status of process
+        # next I spawn a thread to FindTrace
+        self.RunBuilddb.set(1)
+        #tRun=threading.Thread(target=self.LaunchFindTrace)
+        self.LaunchFindTrace()
+        #tRun.start()
+        # stay here until thread dies
+        #tRun.join()
+
+        #fill/update notebooks if not running batch mode
+        if not BATCHMODE:
+            info = "Building lists, updating frames"
+            self.addTextInfoBar(info)
+            self.UpdateHdrList(self.StatChanList_fm)
+            self.BuildLists()
+            self.UpdateTimeShift(self.TimeShift_fm)
+            self.UpdateGlobalList(self.GlobalFix_fm)
+            self.NumBigFiles.set(len(self.BigEndianList))
+            self.NumLittleFiles.set(len(self.LittleEndianList))
+            #clear any lingering updates
+            self.UpdateHdrDict = {}
+            self.SetHdrDict = {}
+            self.UpdateTimeDict = {}
+            self.SetTimeDict = {}
+        self.ClearAll(self.SetHdrVars)
+        self.ClearAll(self.NewVars)
+        text= "\n" + str(self.FoundFiles.get()) + \
+            " unique mseed files found. *** " \
+            + str(self.RWErrors.get()) + " files with errors. See Log."
+        self.addTextInfoBar(text, "green")
+        self.root.bell()
+
+        #insert info on Log notebook
+        if not BATCHMODE:
+            self.WriteLog("\n<Build Trace db>", "All", "blue")
+            dirs = "Directories searched: " + self.DataDirs.get()
+            self.WriteLog(dirs,"All","black")
+            self.WriteLog(text,"All","black")
+            if self.StatChanList:
+                self.WriteLog("\t<Unique ID's found:>","All", "dkgreen")
+                for item in self.StatChanList:
+                    self.WriteLog("\t"+item,"All", "black")
+                self.WriteLog("\t<end>","All", "dkgreen")
+            self.WriteLog("<end>","All", "blue")
+
+        #since we just rebuilt db no files have been altered
+        self.AlteredText.set("")
+        return
 
 #######################################
-	def LaunchFindTrace(self) :
-		"""
-		separated out so FindTrace could be run as a thread
+    def LaunchFindTrace(self) :
+        """
+        separated out so FindTrace could be run as a thread
 
-		"""
-		if not BATCHMODE:
-			self.CancelTL(self.RunBuilddb, "Build Trace db")
+        """
+        if not BATCHMODE:
+            self.CancelTL(self.RunBuilddb, "Build Trace db")
 
-		(self.TraceDict, self.TraceTimeDict, NumFiles,rwError) = self.FindTrace(self.DataDirList)
+        (self.TraceDict, self.TraceTimeDict, NumFiles,rwError) = \
+            self.FindTrace(self.DataDirList)
 
-		if self.RunBuilddb.get() and not BATCHMODE:
-			self.KillCancelTL(self.RunBuilddb)
-		self.ActiveText.set("")
-		self.FoundFiles.set(NumFiles)
-		self.RWErrors.set(rwError)
-		return
+        if self.RunBuilddb.get() and not BATCHMODE:
+            self.KillCancelTL(self.RunBuilddb)
+        self.ActiveText.set("")
+        self.FoundFiles.set(NumFiles)
+        self.RWErrors.set(rwError)
+        return
 
 #######################################
-	def FindTrace(self, DataDir) :
-		"""
-		based on traverse routine in "python standard library", Lundh pg 34
-		"""
-		#local variables
-		stack=[]
-		lstrip=string.strip
-		ljoin=string.join
-		losjoin=os.path.join
-		losaccess=os.access
-		loslistdir=os.listdir
-		losisdir=os.path.isdir
-		losislink=os.path.islink
-		losisfile=os.path.isfile
-		stackappend=stack.append
-		stackpop=stack.pop
-		appendBigEndian=self.BigEndianList.append
-		appendLittleEndian=self.LittleEndianList.append
-		# build stack of input directories
-		for k in range(len(DataDir)) :
-			if not DataDir[k] in stack:
-				stackappend(DataDir[k])
-		# init several list and dictionaries
-		files = []
-		file_list = {}
-		time_list = {}
-		NumMseedFiles=0
-		rwError=0
-		cnt=1
-
-		#loop while directories still exist in stack
-		while stack :
-			directory = stackpop()
-			if not losaccess(directory, 5):
-				text = "Skipped: %s" % directory
-				text1 = "\t\tAccess Error"
-				self.WriteLog(text,"All","red")
-				self.WriteLog(text1,"All","black")
-				continue
-
-			try:
-				genfiles=(ifile for ifile in loslistdir(directory))
-			except StandardError, e:
-				print "Directory Read Error: %s" % e
-				continue
-
-			while 1:
-				try:
-					file=genfiles.next()
-				except StopIteration:
-					break
-
-				#respond to a cancel request
-				if not self.RunBuilddb.get():
-					break
-				# keep user posted of progress
-				if mod(cnt, 10):
-					pass
-				else:
-					self.wait("Examining File: ", cnt)
-				#build up list of mseed files w/ full pathnames
-				fullname = losjoin(directory, file)
-				if losisfile(fullname) :
-					if not losaccess(fullname, 6):
-						err= "ERROR: Read/Write permission denied. \n\t File:" + fullname
-						self.WriteLog(err,"Header","red")
-						rwError+=1
-						continue
-
-					try:
-						msfile = Mseed(fullname)
-						if msfile.isMseed() :
-
-							try:
-								#simple test to determine if correct size file
-								filesize=msfile.filesize
-								blksize=msfile.blksize
-								numblocks=msfile.numblocks
-							except:
-								err= "ERROR: Cannot determine file and block sizes. \n\t File:" + fullname
-								self.WriteLog(err,"Header","red")
-								rwError+=1
-								continue
-							#assign header info
-							type=msfile.type
-							rate=msfile.rate
-							time=msfile.time
-							stat=lstrip(msfile.FH.Stat)
-							chan=lstrip(msfile.FH.Chan)
-							loc=lstrip(msfile.FH.Loc)
-							net=lstrip(msfile.FH.Net)
-
-							#window on specific stations if exist
-							if self.StatSelList:
-								if not stat in self.StatSelList:
-									continue
-
-							# build endian lists
-							if msfile.byteorder == "big":
-								if not fullname in self.BigEndianList:
-									appendBigEndian(fullname)
-							else:
-								if not fullname in self.LittleEndianList:
-									appendLittleEndian(fullname)
-
-							#build file list for fixing headers
-							fileid=ljoin(map(str,(stat,chan,loc,net,rate)),":")
-#							fileid= str(stat) + ":" + chan + ":" + loc + ":" + net + \
-#								":" + str(rate)
-							try:
-								if not fullname in file_list[fileid]:
-									file_list[fileid].append(fullname)
-									NumMseedFiles+=1
-							except KeyError:
-								file_list[fileid] = []
-								file_list[fileid].append(fullname)
-								NumMseedFiles+=1
-
-							# build empty time_list to fill later with GetStartEnd
-							timeid=ljoin(map(str,(stat,loc,net)),":")
-#							timeid=str(stat) + ":" + loc + ":" + net
-#							if not time_list.has_key(timeid) :
-							time_list[timeid] = []
-
-						msfile.close()
-					except StandardError, e:
-						print "File Open Error: %s" % e
-						print fullname
-				cnt+=1
-
-				# add fullname to stack if it is a directory or link
-				if losisdir(fullname) or (losislink(fullname) and not losisfile(fullname)):
-					if not fullname in stack:
-						stackappend(fullname)
-		return file_list, time_list, NumMseedFiles, rwError
+    def FindTrace(self, DataDir) :
+        """
+        based on traverse routine in "python standard library", Lundh pg 34
+        """
+        #local variables
+        stack = []
+        losjoin = os.path.join
+        losaccess = os.access
+        loslistdir = os.listdir
+        losisdir = os.path.isdir
+        losislink = os.path.islink
+        losisfile = os.path.isfile
+        stackappend = stack.append
+        stackpop = stack.pop
+        appendBigEndian = self.BigEndianList.append
+        appendLittleEndian = self.LittleEndianList.append
+        # build stack of input directories
+        for k in range(len(DataDir)) :
+            if not DataDir[k] in stack:
+                stackappend(DataDir[k])
+        # init several list and dictionaries
+        files = []
+        file_list = {}
+        time_list = {}
+        NumMseedFiles = 0
+        rwError=0
+        cnt=1
+
+        #loop while directories still exist in stack
+        while stack :
+            directory = stackpop()
+            if not losaccess(directory, 5):
+                text = "Skipped: %s" % directory
+                text1 = "\t\tAccess Error"
+                self.WriteLog(text,"All","red")
+                self.WriteLog(text1,"All","black")
+                continue
+
+            try:
+                genfiles=(ifile for ifile in loslistdir(directory))
+            except StandardError as e:
+                print("Directory Read Error: %s" % e)
+                continue
+
+            while 1:
+                try:
+                    file = next(genfiles)
+                except StopIteration:
+                    break
+
+                #respond to a cancel request
+                if not self.RunBuilddb.get():
+                    break
+                # keep user posted of progress
+                if mod(cnt, 10):
+                    pass
+                else:
+                    self.wait("Examining File: ", cnt)
+                #build up list of mseed files w/ full pathnames
+                fullname = losjoin(directory, file)
+                if losisfile(fullname) :
+                    if not losaccess(fullname, 6):
+                        err= "ERROR: Read/Write permission denied. "\
+                            "\n\t File:" + fullname
+                        self.WriteLog(err,"Header","red")
+                        rwError+=1
+                        continue
+
+                    try:
+                        msfile = Mseed(fullname)
+                        if msfile.isMseed() :
+                            try:
+                                #simple test to determine if correct size file
+                                filesize = msfile.filesize
+                                blksize = msfile.blksize
+                                numblocks = msfile.numblocks
+                            except Exception as e:
+                                err= "ERROR: Cannot determine file and block"\
+                                    " sizes. \n\t File:" + fullname
+                                self.WriteLog(err,"Header","red")
+                                rwError+=1
+                                continue
+                            #assign header info
+                            type = msfile.type
+                            rate = msfile.rate
+                            time = msfile.time
+                            stat = msfile.FH.Stat.decode().strip()
+                            chan = msfile.FH.Chan.decode().strip()
+                            loc = msfile.FH.Loc.decode().strip()
+                            net = msfile.FH.Net.decode().strip()
+
+                            #window on specific stations if exist
+                            if self.StatSelList:
+                                if not stat in self.StatSelList:
+                                    continue
+
+                            # build endian lists
+                            if msfile.byteorder == "big":
+                                if not fullname in self.BigEndianList:
+                                    appendBigEndian(fullname)
+                            else:
+                                if not fullname in self.LittleEndianList:
+                                    appendLittleEndian(fullname)
+
+                            #build file list for fixing headers
+                            fileid = ":".join(map(str,(
+                                stat,chan,loc,net,rate)))
+                            #fileid= str(stat) + ":" + chan + ":" + loc + ":"\
+                            #   + net + ":" + str(rate)
+                            try:
+                                if not fullname in file_list[fileid]:
+                                    file_list[fileid].append(fullname)
+                                    NumMseedFiles+=1
+                            except KeyError:
+                                file_list[fileid] = []
+                                file_list[fileid].append(fullname)
+                                NumMseedFiles+=1
+
+                            # build empty time_list to fill later with
+                            # GetStartEnd
+                            timeid = ":".join(map(str,(stat,loc,net)),)
+                            #timeid = ":".join(map(str,(stat,loc,net)),)
+                            #timeid=str(stat) + ":" + loc + ":" + net
+                            #if not time_list.has_key(timeid) :
+                            time_list[timeid] = []
+
+                        msfile.close()
+                    except StandardError as e:
+                        print("File Open Error: %s" % e)
+                        print(fullname)
+                cnt+=1
+
+                # add fullname to stack if it is a directory or link
+                if losisdir(fullname) or (losislink(fullname) \
+                                          and not losisfile(fullname)):
+                    if not fullname in stack:
+                        stackappend(fullname)
+        return file_list, time_list, NumMseedFiles, rwError
 
 ##################################################################
-	def UpdateHdrList(self,fm):
-		"""
-		create HdrList entries
-		This is extracted from the buildHdrList to allow for
-		dynamic update of header list
-		"""
-		#build list for stat:chan:loc:net:sps selection dropdown
-		self.StatChanList=self.TraceDict.keys()
-		#for n in self.TraceDict.keys() :
-			#self.StatChanList.append(n)
-		self.StatChanList.sort()
-		self.ClearAll(self.StatChanListVars)
-		if not self.StatChanList:
-			self.addTextInfoBar("No Data Found", 'orange')
-
-		#build dropdown and entry boxes
-		n=0
-		for var in self.StatChanListVars:
-			Label(fm, text=var[0]).grid(row=n, sticky=W)
-			if var[0] == "Stat:Chan:Loc:Net:Sps":
-				Pmw.ComboBox(fm,
-					     history=0,
-					     entry_width=self.e_width,
-					     entry_textvariable=self.StationName,
-					     selectioncommand=Command(self.UpdateHdr),
-					     scrolledlist_items=(self.StatChanList)
-					     ).grid(row=n, column=1, sticky=W)
-				Label(fm, text="New Values").grid(row=n, column=2, sticky=W)
-				Label(fm, text="Applied").grid(row=n, column=3, sticky=W)
-			else :
-				Entry(fm,
-				      width = self.e_width,
-				      selectbackground = 'yellow',
-				      textvariable = var[1]).grid(row=n, column=1, sticky=W)
-
-				if 1<=n and n <=4 :
-					Entry(fm,
-					      width = self.e_width,
-					      selectbackground = 'yellow',
-					      textvariable = self.NewVars[n-1][1]).grid(row=n, column=2, sticky=W)
-			n+=1
-
-		#build boxes indicating if update is applied
-		n=1
-		for var in self.SetHdrVars:
-			Checkbutton(fm,
-				    variable = var[1],
-				    text = "   ",
-				    indicatoron = "FALSE",
-				    selectcolor = "green",
-				    state = "disabled"
-				    ).grid(row=n, column=3)
-			n+=1
+    def UpdateHdrList(self,fm):
+        """
+        create HdrList entries
+        This is extracted from the buildHdrList to allow for
+        dynamic update of header list
+        """
+        #build list for stat:chan:loc:net:sps selection dropdown
+        self.StatChanList = sorted(list(self.TraceDict.keys()))
+        self.ClearAll(self.StatChanListVars)
+        if not self.StatChanList:
+            self.addTextInfoBar("No Data Found", 'orange')
+
+        #build dropdown and entry boxes
+        n=0
+        for var in self.StatChanListVars:
+            Label(fm, text=var[0]).grid(row=n, sticky=W)
+            if var[0] == "Stat:Chan:Loc:Net:Sps":
+                Pmw.ComboBox(fm,
+                             history=0,
+                             entry_width=self.e_width,
+                             entry_textvariable=self.StationName,
+                             selectioncommand=Command(self.UpdateHdr),
+                             scrolledlist_items=(self.StatChanList)
+                             ).grid(row=n, column=1, sticky=W)
+                Label(fm, text="New Values").grid(row=n, column=2, sticky=W)
+                Label(fm, text="Applied").grid(row=n, column=3, sticky=W)
+            else :
+                Entry(fm,
+                      width = self.e_width,
+                      selectbackground = 'yellow',
+                      textvariable = var[1]).grid(row=n, column=1, sticky=W)
+
+                if 1<=n and n <=4 :
+                    Entry(fm,
+                          width = self.e_width,
+                          selectbackground = 'yellow',
+                          textvariable = self.NewVars[n-1][1]).grid(
+                              row=n, column=2, sticky=W)
+            n+=1
+
+        #build boxes indicating if update is applied
+        n=1
+        for var in self.SetHdrVars:
+            Checkbutton(fm,
+                        variable = var[1],
+                        text = "   ",
+                        indicatoron = "FALSE",
+                        selectcolor = "green",
+                        state = "disabled"
+                        ).grid(row=n, column=3)
+            n+=1
 
 #########################################
-	def UpdateHdr(self, name=""):
-		"""
-		builds UpdateHdrDict based on entries in NewValues
-		enters current header values in appropriate fields
-		"""
-		# assign new values to UpdateHdrDict
-		for var in self.NewVars:
-			testkey = self.OldSID.get()
-			if self.UpdateHdrDict.has_key(testkey) :
-				if var[1].get():
-					value=string.upper(var[1].get())
-					if self.UpdateHdrDict[testkey].has_key(var[0]):
-						if self.UpdateHdrDict[testkey][var[0]] != value:
-							if self.SetHdrDict.has_key(testkey):
-								if self.SetHdrDict[testkey].has_key(var[0]):
-									del self.SetHdrDict[testkey][var[0]]
-					self.UpdateHdrDict[testkey][var[0]]=value
-			else :
-				if var[1].get() :
-					self.UpdateHdrDict[testkey] = {}
-					value=string.upper(var[1].get())
-					self.UpdateHdrDict[testkey][var[0]]=value
-		self.ClearAll(self.NewVars)
-
-		# populate current header listing with new selection
-		if name:
-			n=0
-			for var in self.StatChanListVars:
-				if n == 0:
-					self.setValue(var[1], name)
-				else:
-					setval= string.split(name, ":")[n-1]
-					self.setValue(var[1], setval)
-				n+=1
-
-		# populate new values with UpdateHdrDict if exists for new selection
-		if self.UpdateHdrDict.has_key(name):
-			for var in self.NewVars:
-				if self.UpdateHdrDict[name].has_key(var[0]):
-					setval = self.UpdateHdrDict[name][var[0]]
-					self.setValue(var[1], setval)
-
-		#fill in Applied buttons
-		self.ClearAll(self.SetHdrVars)
-		if self.SetHdrDict.has_key(name):
-			for var in self.SetHdrVars:
-				if self.SetHdrDict[name].has_key(var[0]):
-					setval =self.SetHdrDict[name][var[0]]
-					self.setValue(var[1], setval)
-		self.OldSID.set(name)
-
-		# if TopLevel tracelist window is open, update it
-		try:
-			if self.TraceList_tl.winfo_exists():
-				self.ListTrace(self.StatChanList_nb)
-		except:
-			pass
-
-		# give user info on traces selected
-		if name:
-			cnt=len(self.TraceDict[name])
-			textstr = str(cnt) + " traces selected for key: " + name
-			self.addTextInfoBar(textstr, 'lightblue')
+    def UpdateHdr(self, name=""):
+        """
+        builds UpdateHdrDict based on entries in NewValues
+        enters current header values in appropriate fields
+        """
+        # assign new values to UpdateHdrDict
+        for var in self.NewVars:
+            testkey = self.OldSID.get()
+            if testkey in self.UpdateHdrDict :
+                if var[1].get():
+                    value = var[1].get().upper()
+                    if var[0] in self.UpdateHdrDict[testkey]:
+                        if self.UpdateHdrDict[testkey][var[0]] != value:
+                            if testkey in self.SetHdrDict:
+                                if var[0] in self.SetHdrDict[testkey]:
+                                    del self.SetHdrDict[testkey][var[0]]
+                    self.UpdateHdrDict[testkey][var[0]]=value
+            else :
+                if var[1].get() :
+                    self.UpdateHdrDict[testkey] = {}
+                    value = var[1].get().upper()
+                    self.UpdateHdrDict[testkey][var[0]]=value
+        self.ClearAll(self.NewVars)
+
+        # populate current header listing with new selection
+        if name:
+            n = 0
+            for var in self.StatChanListVars:
+                if n == 0:
+                    self.setValue(var[1], name)
+                else:
+                    setval = name.split(":")[n-1]
+                    self.setValue(var[1], setval)
+                n += 1
+
+        # populate new values with UpdateHdrDict if exists for new selection
+        if name in self.UpdateHdrDict:
+            for var in self.NewVars:
+                if var[0] in self.UpdateHdrDict[name]:
+                    setval = self.UpdateHdrDict[name][var[0]]
+                    self.setValue(var[1], setval)
+
+        #fill in Applied buttons
+        self.ClearAll(self.SetHdrVars)
+        if name in self.SetHdrDict:
+            for var in self.SetHdrVars:
+                if var[0] in self.SetHdrDict[name]:
+                    setval =self.SetHdrDict[name][var[0]]
+                    self.setValue(var[1], setval)
+        self.OldSID.set(name)
+
+        # if TopLevel tracelist window is open, update it
+        try:
+            if self.TraceList_tl.winfo_exists():
+                self.ListTrace(self.StatChanList_nb)
+        except Exception as e:
+            pass
+
+        # give user info on traces selected
+        if name:
+            cnt = len(self.TraceDict[name])
+            textstr = str(cnt) + " traces selected for key: " + name
+            self.addTextInfoBar(textstr, 'lightblue')
 
 #######################################
-	def LaunchModHdrs(self) :
-		"""
-		separated out so ModHdrs could be run as a thread
-
-		"""
-
-		#if headers have already been alterred warn user
-		if self.SetHdrDict.keys() or self.SetTimeDict.keys():
-			self.WarnWidget(self.StatChanList_nb, "headers")
-			self.WarnWidget_tl.wait_window()
-			if not self.IgnoreWarn.get():
-				return
-			elif self.CancelWarn.get():
-				return
-
-		#if the user ignores warning proceed
-		self.RunModHdrs.set(1)
-
-		#mRun=threading.Thread(target=self.ModHdrs)
-		self.ModHdrs()
-		#mRun.start()
-		# stay here until thread dies
-		#mRun.join()
-
-		if self.RunModHdrs.get():
-			self.KillCancelTL(self.RunModHdrs)
-		self.IgnoreWarn.set(0)
+    def LaunchModHdrs(self) :
+        """
+        separated out so ModHdrs could be run as a thread
+
+        """
+
+        #if headers have already been alterred warn user
+        if self.SetHdrDict or self.SetTimeDict:
+            self.WarnWidget(self.StatChanList_nb, "headers")
+            self.WarnWidget_tl.wait_window()
+            if not self.IgnoreWarn.get():
+                return
+            elif self.CancelWarn.get():
+                return
+
+        #if the user ignores warning proceed
+        self.RunModHdrs.set(1)
+
+        #mRun=threading.Thread(target=self.ModHdrs)
+        self.ModHdrs()
+        #mRun.start()
+        # stay here until thread dies
+        #mRun.join()
+
+        if self.RunModHdrs.get():
+            self.KillCancelTL(self.RunModHdrs)
+        self.IgnoreWarn.set(0)
 
 #######################################
-	def ModHdrs(self):
-		"""
-		uses values in UpdateHdrDict to modify headers for traces in
-		TraceDict
-		"""
-		ljoin=string.join
-		if not BATCHMODE:
-			self.CancelTL(self.RunModHdrs, "Modify Headers")
-			self.addTextInfoBar()
-
-			# first make sure any current 'new values' are saved to UpdateHdrDict
-			self.UpdateHdr(self.StationName.get())
-			if not self.StationName.get() and not self.UpdateHdrDict:
-				self.addTextInfoBar("No Station Selected", 'orange')
-				return
-			elif not self.UpdateHdrDict:
-				self.addTextInfoBar("No Updates Specified", 'orange')
-				return
-
-		self.ActiveText.set("Modify Headers Running")
-		self.AlteredText.set("Headers or blockette times have been modified.\n Rebuild database to avoid unexpected results.\n")
-
-		# now make mods to headers for all keys (sta:chan:loc:net:sps) in
-		# UpdateHdrDict
-		cnt=0
-		error_cnt=0
-		warn_cnt=0
-		inlist = self.UpdateHdrDict.keys()
-		inlist.sort()
-		for key in inlist:
-			if not self.SetHdrDict.has_key(key):
-				self.SetHdrDict[key]={}
-			if self.TraceDict.has_key(key) :
-				#set new values if exist and keep track
-				#of modifications in SetHdrDict
-				Stat=Loc=Chan=Net=""
-				skeylist=(skey for skey in self.UpdateHdrDict[key].keys())
-				while 1:
-					try:
-						subkey=skeylist.next()
-					except StopIteration:
-						break
-#				for subkey in self.UpdateHdrDict[key].keys() :
-					value=self.UpdateHdrDict[key][subkey]
-					if subkey == "Station_Name":
-						Stat=value
-						self.SetHdrDict[key][subkey]=1
-					if subkey == "Channel":
-						Chan=value
-						self.SetHdrDict[key][subkey]=1
-					if subkey == "Location_Code":
-						Loc=value
-						self.SetHdrDict[key][subkey]=1
-					if subkey == "Network_Code":
-						Net=value
-						self.SetHdrDict[key][subkey]=1
-				ifilelist=(ifile for ifile in self.TraceDict[key])
-#				for infile in self.TraceDict[key] :
-					#respond to cancel requests
-				while 1:
-					try:
-						infile=ifilelist.next()
-					except StopIteration:
-						break
-					if not self.RunModHdrs.get():
-						break
-					cnt+=1
-					if mod(cnt, 10):
-						pass
-					else:
-						self.wait("Modifying Trace: ", cnt)
-
-					#determine file size and get block size from Blockette 1000
-					msfile=Mseed(infile)
-					filesize=msfile.filesize
-					blksize=msfile.blksize
-					numblocks=msfile.numblocks
-					#(numblocks, odd_size)=divmod(filesize, blksize)
-					## should not be needed, but not expensive
-					#if odd_size:
-						#warn="WARNING: File size is not an integer number of block size ("\
-							#+ str(blksize) +"). File: " + infile
-						#self.WriteLog(warn,"Header","red")
-						#warn_cnt+=1
-
-					# loop over all blocks and correct headers
-					blk=0
-					while blk < numblocks:
-						hdrs=msfile.fixedhdr(blk*blksize)
-						(SeqNum, DHQual, res, oldStat, oldLoc, oldChan, oldNet)=hdrs[0]
-						if not Stat: Stat=oldStat
-						if not Loc: Loc=oldLoc
-						if not Chan: Chan=oldChan
-						if not Net: Net=oldNet
-						newhdrs=((SeqNum, DHQual, res, Stat, Loc, Chan, Net), hdrs[1], hdrs[2], hdrs[3])
-						bytes_written = msfile.WriteFixedHdr(newhdrs, blk*blksize)
-						blk+=1
-					msfile.close()
-
-		#do some cleanup
-		self.ClearAll(self.StatChanListVars)
-		self.ClearAll(self.SetHdrVars)
-		self.ClearAll(self.NewVars)
-		if error_cnt or warn_cnt:
-			text= ljoin(("Modified Headers in ",str(cnt - error_cnt) ," files. Encountered " ,\
-				     str(error_cnt)," error(s) & ",str(warn_cnt)," warning(s)"), SPACE)
-			self.addTextInfoBar(text, "orange")
-		else:
-			text= ljoin(("Modified Headers in ",str(cnt)," files"), SPACE)
-			self.addTextInfoBar(text, "green")
-
-		#insert info on Log notebook
-		self.WriteLog("\n<Modify Headers>", "Header", "blue")
-		if error_cnt or warn_cnt:
-			self.WriteLog(text , "Header", "red")
-		else:
-			self.WriteLog(text, "Header", "black")
-		self.DumpUpdateDicts("mod")
-		self.WriteLog("<end>", "Header", "blue")
-
-		self.ActiveText.set("")
+    def ModHdrs(self):
+        """
+        uses values in UpdateHdrDict to modify headers for traces in
+        TraceDict
+        """
+        if not BATCHMODE:
+            self.CancelTL(self.RunModHdrs, "Modify Headers")
+            self.addTextInfoBar()
+
+            # first make sure any current 'new values' are saved to UpdateHdrDict
+            self.UpdateHdr(self.StationName.get())
+            if not self.StationName.get() and not self.UpdateHdrDict:
+                self.addTextInfoBar("No Station Selected", 'orange')
+                return
+            elif not self.UpdateHdrDict:
+                self.addTextInfoBar("No Updates Specified", 'orange')
+                return
+
+        self.ActiveText.set("Modify Headers Running")
+        self.AlteredText.set("Headers or blockette times have been modified.\n Rebuild database to avoid unexpected results.\n")
+
+        # now make mods to headers for all keys (sta:chan:loc:net:sps) in
+        # UpdateHdrDict
+        cnt = 0
+        error_cnt = 0
+        warn_cnt = 0
+        inlist = sorted(list(self.UpdateHdrDict.keys()))
+        for key in inlist:
+            if key not in self.SetHdrDict:
+                self.SetHdrDict[key] = {}
+            if key in self.TraceDict :
+                #set new values if exist and keep track
+                #of modifications in SetHdrDict
+                Stat = Loc = Chan = Net = ""
+                skeylist = (skey for skey in self.UpdateHdrDict[key])
+                while 1:
+                    try:
+                        subkey = next(skeylist)
+                    except StopIteration:
+                        break
+                    #for subkey in self.UpdateHdrDict[key].keys() :
+                    value = self.UpdateHdrDict[key][subkey]
+                    if subkey == "Station_Name":
+                        Stat = value
+                        self.SetHdrDict[key][subkey]=1
+                    if subkey == "Channel":
+                        Chan = value
+                        self.SetHdrDict[key][subkey]=1
+                    if subkey == "Location_Code":
+                        Loc = value
+                        self.SetHdrDict[key][subkey]=1
+                    if subkey == "Network_Code":
+                        Net = value
+                        self.SetHdrDict[key][subkey]=1
+                ifilelist=(ifile for ifile in self.TraceDict[key])
+                    #for infile in self.TraceDict[key] :
+                #respond to cancel requests
+                while 1:
+                    try:
+                        infile = next(ifilelist)
+                    except StopIteration:
+                        break
+                    if not self.RunModHdrs.get():
+                        break
+                    cnt += 1
+                    if mod(cnt, 10):
+                        pass
+                    else:
+                        self.wait("Modifying Trace: ", cnt)
+
+                    # determine file size and get block size from
+                    # Blockette 1000
+                    msfile = Mseed(infile)
+                    filesize = msfile.filesize
+                    blksize = msfile.blksize
+                    numblocks = msfile.numblocks
+                    #(numblocks, odd_size)=divmod(filesize, blksize)
+                    ## should not be needed, but not expensive
+                    #if odd_size:
+                        #warn="WARNING: File size is not an integer number "\
+                        # "of block size (+ str(blksize) +"). File: " + infile
+                        #self.WriteLog(warn,"Header","red")
+                        #warn_cnt+=1
+
+                    # loop over all blocks and correct headers
+                    blk = 0
+                    while blk < numblocks:
+                        hdrs = msfile.fixedhdr(blk*blksize)
+                        (SeqNum, DHQual, res, oldStat, oldLoc, oldChan,
+                         oldNet) = hdrs[0]
+                        if not Stat:
+                            Stat = oldStat
+                        if not Loc:
+                            Loc = oldLoc
+                        if not Chan:
+                            Chan = oldChan
+                        if not Net:
+                            Net = oldNet
+                        newhdrs = ((SeqNum, DHQual, res, Stat, Loc, Chan,
+                                    Net), hdrs[1], hdrs[2], hdrs[3])
+                        bytes_written = msfile.WriteFixedHdr(
+                            newhdrs, blk*blksize)
+                        blk += 1
+                    msfile.close()
+
+        #do some cleanup
+        self.ClearAll(self.StatChanListVars)
+        self.ClearAll(self.SetHdrVars)
+        self.ClearAll(self.NewVars)
+        if error_cnt or warn_cnt:
+            text = SPACE.join(("Modified Headers in ", str(cnt - error_cnt),
+                              " files. Encountered " , str(error_cnt),
+                              " error(s) & ", str(warn_cnt)," warning(s)"))
+            self.addTextInfoBar(text, "orange")
+        else:
+            text = SPACE.join(("Modified Headers in ",str(cnt)," files"))
+            self.addTextInfoBar(text, "green")
+
+        #insert info on Log notebook
+        self.WriteLog("\n<Modify Headers>", "Header", "blue")
+        if error_cnt or warn_cnt:
+            self.WriteLog(text , "Header", "red")
+        else:
+            self.WriteLog(text, "Header", "black")
+        self.DumpUpdateDicts("mod")
+        self.WriteLog("<end>", "Header", "blue")
+
+        self.ActiveText.set("")
 
 ##################################################################
 
-	def UpdateGlobalList(self, fm):
-		"""
-		builds drop downs for global modify notebook
-		"""
-
-		#build drop down and new entries
-		Label(fm, text="For Headers Matching:").grid(row=0, column=1, sticky=W)
-		Label(fm, text="Substitute Values:").grid(row=0, column=2, sticky=W)
-		n=1
-		for var in self.GlobalListVars:
-			Label(fm, text=var[0]).grid(row=n, sticky=W)
-			Pmw.ComboBox(fm,
-				     history=0,
-				     entry_width=self.e_width,
-				     entry_textvariable=var[1],
-				     scrolledlist_items=(var[2])
-				     ).grid(row=n, column=1, sticky=W)
-			if var[0] != "Sample_Rate" :
-				Entry(fm,
-				      width = self.e_width,
-				      selectbackground = 'yellow',
-				      textvariable = var[3]).grid(row=n, column=2, sticky=W)
-			#set wildcard as default
-			var[1].set("*")
-			n+=1
+    def UpdateGlobalList(self, fm):
+        """
+        builds drop downs for global modify notebook
+        """
+
+        #build drop down and new entries
+        Label(fm, text="For Headers Matching:").grid(
+            row=0, column=1, sticky=W)
+        Label(fm, text="Substitute Values:").grid(row=0, column=2, sticky=W)
+        n=1
+        for var in self.GlobalListVars:
+            Label(fm, text=var[0]).grid(row=n, sticky=W)
+            Pmw.ComboBox(fm,
+                         history=0,
+                         entry_width=self.e_width,
+                         entry_textvariable=var[1],
+                         scrolledlist_items=(var[2])
+                         ).grid(row=n, column=1, sticky=W)
+            if var[0] != "Sample_Rate" :
+                Entry(fm,
+                      width = self.e_width,
+                      selectbackground = 'yellow',
+                      textvariable = var[3]).grid(row=n, column=2, sticky=W)
+            #set wildcard as default
+            var[1].set("*")
+            n+=1
 
 #######################################
-	def GlobalSet(self):
-		"""
-		build UpdateHdrDict
-		"""
-		self.addTextInfoBar()
-		#check if mods are enterred
-		if not self.GUStation.get() \
-		   and not self.GUChannel.get() \
-		   and not self.GULocCode.get() \
-		   and not self.GUNetCode.get():
-			self.addTextInfoBar("No 'Substitute Values' Given", 'orange')
-			return
-
-		for key in self.TraceDict.keys():
-			#make sure there are no lingering NewVars
-			self.ClearAll(self.NewVars)
-			(stat,chan,loc,net,sps)=string.split(key, ":")
-			if (self.GlobalStation.get() == "*" or self.GlobalStation.get() == stat) \
-			   and \
-			   (self.GlobalChannel.get() == "*" or self.GlobalChannel.get() == chan)\
-			   and \
-			   (self.GlobalLocCode.get() == "*" or self.GlobalLocCode.get() == loc)\
-			   and \
-			   (self.GlobalNetCode.get() == "*" or self.GlobalNetCode.get() == net)\
-			   and \
-			   (self.GlobalSps.get() == "*" or self.GlobalSps.get() == sps):
-				if self.GUStation.get():
-					self.NStation.set(self.GUStation.get())
-					if self.SetHdrDict.has_key(key):
-						if self.SetHdrDict[key].has_key("Station_Name"):
-							del self.SetHdrDict[key]["Station_Name"]
-				if self.GUChannel.get():
-					self.NChannel.set(self.GUChannel.get())
-					if self.SetHdrDict.has_key(key):
-						if self.SetHdrDict[key].has_key("Channel"):
-							del self.SetHdrDict[key]["Channel"]
-				if self.GULocCode.get():
-					self.NLocCode.set(self.GULocCode.get())
-					if self.SetHdrDict.has_key(key):
-						if self.SetHdrDict[key].has_key("Location_Code"):
-							del self.SetHdrDict[key]["Location_Code"]
-				if self.GUNetCode.get():
-					self.NNetCode.set(self.GUNetCode.get())
-					if self.SetHdrDict.has_key(key):
-						if self.SetHdrDict[key].has_key("Network_Code"):
-							del self.SetHdrDict[key]["Network_Code"]
-				self.OldSID.set(key)
-				self.UpdateHdr()
-
-		# empty all entries
-		self.ClearAll(self.StatChanListVars)
-		self.ClearAll(self.NewVars)
-		self.ClearAllGlobal(self.GlobalListVars)
-		info = "Global Set Done. Use 'Trace Headers->Modify Headers' to apply."
-		self.addTextInfoBar(info, 'green')
+    def GlobalSet(self):
+        """
+        build UpdateHdrDict
+        """
+        self.addTextInfoBar()
+        #check if mods are enterred
+        if not self.GUStation.get() \
+           and not self.GUChannel.get() \
+           and not self.GULocCode.get() \
+           and not self.GUNetCode.get():
+            self.addTextInfoBar("No 'Substitute Values' Given", 'orange')
+            return
+
+        for key in self.TraceDict:
+            #make sure there are no lingering NewVars
+            self.ClearAll(self.NewVars)
+            (stat,chan,loc,net,sps) = key.split(":")
+            if (self.GlobalStation.get() == "*" \
+                or self.GlobalStation.get() == stat) \
+               and \
+               (self.GlobalChannel.get() == "*" \
+                or self.GlobalChannel.get() == chan)\
+               and \
+               (self.GlobalLocCode.get() == "*" \
+                or self.GlobalLocCode.get() == loc)\
+               and \
+               (self.GlobalNetCode.get() == "*" \
+                or self.GlobalNetCode.get() == net)\
+               and \
+               (self.GlobalSps.get() == "*" \
+                or self.GlobalSps.get() == sps):
+
+                if self.GUStation.get():
+                    self.NStation.set(self.GUStation.get())
+                    if key in self.SetHdrDict:
+                        if "Station_Name" in self.SetHdrDict[key]:
+                            del self.SetHdrDict[key]["Station_Name"]
+
+                if self.GUChannel.get():
+                    self.NChannel.set(self.GUChannel.get())
+                    if key in self.SetHdrDict:
+                        if "Channel" in self.SetHdrDict[key]:
+                            del self.SetHdrDict[key]["Channel"]
+                if self.GULocCode.get():
+                    self.NLocCode.set(self.GULocCode.get())
+                    if key in self.SetHdrDict:
+                        if "Location_Code" in self.SetHdrDict[key]:
+                            del self.SetHdrDict[key]["Location_Code"]
+                if self.GUNetCode.get():
+                    self.NNetCode.set(self.GUNetCode.get())
+                    if key in self.SetHdrDict:
+                        if "Network_Code" in self.SetHdrDict[key]:
+                            del self.SetHdrDict[key]["Network_Code"]
+                self.OldSID.set(key)
+                self.UpdateHdr()
+
+        # empty all entries
+        self.ClearAll(self.StatChanListVars)
+        self.ClearAll(self.NewVars)
+        self.ClearAllGlobal(self.GlobalListVars)
+        info = "Global Set Done. Use 'Trace Headers->Modify Headers' "\
+            "to apply."
+        self.addTextInfoBar(info, 'green')
 
 #######################################
-	def TimeDictSet(self):
-		"""
-		build UpdateTimeDict
-		"""
-		self.addTextInfoBar()
-		#check input formats before committing to UpdateTimeDict
-		if not self.TimeShiftName.get():
-			if self.UpdateTimeDict:
-				return 1
-			else:
-				self.addTextInfoBar("No 'Stat:Loc:Net' selected", 'red')
-				return 0
-		(startEpoch, err) = self.BuildEpoch(self.TSStartTime)
-		if err:
-			err = err + ": Start_Time"
-			self.addTextInfoBar("Invalid StartTime String", 'red')
-			return 0
-
-		(endEpoch, err) = self.BuildEpoch(self.TSEndTime)
-		if err:
-			err = err + ": End_Time"
-			self.addTextInfoBar("Invalid EndTime String", 'red')
-			return 0
-
-		try:
-			self.TSShift.get()
-			if self.TSShift.get() == "":
-				err="ERROR: Time_Shift_sec must be a float"
-				self.addTextInfoBar(err, 'red')
-				return 0
-		except:
-			err="ERROR: Time_Shift_sec must be a float"
-			self.addTextInfoBar(err, 'red')
-			return 0
-		if self.TimeTagQuest.get():
-			if self.TimeTagQuest.get() != "set" and self.TimeTagQuest.get() != "unset":
-				err="ERROR: 'Time Tag is questionable' must be either 'set', 'unset', or blank"
-				self.addTextInfoBar(err, 'red')
-				return 0
-
-		#Create UpdateTimeDict entry. THIS OVERWRITES any previous entry
-		#I overwrite since when a user selects Stat:Loc:Net on Notebook
-		#they are informed if an entry exists and if it has been applied.
-		#User beware
-		(stat,loc,net)=string.split(self.TimeShiftName.get(), ':')
-		for key in self.TraceTimeDict.keys():
-			(TTD_stat, TTD_loc, TTD_net)=string.split(key, ':')
-			if TTD_stat==stat \
-			   and \
-			   (TTD_loc==loc or loc=="*") \
-			   and \
-			   TTD_net==net :
-				self.UpdateTimeDict[key]={}
-				for var in self.ShiftVars:
-					self.UpdateTimeDict[key][var[0]]=var[1].get()
-		# empty all entries
-#		self.ClearAll(self.StatChanListVars)
-		info = "Time Set Done. Use 'Apply Time Corrections' to apply."
-		self.addTextInfoBar(info, 'green')
-		return 1
+    def TimeDictSet(self):
+        """
+        build UpdateTimeDict
+        """
+        self.addTextInfoBar()
+        #check input formats before committing to UpdateTimeDict
+        if not self.TimeShiftName.get():
+            if self.UpdateTimeDict:
+                return 1
+            else:
+                self.addTextInfoBar("No 'Stat:Loc:Net' selected", 'red')
+                return 0
+        (startEpoch, err) = self.BuildEpoch(self.TSStartTime)
+        if err:
+            err = err + ": Start_Time"
+            self.addTextInfoBar("Invalid StartTime String", 'red')
+            return 0
+
+        (endEpoch, err) = self.BuildEpoch(self.TSEndTime)
+        if err:
+            err = err + ": End_Time"
+            self.addTextInfoBar("Invalid EndTime String", 'red')
+            return 0
+
+        try:
+            self.TSShift.get()
+            if self.TSShift.get() == "":
+                err = "ERROR: Time_Shift_sec must be a float"
+                self.addTextInfoBar(err, 'red')
+                return 0
+        except Exception as e:
+            err = "ERROR: Time_Shift_sec must be a float"
+            self.addTextInfoBar(err, 'red')
+            return 0
+        if self.TimeTagQuest.get():
+            if self.TimeTagQuest.get() != "set" \
+               and self.TimeTagQuest.get() != "unset":
+                err = "ERROR: 'Time Tag is questionable' must be either "\
+                    "'set', 'unset', or blank"
+                self.addTextInfoBar(err, 'red')
+                return 0
+
+        #Create UpdateTimeDict entry. THIS OVERWRITES any previous entry
+        #I overwrite since when a user selects Stat:Loc:Net on Notebook
+        #they are informed if an entry exists and if it has been applied.
+        #User beware
+        (stat,loc,net) = self.TimeShiftName.get().split(':')
+        for key in self.TraceTimeDict:
+            (TTD_stat, TTD_loc, TTD_net) = key.split(':')
+            if TTD_stat==stat \
+               and \
+               (TTD_loc==loc or loc=="*") \
+               and \
+               TTD_net==net :
+                self.UpdateTimeDict[key]={}
+                for var in self.ShiftVars:
+                    self.UpdateTimeDict[key][var[0]]=var[1].get()
+        # empty all entries
+#                self.ClearAll(self.StatChanListVars)
+        info = "Time Set Done. Use 'Apply Time Corrections' to apply."
+        self.addTextInfoBar(info, 'green')
+        return 1
 
 ##################################################################
 
-	def UpdateTimeShift(self, fm):
-		"""
-		builds drop downs for TimeShift  notebook
-		"""
-		#build list for stat:loc:net selection dropdown
-		self.StatLocNetList=self.TraceTimeDict.keys()
-		#self.StatLocNetList=[]
-		#for n in self.TraceTimeDict.keys() :
-			#self.StatLocNetList.append(n)
-		self.StatLocNetList.sort()
-		if not self.StatLocNetList:
-			self.addTextInfoBar("No Data Found", 'orange')
-
-
-		#build drop down and new entries
-		Label(fm, text="For Traces Matching:").grid(row=0, column=1, sticky=W)
-		Label(fm, text="Time Shift:").grid(row=0, column=3, sticky=W)
-		Label(fm, text="Applied").grid(row=0, column=4, sticky=W)
-		n=1
-		Label(fm, text="Stat:Loc:Net").grid(row=1, sticky=W)
-		Pmw.ComboBox(fm,
-			     history=0,
-			     entry_width=self.e_width-5,
-			     entry_textvariable=self.TimeShiftName,
-			     scrolledlist_items=(self.StatLocNetList),
-			     selectioncommand=Command(self.LoadTimeSelect)
-			     ).grid(row=n, column=1, sticky=W)
-		self.WildButton = Checkbutton(fm,
-					      text ="Wildcard Location Code",
-					      command = Command(self.WildCardLoc),
-					      variable = self.WildLoc
-					      )
-		self.WildButton.grid(row=n+1, column=1, sticky=W)
-
-		n=1
-		for var in self.ShiftVars:
-			if var[0] == "Corr_Type": continue
-			if var[0] != "Time_Tag_Quest":
-				Label(fm, text=var[0]).grid(row=n, column=2, sticky=E)
-				Entry(fm,
-				      width = self.e_width-5,
-				      selectbackground = 'yellow',
-				      textvariable = var[1]).grid(row=n, column=3, sticky=W)
-				n+=1
-
-			elif var[0] == "Time_Tag_Quest":
-				Label(fm, text="Time Tag is questionable: ").grid(row=n, column=2, sticky=W)
-				Pmw.ComboBox(fm,
-					     history=0,
-					     entry_width=8,
-					     entry_textvariable=self.TimeTagQuest,
-					     scrolledlist_items=("set", "unset"),
-					     ).grid(row=n, column=3, sticky=W)
-
-		#build boxes indicating if update is applied
-		n=3
-		for var in self.SetTimeVars:
-			Checkbutton(fm,
-				    variable = var[1],
-				    indicatoron = "FALSE",
-				    text = "   ",
-				    selectcolor = "green",
-				    state = "disabled"
-				    ).grid(row=n, column=4)
-			n+=1
-#	clear variables etc.
-		self.ResetTimeShift()
+    def UpdateTimeShift(self, fm):
+        """
+        builds drop downs for TimeShift  notebook
+        """
+        #build list for stat:loc:net selection dropdown
+        self.StatLocNetList = sorted(list(self.TraceTimeDict.keys()))
+        if not self.StatLocNetList:
+            self.addTextInfoBar("No Data Found", 'orange')
+
+        #build drop down and new entries
+        Label(fm, text="For Traces Matching:").grid(row=0, column=1, sticky=W)
+        Label(fm, text="Time Shift:").grid(row=0, column=3, sticky=W)
+        Label(fm, text="Applied").grid(row=0, column=4, sticky=W)
+        n=1
+        Label(fm, text="Stat:Loc:Net").grid(row=1, sticky=W)
+        Pmw.ComboBox(fm,
+                     history=0,
+                     entry_width=self.e_width-5,
+                     entry_textvariable=self.TimeShiftName,
+                     scrolledlist_items=(self.StatLocNetList),
+                     selectioncommand=Command(self.LoadTimeSelect)
+                     ).grid(row=n, column=1, sticky=W)
+        self.WildButton = Checkbutton(fm,
+                                      text ="Wildcard Location Code",
+                                      command = Command(self.WildCardLoc),
+                                      variable = self.WildLoc
+                                      )
+        self.WildButton.grid(row=n+1, column=1, sticky=W)
+
+        n = 1
+        for var in self.ShiftVars:
+            if var[0] == "Corr_Type": continue
+            if var[0] != "Time_Tag_Quest":
+                Label(fm, text=var[0]).grid(row=n, column=2, sticky=E)
+                Entry(fm,
+                      width = self.e_width-5,
+                      selectbackground = 'yellow',
+                      textvariable = var[1]).grid(row=n, column=3, sticky=W)
+                n += 1
+
+            elif var[0] == "Time_Tag_Quest":
+                Label(fm, text="Time Tag is questionable: ").grid(
+                    row=n, column=2, sticky=W)
+                Pmw.ComboBox(fm,
+                             history=0,
+                             entry_width=8,
+                             entry_textvariable=self.TimeTagQuest,
+                             scrolledlist_items=("set", "unset"),
+                             ).grid(row=n, column=3, sticky=W)
+
+        #build boxes indicating if update is applied
+        n = 3
+        for var in self.SetTimeVars:
+            Checkbutton(fm,
+                        variable = var[1],
+                        indicatoron = "FALSE",
+                        text = "   ",
+                        selectcolor = "green",
+                        state = "disabled"
+                        ).grid(row=n, column=4)
+            n += 1
+#        clear variables etc.
+        self.ResetTimeShift()
 #######################################
-	def WildCardLoc(self):
-		"""
-		sub loc code with *
-		"""
-		if self.WildLoc.get():
-			if self.TimeShiftName.get():
-				self.OldShiftName.set(self.TimeShiftName.get())
-				newname=string.split(self.TimeShiftName.get(), ":")
-				newname[1]="*"
-				self.TimeShiftName.set(string.join(newname,":"))
-			else:
-				return
-		else:
-			if self.TimeShiftName.get():
-				self.TimeShiftName.set(self.OldShiftName.get())
-			else:
-				return
+    def WildCardLoc(self):
+        """
+        sub loc code with *
+        """
+        if self.WildLoc.get():
+            if self.TimeShiftName.get():
+                self.OldShiftName.set(self.TimeShiftName.get())
+                newname = self.TimeShiftName.get().split(":")
+                newname[1]="*"
+                self.TimeShiftName.set(":".join(newname))
+            else:
+                return
+        else:
+            if self.TimeShiftName.get():
+                self.TimeShiftName.set(self.OldShiftName.get())
+            else:
+                return
 #######################################
-	def LaunchApplyTimeCor(self, undo=0) :
-		"""
-		separated out so ApplyTimeCor could be run as a thread
-
-		"""
-
-		#if headers have already been alterred warn user
-		if not undo:
-			if self.SetTimeDict.keys() or self.SetHdrDict.keys():
-				self.WarnWidget(self.TimeShift_nb, "time")
-				self.WarnWidget_tl.wait_window()
-				if self.CancelWarn.get():
-					return
-
-		#if the user ignores warning proceed
-		#set var indicating ApplyTimeCor is running. Watched to exit thread if
-		#cancel button selected in CancelTL
-		self.RunApplyTimeCor.set(1)
-		#write log and user information
-		self.WriteLog("\n<Modify Time>", "Time", "blue")
-
-		#tRun=threading.Thread(target=self.ApplyTimeCor)
-		self.ApplyTimeCor()
-		#tRun.start()
-		# stay here until thread dies
-		#tRun.join()
-
-		#nuke top level CancelTL
-		if self.RunApplyTimeCor.get():
-			self.KillCancelTL(self.RunApplyTimeCor)
-
-		#some cleanup
-		self.WriteLog("<end>", "Time", "blue")
-		self.ResetTimeShift()
-		self.IgnoreWarn.set(0)
-		self.UseNewOnlyTime.set(0)
+    def LaunchApplyTimeCor(self, undo=0) :
+        """
+        separated out so ApplyTimeCor could be run as a thread
+
+        """
+
+        #if headers have already been alterred warn user
+        if not undo:
+            if self.SetTimeDict or self.SetHdrDict:
+                self.WarnWidget(self.TimeShift_nb, "time")
+                self.WarnWidget_tl.wait_window()
+                if self.CancelWarn.get():
+                    return
+
+        #if the user ignores warning proceed
+        #set var indicating ApplyTimeCor is running. Watched to exit thread if
+        #cancel button selected in CancelTL
+        self.RunApplyTimeCor.set(1)
+        #write log and user information
+        self.WriteLog("\n<Modify Time>", "Time", "blue")
+
+        #tRun=threading.Thread(target=self.ApplyTimeCor)
+        self.ApplyTimeCor()
+        #tRun.start()
+        # stay here until thread dies
+        #tRun.join()
+
+        #nuke top level CancelTL
+        if self.RunApplyTimeCor.get():
+            self.KillCancelTL(self.RunApplyTimeCor)
+
+        #some cleanup
+        self.WriteLog("<end>", "Time", "blue")
+        self.ResetTimeShift()
+        self.IgnoreWarn.set(0)
+        self.UseNewOnlyTime.set(0)
 
 #######################################
-	def NewOnlyTime(self):
-		"""
-		Set flag to only use new (unapplied) timing corrections
-		"""
-		self.killWindow(self.WarnWidget_tl)
-		self.ActiveText.set("")
-		self.AlteredText.set("")
-		self.UseNewOnlyTime.set(1)
+    def NewOnlyTime(self):
+        """
+        Set flag to only use new (unapplied) timing corrections
+        """
+        self.killWindow(self.WarnWidget_tl)
+        self.ActiveText.set("")
+        self.AlteredText.set("")
+        self.UseNewOnlyTime.set(1)
 #######################################
-	def ApplyTimeCor(self):
-		"""
-		apply timing correction to start time etc.
-		"""
-
-		# Launch CancelTL allowing user to cancel process
-		if not BATCHMODE:
-			self.CancelTL(self.RunApplyTimeCor, "Apply Time Correction")
-		#update with lingering window entries
-		if not self.TimeDictSet():
-			return
-
-		num_cnt=0
-		err_cnt=0
-		skip_cnt=0
-
-		for key in self.UpdateTimeDict.keys():
-			if not self.TraceTimeDict.has_key(key): continue
-			#capture cancel
-			if not self.RunApplyTimeCor.get():
-				infotext="Canceled Applied Corrections to: " + str(num_cnt) + " files."
-				self.addTextInfoBar(infotext, 'orange')
-				logtext = "\t" + infotext
-				self.WriteLog(logtext, "Time", "red")
-				break
-			self.TimeShiftName.set(key)
-			self.GetStartEnd()
-			for var in self.ShiftVars:
-				if self.UpdateTimeDict[key].has_key(var[0]):
-					var[1].set(self.UpdateTimeDict[key][var[0]])
-
-			self.addTextInfoBar()
-
-			self.ActiveText.set("Time Shift Running")
-			self.AlteredText.set("Headers or blockette times have been modified.\n \'Apply Unapplied Only\' to avoid unexpected results.\n")
-
-			# build epoch start & end time for correction
-			(startEpoch, err) = self.BuildEpoch(self.TSStartTime)
-			if err:
-				err = err + ": Start_Time"
-				self.addTextInfoBar("Invalid StartTime String", 'red')
-				return
-
-			(endEpoch, err) = self.BuildEpoch(self.TSEndTime)
-			if err:
-				err = err + ": End_Time"
-				self.addTextInfoBar("Invalid EndTime String", 'red')
-				return
-
-			#write log and user information
-#			self.WriteLog("\n<Modify Time>\n", "Time", "blue")
-			logtext= "\n\tKey Name: " + key
-			self.WriteLog(logtext, "Time", "black")
-			cnt=len(self.TraceTimeDict[key]) - 1 #first record
-			logtext="\tNumber of Traces Selected: " + str(cnt)
-			self.WriteLog(logtext, "Time", "black")
-			if self.TimeCorrectedFiles.has_key(key):
-				changedfiles=len(self.TimeCorrectedFiles[key])
-				if self.UseNewOnlyTime.get():
-					logtext="\tSkipping " + str(changedfiles) + " previously corrected files."
-					self.WriteLog(logtext, "Time", "black")
-				else:
-					logtext="\tApplying Corrections to " + str(changedfiles) + " previously corrected files."
-					self.WriteLog(logtext, "Time", "red")
-			logtext="\tStart_Time of Correction: " + str(self.TSStartTime.get())
-			self.WriteLog(logtext, "Time", "black")
-			logtext="\tEnd_Time of Correction: " + str(self.TSEndTime.get())
-			self.WriteLog(logtext, "Time", "black")
-			logtext= "\tTime_Shift_sec " + str(self.TSShift.get())
-			self.WriteLog(logtext, "Time", "black")
-			if self.TypeTimeCor.get():
-				type="Replace existing time correction"
-			else:
-				type="Add to existing time correction"
-			logtext="\tType of Correction: " + type
-			self.WriteLog(logtext, "Time", "black")
-
-			if self.TimeTagQuest.get():
-				action = self.TimeTagQuest.get()
-				if action == "set":
-					logtext = "\t\"Time tag is questionable\" flag set"
-				elif action == "unset":
-					logtext = "\t\"Time tag is questionable\" flag unset"
-				self.WriteLog(logtext, "Time", "black")
-
-			#set up dictionary to monitor corrected files
-			if not self.TimeCorrectedFiles.has_key(key):
-				self.TimeCorrectedFiles[key]=[]
-			#apply corrections for selected keys
-			textstr= "Correcting File Number: "
-			for timetup in self.TraceTimeDict[key][1:]:
-				if self.UseNewOnlyTime.get():
-					if timetup[0] in self.TimeCorrectedFiles[key]:
-						skip_cnt+=1
-						infotext="Skipping File " + str(skip_cnt)
-						self.addTextInfoBar(infotext)
-						continue
-				#respond to cancel requests
-				if not self.RunApplyTimeCor.get():
-					infotext="Canceled Applied Corrections to: " + str(num_cnt) + " files."
-					self.addTextInfoBar(infotext, 'orange')
-					logtext = "\t" + infotext
-					self.WriteLog(logtext, "Time", "red")
-					break
-				if (startEpoch <= timetup[1] and timetup[1] <= endEpoch) or \
-				   (startEpoch <= timetup[2] and timetup[2] <= endEpoch) or \
-				   (timetup[1] <= startEpoch and endEpoch <= timetup[2]):
-					#info for user
-					if not self.TimeSet(timetup[0], startEpoch, endEpoch):
-						err_cnt+=1
-						#if this fails, make sure UpdateTimeDict is cleared for key
-						del self.UpdateTimeDict[key]
-						break
-					else:
-						self.TimeCorrectedFiles[key].append(timetup[0])
-						num_cnt+=1
-						if not self.SetTimeDict.has_key(key):
-							self.SetTimeDict[key]={}
-					if mod(num_cnt, 10):
-						pass
-					else:
-						self.wait(textstr, num_cnt)
-
-			#keep track of time corrections applied
-			if self.UpdateTimeDict.has_key(key):
-				for subkey in self.UpdateTimeDict[key].keys():
-					#add to existing if TypeTimeCor is set to 'Add To' i.e. == 0
-					if subkey == "Time_Shift_sec" and not self.TypeTimeCor.get():
-						#add to previous if the user ignored warning to Apply unapplied only.
-						#the user can totally screw this up since the time shift is for a Sta:Loc:Net and not
-						#by trace. e.g. consecutive runs of ApplyTimeCor sometimes Applying all corrections
-						#and other applying only unapplied.
-						if self.SetTimeDict[key].has_key(subkey) and not self.UseNewOnlyTime.get():
-							self.SetTimeDict[key][subkey]=self.SetTimeDict[key][subkey] + self.UpdateTimeDict[key][subkey]
-						else:
-							self.SetTimeDict[key][subkey]=self.UpdateTimeDict[key][subkey]
-					else:
-						self.SetTimeDict[key][subkey]=self.UpdateTimeDict[key][subkey]
-
-		if err_cnt:
-			logtext="\tTime corection failed for " + str(err_cnt) + " files"
-			self.WriteLog(logtext, "Time", "red")
-
-
-		if self.RunApplyTimeCor.get():
-			infotext="Done. Applied Corrections to: " + str(num_cnt) + " files."
-			self.addTextInfoBar(infotext, 'green')
-			if not BATCHMODE:
-				self.KillCancelTL(self.RunApplyTimeCor)
-			logtext = "\t" + infotext
-			self.WriteLog(logtext, "Time", "green")
-		self.ActiveText.set("")
-#		self.WriteLog("<end>\n", "Time", "blue")
+    def ApplyTimeCor(self):
+        """
+        apply timing correction to start time etc.
+        """
+
+        # Launch CancelTL allowing user to cancel process
+        if not BATCHMODE:
+            self.CancelTL(self.RunApplyTimeCor, "Apply Time Correction")
+        #update with lingering window entries
+        if not self.TimeDictSet():
+            return
+
+        num_cnt = 0
+        err_cnt = 0
+        skip_cnt = 0
+
+        UpdateTimeDictKeys = list(self.UpdateTimeDict.keys())
+        for key in UpdateTimeDictKeys:
+            if key not in self.TraceTimeDict:
+                continue
+            #capture cancel
+            if not self.RunApplyTimeCor.get():
+                infotext="Canceled Applied Corrections to: " + str(num_cnt)\
+                    + " files."
+                self.addTextInfoBar(infotext, 'orange')
+                logtext = "\t" + infotext
+                self.WriteLog(logtext, "Time", "red")
+                break
+            self.TimeShiftName.set(key)
+            self.GetStartEnd()
+            for var in self.ShiftVars:
+                if var[0] in self.UpdateTimeDict[key]:
+                    var[1].set(self.UpdateTimeDict[key][var[0]])
+
+            self.addTextInfoBar()
+
+            self.ActiveText.set("Time Shift Running")
+            self.AlteredText.set("Headers or blockette times have been "
+                                 "modified.\n \'Apply Unapplied Only\' to "
+                                 "avoid unexpected results.\n")
+
+            # build epoch start & end time for correction
+            (startEpoch, err) = self.BuildEpoch(self.TSStartTime)
+            if err:
+                err = err + ": Start_Time"
+                self.addTextInfoBar("Invalid StartTime String", 'red')
+                return
+
+            (endEpoch, err) = self.BuildEpoch(self.TSEndTime)
+            if err:
+                err = err + ": End_Time"
+                self.addTextInfoBar("Invalid EndTime String", 'red')
+                return
+
+            #write log and user information
+#                        self.WriteLog("\n<Modify Time>\n", "Time", "blue")
+            logtext= "\n\tKey Name: " + key
+            self.WriteLog(logtext, "Time", "black")
+            cnt=len(self.TraceTimeDict[key]) - 1 #first record
+            logtext="\tNumber of Traces Selected: " + str(cnt)
+            self.WriteLog(logtext, "Time", "black")
+            if key in self.TimeCorrectedFiles:
+                changedfiles=len(self.TimeCorrectedFiles[key])
+                if self.UseNewOnlyTime.get():
+                    logtext="\tSkipping " + str(changedfiles) + \
+                        " previously corrected files."
+                    self.WriteLog(logtext, "Time", "black")
+                else:
+                    logtext="\tApplying Corrections to " + str(changedfiles)\
+                        + " previously corrected files."
+                    self.WriteLog(logtext, "Time", "red")
+            logtext="\tStart_Time of Correction: " + \
+                str(self.TSStartTime.get())
+            self.WriteLog(logtext, "Time", "black")
+            logtext="\tEnd_Time of Correction: " + \
+                str(self.TSEndTime.get())
+            self.WriteLog(logtext, "Time", "black")
+            logtext= "\tTime_Shift_sec " + str(self.TSShift.get())
+            self.WriteLog(logtext, "Time", "black")
+            if self.TypeTimeCor.get():
+                type="Replace existing time correction"
+            else:
+                type="Add to existing time correction"
+            logtext="\tType of Correction: " + type
+            self.WriteLog(logtext, "Time", "black")
+
+            if self.TimeTagQuest.get():
+                action = self.TimeTagQuest.get()
+                if action == "set":
+                    logtext = "\t\"Time tag is questionable\" flag set"
+                elif action == "unset":
+                    logtext = "\t\"Time tag is questionable\" flag unset"
+                self.WriteLog(logtext, "Time", "black")
+
+            #set up dictionary to monitor corrected files
+            if key not in self.TimeCorrectedFiles:
+                self.TimeCorrectedFiles[key]=[]
+            #apply corrections for selected keys
+            textstr= "Correcting File Number: "
+            for timetup in self.TraceTimeDict[key][1:]:
+                if self.UseNewOnlyTime.get():
+                    if timetup[0] in self.TimeCorrectedFiles[key]:
+                        skip_cnt+=1
+                        infotext="Skipping File " + str(skip_cnt)
+                        self.addTextInfoBar(infotext)
+                        continue
+                #respond to cancel requests
+                if not self.RunApplyTimeCor.get():
+                    infotext="Canceled Applied Corrections to: " + \
+                        str(num_cnt) + " files."
+                    self.addTextInfoBar(infotext, 'orange')
+                    logtext = "\t" + infotext
+                    self.WriteLog(logtext, "Time", "red")
+                    break
+                if (startEpoch <= timetup[1] and timetup[1] <= endEpoch) or \
+                   (startEpoch <= timetup[2] and timetup[2] <= endEpoch) or \
+                   (timetup[1] <= startEpoch and endEpoch <= timetup[2]):
+                    #info for user
+                    if not self.TimeSet(timetup[0], startEpoch, endEpoch):
+                        err_cnt+=1
+                        # if this fails, make sure UpdateTimeDict is cleared
+                        # for key
+                        del self.UpdateTimeDict[key]
+                        break
+                    else:
+                        self.TimeCorrectedFiles[key].append(timetup[0])
+                        num_cnt+=1
+                        if key not in self.SetTimeDict:
+                            self.SetTimeDict[key]={}
+                    if mod(num_cnt, 10):
+                        pass
+                    else:
+                        self.wait(textstr, num_cnt)
+
+            #keep track of time corrections applied
+            if key in self.UpdateTimeDict:
+                for subkey in self.UpdateTimeDict[key]:
+                    #add to existing if TypeTimeCor is set to 'Add To' i.e. == 0
+                    if subkey == "Time_Shift_sec" \
+                       and not self.TypeTimeCor.get():
+                        # add to previous if the user ignored warning to Apply
+                        # unapplied only. the user can totally screw this up
+                        # since the time shift is for a Sta:Loc:Net and not
+                        # by trace. e.g. consecutive runs of ApplyTimeCor
+                        # sometimes Applying all corrections
+                        # and other applying only unapplied.
+                        if subkey in self.SetTimeDict[key] \
+                           and not self.UseNewOnlyTime.get():
+                            self.SetTimeDict[key][subkey] = \
+                                self.SetTimeDict[key][subkey] + \
+                                self.UpdateTimeDict[key][subkey]
+                        else:
+                            self.SetTimeDict[key][subkey] = \
+                                self.UpdateTimeDict[key][subkey]
+                    else:
+                        self.SetTimeDict[key][subkey] = \
+                            self.UpdateTimeDict[key][subkey]
+
+        if err_cnt:
+            logtext="\tTime corection failed for " + str(err_cnt) + " files"
+            self.WriteLog(logtext, "Time", "red")
+
+
+        if self.RunApplyTimeCor.get():
+            infotext="Done. Applied Corrections to: " + str(num_cnt) + \
+                " files."
+            self.addTextInfoBar(infotext, 'green')
+            if not BATCHMODE:
+                self.KillCancelTL(self.RunApplyTimeCor)
+            logtext = "\t" + infotext
+            self.WriteLog(logtext, "Time", "green")
+        self.ActiveText.set("")
+#                self.WriteLog("<end>\n", "Time", "blue")
 
 #######################################
-	def LaunchUndoTimeCor(self):
-		"""
-		Launch UndoTimeCor in thread
-		"""
-		if not self.SetTimeDict:
-			infotext="No Time Corrections Applied this session"
-			self.addTextInfoBar(infotext, 'orange')
-			return
-
-		#if headers have already been alterred warn user
-		self.WarnWidget(self.TimeShift_nb, "undo")
-		self.WarnWidget_tl.wait_window()
-		if not self.IgnoreWarn.get():
-			return
-		elif self.CancelWarn.get():
-			return
-
-		self.ResetTimeShift()
-		self.UpdateTimeDict={}
-		for key in self.SetTimeDict.keys():
-			#Populate UpdateTimeDict with previously applied Time Corrections
-			if not self.UpdateTimeDict.has_key(key):
-				self.UpdateTimeDict[key]={}
-			for subkey in self.SetTimeDict[key].keys():
-				if subkey == "Time_Shift_sec":
-					self.UpdateTimeDict[key][subkey]=(-1.0)*self.SetTimeDict[key][subkey]
-				elif subkey == "Time_Tag_Quest":
-					if self.SetTimeDict[key][subkey] == "set":
-						self.UpdateTimeDict[key][subkey]="unset"
-					elif self.SetTimeDict[key][subkey] == "unset":
-						self.UpdateTimeDict[key][subkey]="set"
-					else:
-						self.UpdateTimeDict[key][subkey]=""
-				elif subkey == "Corr_Type":
-					self.UpdateTimeDict[key][subkey]=0
-				else:
-					self.UpdateTimeDict[key][subkey]=self.SetTimeDict[key][subkey]
-
-#		self.SetTimeDict={}
-		self.LaunchApplyTimeCor(1)
-		return
+    def LaunchUndoTimeCor(self):
+        """
+        Launch UndoTimeCor in thread
+        """
+        if not self.SetTimeDict:
+            infotext = "No Time Corrections Applied this session"
+            self.addTextInfoBar(infotext, 'orange')
+            return
+
+        #if headers have already been alterred warn user
+        self.WarnWidget(self.TimeShift_nb, "undo")
+        self.WarnWidget_tl.wait_window()
+        if not self.IgnoreWarn.get():
+            return
+        elif self.CancelWarn.get():
+            return
+
+        self.ResetTimeShift()
+        self.UpdateTimeDict = {}
+        for key in self.SetTimeDict:
+            #Populate UpdateTimeDict with previously applied Time Corrections
+            if key not in self.UpdateTimeDict:
+                self.UpdateTimeDict[key] = {}
+            for subkey in self.SetTimeDict[key]:
+                if subkey == "Time_Shift_sec":
+                    self.UpdateTimeDict[key][subkey] = \
+                        (-1.0)*self.SetTimeDict[key][subkey]
+                elif subkey == "Time_Tag_Quest":
+                    if self.SetTimeDict[key][subkey] == "set":
+                        self.UpdateTimeDict[key][subkey] = "unset"
+                    elif self.SetTimeDict[key][subkey] == "unset":
+                        self.UpdateTimeDict[key][subkey] = "set"
+                    else:
+                        self.UpdateTimeDict[key][subkey] = ""
+                elif subkey == "Corr_Type":
+                    self.UpdateTimeDict[key][subkey] = 0
+                else:
+                    self.UpdateTimeDict[key][subkey] = \
+                        self.SetTimeDict[key][subkey]
+
+                # self.SetTimeDict={}
+        self.LaunchApplyTimeCor(1)
+        return
 
 #######################################
-	def BuildEpoch(self, input_time):
-		"""
-		build epoch time from input time string
-		"""
-		EpochTime=None
-		err=""
-		intTime = str(input_time.get())
-
-		try:
-			TimeStr = time.strptime(intTime, '%Y:%j:%H:%M:%S')
-			EpochTime = time.mktime(TimeStr)
-		except:
-			err = "Invalid Time String"
-			self.ActiveText.set("")
-			self.AlteredText.set("")
-			return EpochTime, err
-
-		return EpochTime, err
+    def BuildEpoch(self, input_time):
+        """
+        build epoch time from input time string
+        """
+        EpochTime=None
+        err=""
+        intTime = str(input_time.get())
+
+        try:
+            TimeStr = time.strptime(intTime, '%Y:%j:%H:%M:%S')
+            EpochTime = time.mktime(TimeStr)
+        except Exception as e:
+            err = "Invalid Time String"
+            self.ActiveText.set("")
+            self.AlteredText.set("")
+            return EpochTime, err
+
+        return EpochTime, err
 
 #######################################
-	def TimeSet(self, ifile,startEpoch, endEpoch):
-		"""
-		apply time correction to given mseed file
-		"""
-
-		# first test to see if time shift will exceed field size
-		ShiftErr = self.TestTimeShift()
-		if ShiftErr:
-			self.addTextInfoBar(ShiftErr, "red")
-			self.WriteLog(ShiftErr, "Time", "red")
-			return 0
-
-		#open mseed files for correction
-		msfile=Mseed(ifile)
-		filesize=msfile.filesize
-		blksize=msfile.blksize
-		(numblocks, odd_size)=divmod(filesize, blksize)
-
-		# loop through file applying correction
-		blk_err=0
-		n=0
-		while n < numblocks:
-
-			hdrs=msfile.fixedhdr(n*blksize)
-
-			#more test just incase, this will fail if headers have been change w/o updating the db
-			(SeqNum, DHQual, res, Stat, Loc, Chan, Net)=hdrs[0]
-			Stat=string.strip(Stat)
-			if self.WildLoc.get():
-				Loc="*"
-			else:
-				Loc=string.strip(Loc)
-			Net=string.strip(Net)
-			key=Stat + ":" + Loc + ":" + Net
-			if key != self.TimeShiftName.get():
-				blk_err+=1
-				n+=1
-				continue
-
-			#determine time of blockette and process if between startEpoch & endEpoch
-			(Year, Day, Hour, Min, Sec, junk, Micro)=hdrs[1]
-			timestr=string.join(map(str,(Year, Day, Hour, Min, Sec)), ":")
-			time_str = time.strptime(timestr, '%Y:%j:%H:%M:%S')
-			blkEpoch = time.mktime(time_str) + (Micro * 0.0001)
-			if startEpoch <= blkEpoch and blkEpoch <= endEpoch:
-				pass
-			else:
-				n+=1
-				continue
-
-			oldshift= hdrs[3][4] * 0.0001
-			shift_applied=int(hdrs[3][0][6])
-			# if type=replace (i.e. 1), remove oldtime shift from Epoch and then apply new
-			# shift value in header equals new shift
-			if self.TypeTimeCor.get():
-				# if an old shift exists and is applied
-				if shift_applied and oldshift:
-					blkEpoch = blkEpoch + self.TSShift.get() - oldshift
-					newshift=self.TSShift.get()
-				# if an old shift  shift exists and is not applied
-				elif not shift_applied and oldshift:
-					blkEpoch = blkEpoch + self.TSShift.get()
-					newshift=self.TSShift.get()
-				else:
-					blkEpoch = blkEpoch + self.TSShift.get()
-					newshift=self.TSShift.get()
-			else:
-				#if type=add (i.e. 0), apply new shift to Epoch
-				# shift value in header equals old + new shift
-				# if an old shift  shift exists and is applied
-				if shift_applied and oldshift:
-					newshift = self.TSShift.get() + oldshift
-					blkEpoch = blkEpoch + self.TSShift.get()
-				# if an old shift  exists and is not applied
-				elif not shift_applied and oldshift:
-					newshift = self.TSShift.get() + oldshift
-					blkEpoch = blkEpoch + self.TSShift.get() + oldshift
-				else:
-					newshift = self.TSShift.get()
-					blkEpoch = blkEpoch + self.TSShift.get()
-
-
-			hdrs[3][4] = newshift/0.0001
-			EpochInt=int(blkEpoch)
-			EpochDec=(blkEpoch-EpochInt)
-			newMicro=round(EpochDec/0.0001)
-
-			#build new start time entry
-			(year, month, day, hour, min, sec, wkday, jday, dst) = time.gmtime(EpochInt)
-
-			#set/unset Activity flag to indicate time shift
-			if newshift:
-				hdrs[3][0] = self.SetFlag(hdrs[3][0], 1)
-			else:
-				hdrs[3][0] = self.SetFlag(hdrs[3][0], 1, "unset")
-
-			#set/unset Data Quality flag to indicate "Time tag questionable"
-			if self.TimeTagQuest.get():
-				action = self.TimeTagQuest.get()
-				hdrs[3][2] = self.SetFlag(hdrs[3][2], 7, action)
-
-
-			newhdrs= (hdrs[0], (year, jday, hour, min, sec, junk, newMicro), hdrs[2], hdrs[3])
-
-			bytes_written = msfile.WriteFixedHdr(newhdrs, n*blksize)
-
-			# This block of code should be activated. What needs to happen is that for every
-			# blockette that has a BTime entry, that entry should be shifted based on the above
-			# logic.
-# 			numblk=hdrs[3][3]
-# 			addseek=hdrs[3][6]
-# 			b=0
-		#loop over number of blockettes following fixed header at block n
-		# I should be searching for blk 500 here.
-# 			while b < numblk:
-# 				seekval=(n*blksize)+addseek
-# 				(blktype, next)=msfile.typenxt(seekval)
-# 				print blktype, next
-# 				getBlkCmd="blklist=msfile.blk" + str(blktype) + "(" + str(seekval) + ")"
-# 				exec getBlkCmd
-# 				addseek=next
-# 				b+=1
-			n+=1
-		#get endianess before closing
-		msfile.close()
-
-		# some user info
-		if blk_err:
-			err=str(blk_err) +" blockettes had the wrong key in file: " + ifile
-			self.WriteLog(err, "Time", "red")
-			err="\tNO CORRECTION APPLIED TO THESE BLOCKETTES"
-			self.WriteLog(err, "Time", "red")
-			if blk_err == numblocks: return 0
-		#	clear variables etc.
-
-		return 1
+    def TimeSet(self, ifile,startEpoch, endEpoch):
+        """
+        apply time correction to given mseed file
+        """
+
+        # first test to see if time shift will exceed field size
+        ShiftErr = self.TestTimeShift()
+        if ShiftErr:
+            self.addTextInfoBar(ShiftErr, "red")
+            self.WriteLog(ShiftErr, "Time", "red")
+            return 0
+
+        #open mseed files for correction
+        msfile = Mseed(ifile)
+        filesize = msfile.filesize
+        blksize = msfile.blksize
+        (numblocks, odd_size) = divmod(filesize, blksize)
+
+        # loop through file applying correction
+        blk_err = 0
+        n = 0
+        while n < numblocks:
+
+            hdrs = msfile.fixedhdr(n*blksize)
+
+            # more test just incase, this will fail if headers have been
+            # change w/o updating the db
+            (SeqNum, DHQual, res, Stat, Loc, Chan, Net)=hdrs[0]
+            Stat = Stat.strip()
+            if self.WildLoc.get():
+                Loc = "*"
+            else:
+                Loc = Loc.strip()
+            Net = Net.strip()
+            key = Stat.decode() + ":" + Loc.decode() + ":" + Net.decode()
+            if key != self.TimeShiftName.get():
+                blk_err += 1
+                n += 1
+                continue
+
+            # determine time of blockette and process if between startEpoch
+            # & endEpoch
+            (Year, Day, Hour, Min, Sec, junk, Micro) = hdrs[1]
+            timestr = ":".join(map(str,(Year, Day, Hour, Min, Sec)))
+            time_str = time.strptime(timestr, '%Y:%j:%H:%M:%S')
+            blkEpoch = time.mktime(time_str) + (Micro * 0.0001)
+            if startEpoch <= blkEpoch and blkEpoch <= endEpoch:
+                pass
+            else:
+                n += 1
+                continue
+
+            oldshift = hdrs[3][4] * 0.0001
+            shift_applied = int(hdrs[3][0][6])
+            # if type=replace (i.e. 1), remove oldtime shift from Epoch
+            # and then apply new shift value in header equals new shift
+            if self.TypeTimeCor.get():
+                # if an old shift exists and is applied
+                if shift_applied and oldshift:
+                    blkEpoch = blkEpoch + self.TSShift.get() - oldshift
+                    newshift = self.TSShift.get()
+                # if an old shift  shift exists and is not applied
+                elif not shift_applied and oldshift:
+                    blkEpoch = blkEpoch + self.TSShift.get()
+                    newshift = self.TSShift.get()
+                else:
+                    blkEpoch = blkEpoch + self.TSShift.get()
+                    newshift = self.TSShift.get()
+            else:
+                # if type=add (i.e. 0), apply new shift to Epoch
+                # shift value in header equals old + new shift
+                # if an old shift  shift exists and is applied
+                if shift_applied and oldshift:
+                    newshift = self.TSShift.get() + oldshift
+                    blkEpoch = blkEpoch + self.TSShift.get()
+                # if an old shift  exists and is not applied
+                elif not shift_applied and oldshift:
+                    newshift = self.TSShift.get() + oldshift
+                    blkEpoch = blkEpoch + self.TSShift.get() + oldshift
+                else:
+                    newshift = self.TSShift.get()
+                    blkEpoch = blkEpoch + self.TSShift.get()
+
+
+            hdrs[3][4] = int(newshift/0.0001)
+            EpochInt = int(blkEpoch)
+            EpochDec = (blkEpoch-EpochInt)
+            newMicro = round(EpochDec/0.0001)
+
+            #build new start time entry
+            (year, month, day, hour, min, sec, wkday, jday, dst) = \
+                time.gmtime(EpochInt)
+
+            #set/unset Activity flag to indicate time shift
+            if newshift:
+                hdrs[3][0] = self.SetFlag(hdrs[3][0], 1)
+            else:
+                hdrs[3][0] = self.SetFlag(hdrs[3][0], 1, "unset")
+
+            #set/unset Data Quality flag to indicate "Time tag questionable"
+            if self.TimeTagQuest.get():
+                action = self.TimeTagQuest.get()
+                hdrs[3][2] = self.SetFlag(hdrs[3][2], 7, action)
+
+
+            newhdrs = (hdrs[0], (year, jday, hour, min, sec, junk, newMicro),
+                       hdrs[2], hdrs[3])
+
+            bytes_written = msfile.WriteFixedHdr(newhdrs, n*blksize)
+
+            # This block of code should be activated. What needs to happen
+            # is that for every blockette that has a BTime entry, that entry
+            # should be shifted based on the above logic.
+            #numblk=hdrs[3][3]
+            #addseek=hdrs[3][6]
+            #b=0
+        #loop over number of blockettes following fixed header at block n
+        # I should be searching for blk 500 here.
+            #while b < numblk:
+                    #seekval=(n*blksize)+addseek
+                    #(blktype, next)=msfile.typenxt(seekval)
+                    #print blktype, next
+                    #getBlkCmd="blklist=msfile.blk" + str(blktype) + "(" +
+                    #    str(seekval) + ")"
+                    #exec getBlkCmd
+                    #addseek=next
+                    #b+=1
+            n += 1
+        #get endianess before closing
+        msfile.close()
+
+        # some user info
+        if blk_err:
+            err = str(blk_err) + " blockettes had the wrong key in file: " + \
+                ifile
+            self.WriteLog(err, "Time", "red")
+            err = "\tNO CORRECTION APPLIED TO THESE BLOCKETTES"
+            self.WriteLog(err, "Time", "red")
+            if blk_err == numblocks: return 0
+        #        clear variables etc.
+
+        return 1
 
 #######################################
-	def TestTimeShift(self):
-		"""
-		Test if time correction exceeds field
-		At this point this is a very brute test. The second half of the code (presently
-		commented) tests each blockette for time corrections and then determines if the
-		resultant correction will exceed the field. I believe that this is un-necessary
-		and definitely adds time.
-		"""
-		# if replacing existing correction we just need to test if entered time exceeds
-		# field size
-		# convert sec to 0.0001 sec
-#		if self.TypeTimeCor.get():
-		NewShiftmSec = (self.TSShift.get())/0.0001
-		if -2**31 >= NewShiftmSec or NewShiftmSec >= (2**31)-1 :
-			err= "Time Correction exceeds limits of field [-2**31 <= TimeCorr <= (2**31)-1]"
-			return err
-		# if adding to existing we need to test all corrections for a given file to see if the
-		# resultant correction exceeds field size
-# 		else:
-# 			# open mseed file
-# #			try:
-# 			msfile=Mseed(ifile)
-# #				(filesize,blksize)=msfile.sizes()
-# 				#initialize variables, lists, and dicts for later
-# 			filesize=msfile.filesize
-# 			blksize=msfile.blksize
-# 			(numblocks, odd_size)=divmod(filesize, blksize)
-# # 			except:
-# # 				err= "Corrupt mseed: " + ifile
-# # 				msfile.close()
-# # 				return err
-# 			# loop through file, snarf time corrections and test for size
-# 			blk_err=0
-# 			n=0
-# 			while n < numblocks:
-# 				hdrs=msfile.fixedhdr(n*blksize)
-# 				oldshift= hdrs[3][4] * 0.0001
-# 				# if an old shift exists and is applied
-# 				if oldshift:
-# 					newshift = self.TSShift.get() + oldshift
-# 				else:
-# 					newshift = self.TSShift.get()
-#
-# 				NewShiftmSec = newshift/0.0001
-# 				if -2**31 >= NewShiftmSec or NewShiftmSec >= (2**31)-1 :
-# 					err= "Time Correction exceeds limits of field [-2**31 <= TimeCorr <= (2**31)-1]"
-# 					return err
-# 				n+=1
-# 			msfile.close()
-		return 0
+    def TestTimeShift(self):
+        """
+        Test if time correction exceeds field
+        At this point this is a very brute test. The second half of the code
+        (presently commented) tests each blockette for time corrections and
+        then determines if the resultant correction will exceed the field. I
+        believe that this is un-necessary and definitely adds time.
+        """
+        # if replacing existing correction we just need to test if entered time exceeds
+        # field size
+        # convert sec to 0.0001 sec
+#                if self.TypeTimeCor.get():
+        NewShiftmSec = (self.TSShift.get())/0.0001
+        if -2**31 >= NewShiftmSec or NewShiftmSec >= (2**31)-1 :
+            err = "Time Correction exceeds limits of field [-2**31 <= "\
+                "TimeCorr <= (2**31)-1]"
+            return err
+        # if adding to existing we need to test all corrections for a given file to see if the
+        # resultant correction exceeds field size
+        #else:
+                ## open mseed file
+                #try:
+                #msfile=Mseed(ifile)
+                        #(filesize,blksize)=msfile.sizes()
+                        ##initialize variables, lists, and dicts for later
+                #filesize=msfile.filesize
+                #blksize=msfile.blksize
+                #(numblocks, odd_size)=divmod(filesize, blksize)
+                 #except Exception as e:
+                         #err= "Corrupt mseed: " + ifile
+                         #msfile.close()
+                         #return err
+                ## loop through file, snarf time corrections and test for size
+                #blk_err=0
+                #n=0
+                #while n < numblocks:
+                        #hdrs=msfile.fixedhdr(n*blksize)
+                        #oldshift= hdrs[3][4] * 0.0001
+                        ## if an old shift exists and is applied
+                        #if oldshift:
+                                #newshift = self.TSShift.get() + oldshift
+                        #else:
+                                #newshift = self.TSShift.get()
+
+                        #NewShiftmSec = newshift/0.0001
+                        #if -2**31 >= NewShiftmSec or NewShiftmSec >=
+                        # (2**31)-1 :
+                                #err= "Time Correction exceeds limits of
+                                # field [-2**31 <= TimeCorr <= (2**31)-1]"
+                                #return err
+                        #n+=1
+                #msfile.close()
+        return 0
 
 #######################################
-	def LoadTimeSelect(self,timeid):
-		"""
-		loads info for selected stat:loc:net key
-		"""
-		key=timeid
-		self.ClearAll(self.ShiftVars)
-		self.TypeTimeCor.set(0)
-		self.TimeTagQuest.set("")
-		self.SetTime.set(0)
-		self.SetTQuest.set(0)
-		self.TSStartTime.set("")
-		self.TSEndTime.set("")
-
-
-		# modify self.TimeShiftName if user wants wildcard
-		if self.WildLoc.get():
-			self.WildCardLoc()
-
-		#load info if Dictionary already has entry for selection
-		if self.UpdateTimeDict.has_key(key):
-			for var in self.ShiftVars:
-				if self.UpdateTimeDict[key].has_key(var[0]):
-					var[1].set(self.UpdateTimeDict[key][var[0]])
-
-			#test to see if time corrections have been applied. If so, do they match dictionary?
-			#if so, replace variable sets from above step
-			if self.SetTimeDict.has_key(key):
-				for var in self.ShiftVars:
-					if self.SetTimeDict[key].has_key(var[0]):
-						var[1].set(self.SetTimeDict[key][var[0]])
-				if self.TSShift.get(): self.SetTime.set(1)
-				if self.TimeTagQuest.get(): self.SetTQuest.set(1)
-
-		else:
-			self.GetStartEnd()
-
-		# if TopLevel tracelist window is open, update it
-		try:
-			if self.TimeCorList_tl.winfo_exists():
-				self.ListTimeCor(self.TimeShift_nb)
-		except:
-			pass
+    def LoadTimeSelect(self,timeid):
+        """
+        loads info for selected stat:loc:net key
+        """
+        key=timeid
+        self.ClearAll(self.ShiftVars)
+        self.TypeTimeCor.set(0)
+        self.TimeTagQuest.set("")
+        self.SetTime.set(0)
+        self.SetTQuest.set(0)
+        self.TSStartTime.set("")
+        self.TSEndTime.set("")
+
+
+        # modify self.TimeShiftName if user wants wildcard
+        if self.WildLoc.get():
+            self.WildCardLoc()
+
+        #load info if Dictionary already has entry for selection
+        if key in self.UpdateTimeDict:
+            for var in self.ShiftVars:
+                if var[0] in self.UpdateTimeDict[key]:
+                    var[1].set(self.UpdateTimeDict[key][var[0]])
+
+            # test to see if time corrections have been applied.
+            # If so, do they match dictionary?
+            # if so, replace variable sets from above step
+            if key in self.SetTimeDict:
+                for var in self.ShiftVars:
+                    if var[0] in self.SetTimeDict[key]:
+                        var[1].set(self.SetTimeDict[key][var[0]])
+                if self.TSShift.get():
+                    self.SetTime.set(1)
+                if self.TimeTagQuest.get():
+                    self.SetTQuest.set(1)
+
+        else:
+            self.GetStartEnd()
+
+        # if TopLevel tracelist window is open, update it
+        try:
+            if self.TimeCorList_tl.winfo_exists():
+                self.ListTimeCor(self.TimeShift_nb)
+        except Exception as e:
+            pass
 
 #######################################
-	def RecalcStartEnd(self):
-		"""
-		recalculates start and endtimes for traces for a given stat:loc:net key
-		"""
-
-		timeid = self.TimeShiftName.get()
-
-		#clear entry if time is already calculated and Traces loaded
-		if self.TraceTimeDict.has_key(timeid):
-			del self.TraceTimeDict[timeid]
-		self.GetStartEnd()
+    def RecalcStartEnd(self):
+        """
+        recalculates start and endtimes for traces for a given
+        stat:loc:net key
+        """
+
+        timeid = self.TimeShiftName.get()
+
+        #clear entry if time is already calculated and Traces loaded
+        if timeid in self.TraceTimeDict:
+            del self.TraceTimeDict[timeid]
+        self.GetStartEnd()
 #######################################
-	def GetStartEnd(self):
-		"""
-		Gets start and endtimes for traces for a given stat:loc:net key
-		"""
-#		self.WildButton.configure(state="disabled")
-		timeid = self.TimeShiftName.get()
-
-		#don't spend time here if time is already calculated and Traces loaded
-		if self.TraceTimeDict.has_key(timeid):
-			try:
-				if self.TraceTimeDict[timeid][0]:	#see if begin and end times exist
-					self.FillTime(timeid)
-					return
-			except:
-				pass
-
-		textstr = "Examining traces for key: " + timeid
-		self.addTextInfoBar(textstr, 'lightblue')
-
-		(keystat,keyloc,keynet)=string.split(timeid, ":")
-		cnt=0
-		for key in self.TraceDict.keys():
-			(stat,chan,loc,net,sps)=string.split(key, ":")
-			if keystat == stat and keynet == net and \
-			   (keyloc == loc or keyloc == "*"):
-				for infile in self.TraceDict[key] :
-					cnt+=1
-					if mod(cnt, 10):
-						pass
-					else:
-						textstr="Key: " + timeid + " Examining Trace: "
-						self.wait(textstr, cnt)
-
-# at this point all files in TraceDict should be mseed files, so not testing here
-					msfile = Mseed(infile)
-					try:
-						(begintime, endtime) = msfile.FirstLastTime()
-						if cnt == 1: #and [begintime,endtime] not in self.TraceTimeDict[timeid]:
-							self.TraceTimeDict[timeid] = []
-							self.TraceTimeDict[timeid].append([begintime,endtime])
-							self.TraceTimeDict[timeid].append([infile,begintime,endtime])
-						else:
-							if not [infile,begintime,endtime] in self.TraceTimeDict[timeid]:
-								if begintime < self.TraceTimeDict[timeid][0][0]:
-									self.TraceTimeDict[timeid][0][0] = begintime
-								if endtime > self.TraceTimeDict[timeid][0][1]:
-									self.TraceTimeDict[timeid][0][1] = endtime
-								self.TraceTimeDict[timeid].append([infile,begintime,endtime])
-					except:
-						logtext= "Corrupt mseed file: " + infile
-						self.WriteLog(logtext, 'Time', 'red')
-					msfile.close()
-			else:
-				continue
-		if self.TraceTimeDict.has_key(timeid):
-			try:
-				self.FillTime(timeid)
-			except:
-				err = "Cannot determine begin and end times for " + timeid + ". See log"
-				self.addTextInfoBar(err, 'red')
+    def GetStartEnd(self):
+        """
+        Gets start and endtimes for traces for a given stat:loc:net key
+        """
+#                self.WildButton.configure(state="disabled")
+        timeid = self.TimeShiftName.get()
+        if not timeid:
+            self.addTextInfoBar("No Sta:Loc:Net selected", 'orange')
+            return        
+
+        # don't spend time here if time is already calculated
+        # and Traces loaded
+        if timeid in self.TraceTimeDict:
+            try:
+                if self.TraceTimeDict[timeid][0]:
+                    #see if begin and end times exist
+                    self.FillTime(timeid)
+                    return
+            except Exception as e:
+                pass
+
+        textstr = "Examining traces for key: " + timeid
+        self.addTextInfoBar(textstr, 'lightblue')
+
+        (keystat,keyloc,keynet) = timeid.split(":")
+        cnt=0
+        for key in self.TraceDict:
+            (stat, chan, loc, net, sps) = key.split(":")
+            if keystat == stat and keynet == net and \
+               (keyloc == loc or keyloc == "*"):
+                for infile in self.TraceDict[key] :
+                    cnt += 1
+                    if mod(cnt, 10):
+                        pass
+                    else:
+                        textstr = "Key: " + timeid + " Examining Trace: "
+                        self.wait(textstr, cnt)
+
+                    # at this point all files in TraceDict should be mseed
+                    # files, so not testing here
+                    msfile = Mseed(infile)
+                    try:
+                        (begintime, endtime) = msfile.FirstLastTime()
+                        if cnt == 1:
+                            # and [begintime,endtime] not in
+                            # self.TraceTimeDict[timeid]:
+                            self.TraceTimeDict[timeid] = []
+                            self.TraceTimeDict[timeid].append(
+                                [begintime,endtime])
+                            self.TraceTimeDict[timeid].append(
+                                [infile,begintime,endtime])
+                        else:
+                            if not [infile,begintime,endtime] \
+                               in self.TraceTimeDict[timeid]:
+                                if begintime < self.TraceTimeDict[timeid][0][0]:
+                                    self.TraceTimeDict[timeid][0][0] = \
+                                        begintime
+                                if endtime > self.TraceTimeDict[timeid][0][1]:
+                                    self.TraceTimeDict[timeid][0][1] = endtime
+                                self.TraceTimeDict[timeid].append(
+                                    [infile,begintime,endtime])
+                    except Exception as e:
+                        logtext= "Corrupt mseed file: " + infile
+                        self.WriteLog(logtext, 'Time', 'red')
+                    msfile.close()
+            else:
+                continue
+        if timeid in self.TraceTimeDict:
+            try:
+                self.FillTime(timeid)
+            except Exception as e:
+                err = "Cannot determine begin and end times for " + timeid + \
+                    ". See log"
+                self.addTextInfoBar(err, 'red')
 
 ##################################################################
-	def FillTime(self, keyname):
-		"""
-		fills time and count for Time Shift nb
-		"""
-		startepoch=self.TraceTimeDict[keyname][0][0]
-		#decided not to used micro sec accuracy since round off errors are creating problems
-# 		micro= int((startepoch - int(startepoch)) / 0.0001)
-# 		micro=str(micro)
-# 		numz=4-len(micro)
-# 		micro=numz*"0" + micro
-		start = time.strftime('%Y:%j:%H:%M:%S', time.gmtime(startepoch))
-#		start=start + "." + str(micro)
-		self.TSStartTime.set(start)
-
-		endepoch=self.TraceTimeDict[keyname][0][1]
-		#to make sure we pickup the last block
-		endepoch+=1
-		#decided not to used micro sec accuracy since round off errors are creating problems
-# 		micro= int((endepoch - int(endepoch)) / 0.0001)
-# 		micro=str(micro)
-# 		numz=4-len(micro)
-# 		micro=numz*"0" + micro
-		end = time.strftime('%Y:%j:%H:%M:%S', time.gmtime(endepoch))
-#		end=end + "." + str(micro)
-		self.TSEndTime.set(end)
-
-		cnt=len(self.TraceTimeDict[keyname]) - 1 # first record has min/max time for keyname
-		textstr = str(cnt) + " traces selected for key: " + keyname
-		self.addTextInfoBar(textstr, 'lightblue')
+    def FillTime(self, keyname):
+        """
+        fills time and count for Time Shift nb
+        """
+        startepoch=self.TraceTimeDict[keyname][0][0]
+        # decided not to used micro sec accuracy since round off errors
+        # are creating problems
+        #micro= int((startepoch - int(startepoch)) / 0.0001)
+        #micro=str(micro)
+        #numz=4-len(micro)
+        #micro=numz*"0" + micro
+        start = time.strftime('%Y:%j:%H:%M:%S', time.gmtime(startepoch))
+        #start=start + "." + str(micro)
+        self.TSStartTime.set(start)
+
+        endepoch=self.TraceTimeDict[keyname][0][1]
+        # to make sure we pickup the last block
+        endepoch+=1
+        # decided not to used micro sec accuracy since round off errors
+        # are creating problems
+        #micro= int((endepoch - int(endepoch)) / 0.0001)
+        #micro=str(micro)
+        #numz=4-len(micro)
+        #micro=numz*"0" + micro
+        end = time.strftime('%Y:%j:%H:%M:%S', time.gmtime(endepoch))
+        # end=end + "." + str(micro)
+        self.TSEndTime.set(end)
+        # first record has min/max time for keyname
+        cnt = len(self.TraceTimeDict[keyname]) - 1 
+        textstr = str(cnt) + " traces selected for key: " + keyname
+        self.addTextInfoBar(textstr, 'lightblue')
 
 ##################################################################
-	def MkNumChar(self, instr, num):
-		"""
-		appends num-len(instr) 0 to input string
-		or truncates string to num chars
-		"""
-		if len(instr) < num:
-			m= num - len(instr)
-			return instr + m*"0"
-		elif len(instr) > num:
-			return instr[0:num]
-		else:
-			return instr
+    def MkNumChar(self, instr, num):
+        """
+        appends num-len(instr) 0 to input string
+        or truncates string to num chars
+        """
+        if len(instr) < num:
+            m= num - len(instr)
+            return instr + m*"0"
+        elif len(instr) > num:
+            return instr[0:num]
+        else:
+            return instr
 #########################################################
-	def WriteLog(self, info, type="", color="black"):
-		"""
-		writes text to log notebook
-		"""
-		#local variables
-		LogAllappend=self.LogAll.append
-		LogHeaderappend=self.LogHeader.append
-		LogTimeappend=self.LogTime.append
-		LogEndianappend=self.LogEndian.append
-
-		if BATCHMODE:
-			if info:
-				print info
-		else:
-			info=info + "\n"
-			LogAllappend((info, color))
-
-			if type == "Header":
-				LogHeaderappend((info, color))
-			elif type == "Time":
-				LogTimeappend((info, color))
-			elif type == "Endian":
-				LogEndianappend((info, color))
-			else:
-				pass
-
-			self.DisplayLog()
+    def WriteLog(self, info, type="", color="black"):
+        """
+        writes text to log notebook
+        """
+        #local variables
+        LogAllappend = self.LogAll.append
+        LogHeaderappend = self.LogHeader.append
+        LogTimeappend = self.LogTime.append
+        LogEndianappend = self.LogEndian.append
+
+        if BATCHMODE:
+            if info:
+                print(info)
+        else:
+            info=info + "\n"
+            LogAllappend((info, color))
+
+            if type == "Header":
+                LogHeaderappend((info, color))
+            elif type == "Time":
+                LogTimeappend((info, color))
+            elif type == "Endian":
+                LogEndianappend((info, color))
+            else:
+                pass
+
+            self.DisplayLog()
 ##################################################################
-	def DisplayLog(self):
-		"""
-		filters log entries
-		"""
-		#local variables
-		LogVarget=self.LogVar.get
-		LogTextinsert=self.LogText.insert
-
-		self.LogText.clear()
-		if LogVarget() == 0: textlist=self.LogAll
-		elif LogVarget() == 1: textlist=self.LogHeader
-		elif LogVarget() == 2: textlist=self.LogTime
-		elif LogVarget() == 3: textlist=self.LogEndian
-		elif LogVarget() == 4: textlist=self.LogSummary
-		else: return
-		for (textcmd, color) in textlist:
-			LogTextinsert('end', textcmd, color)
+    def DisplayLog(self):
+        """
+        filters log entries
+        """
+        #local variables
+        LogVarget = self.LogVar.get
+        LogTextinsert = self.LogText.insert
+
+        self.LogText.clear()
+        if LogVarget() == 0:
+            textlist = self.LogAll
+        elif LogVarget() == 1:
+            textlist = self.LogHeader
+        elif LogVarget() == 2:
+            textlist = self.LogTime
+        elif LogVarget() == 3:
+            textlist = self.LogEndian
+        elif LogVarget() == 4:
+            textlist = self.LogSummary
+        else: return
+        for (textcmd, color) in textlist:
+            LogTextinsert('end', textcmd, color)
 
 ##################################################################
-	def FlushLogs(self):
-		"""
-		flushes logs
-		"""
-		self.LogAll=[]
-		self.LogHeader=[]
-		self.LogTime=[]
-		self.LogEndian=[]
-		self.LogSummary=[]
-		self.LogText.clear()
+    def FlushLogs(self):
+        """
+        flushes logs
+        """
+        self.LogAll = []
+        self.LogHeader = []
+        self.LogTime = []
+        self.LogEndian = []
+        self.LogSummary = []
+        self.LogText.clear()
 
 #######################################
-	def LaunchChangeEndian(self, endian) :
-		"""
-		separated out so ChangeEndian could be run as a thread
-		"""
-		self.RunChangeEndian.set(1)
-
-		if endian == "big":
-			self.ToEndian.set("big")
-		else:
-			self.ToEndian.set("little")
-		#launch thread
-		#eRun=threading.Thread(target=self.ChangeEndian)
-		self.ChangeEndian()
-		#eRun.start()
-		# stay here until thread dies
-		#eRun.join()
-
-		if self.RunChangeEndian.get():
-			self.KillCancelTL(self.RunChangeEndian)
-		self.ActiveText.set("")
+    def LaunchChangeEndian(self, endian) :
+        """
+        separated out so ChangeEndian could be run as a thread
+        """
+        self.RunChangeEndian.set(1)
+
+        if endian == "big":
+            self.ToEndian.set("big")
+        else:
+            self.ToEndian.set("little")
+        #launch thread
+        #eRun=threading.Thread(target=self.ChangeEndian)
+        self.ChangeEndian()
+        #eRun.start()
+        # stay here until thread dies
+        #eRun.join()
+
+        if self.RunChangeEndian.get():
+            self.KillCancelTL(self.RunChangeEndian)
+        self.ActiveText.set("")
 
 ##################################################################
-	def ChangeEndian(self):
-		"""
-		rewrites all blockettes in either big or little endian
-		"""
-
-		if not BATCHMODE:
-			self.CancelTL(self.RunChangeEndian, "Change Endianess")
-
-		self.ActiveText.set("Changing Endianess")
-		endian=self.ToEndian.get()
-		if endian == "big":
-			inlist=self.LittleEndianList
-			outlist=self.BigEndianList
-			numfiles=len(self.LittleEndianList)
-			if not numfiles:
-				err="No Little Endian Files Found"
-				self.addTextInfoBar(err, "red")
-				return
-		else:
-			inlist=self.BigEndianList
-			outlist=self.LittleEndianList
-			numfiles=len(self.BigEndianList)
-			if not numfiles:
-				err="No Big Endian Files Found"
-				self.addTextInfoBar(err, "red")
-				return
-
-		files_left=numfiles
-		textstr="Files Remaining: "
-		self.wait(textstr, files_left)
-
-
-		#write log and user information
-		self.WriteLog("\n<Change Endianess>", "Endian", "blue")
-		logtext= "\tSelected " + str(numfiles) + " traces to convert to " + endian + " endian headers"
-		self.WriteLog(logtext, "Endian", "black")
-
-		# loop over files reading & writing blockettes
-		corr_files=0
-		while inlist:
-			ErrFlag=0
-			#respond to cancel requests
-			if not self.RunChangeEndian.get():
-				break
-			ifile=inlist.pop()
-			# 	info for user
-			if mod(files_left, 5):
-				pass
-			else:
-				self.wait(textstr, files_left)
-			files_left-=1
-
-			msfile=Mseed(ifile)
-			#local variables'
-			fixedhdr=msfile.fixedhdr
-			WriteFixedHdr=msfile.WriteFixedHdr
-			typenxt=msfile.typenxt
-			GetBlk=msfile.GetBlk
-			PutBlk=msfile.PutBlk
-
-			filesize=msfile.filesize
-			blksize=msfile.blksize
-			(numblocks, odd_size)=divmod(filesize, blksize)
-			outlist.append(ifile)
-
-			blk_err=0
-			n=0
-			while n < numblocks:
-				#read & rewrite fixed header
-				hdrs=fixedhdr(n*blksize)
-				bytes_written = WriteFixedHdr(hdrs, n*blksize, endian)
-				numblk=hdrs[3][3]
-				addseek=hdrs[3][6]
-				b=0
-				#loop over number of blockettes following fixed header at block n
-				while b < numblk:
-					seekval=(n*blksize)+addseek
-					(blktype, next)=typenxt(seekval)
-					blklist=GetBlk(blktype, seekval)
-					if not blklist:
-						#if blockette error encountered bail and undo endian changes
-						err= "\n\tCorrupt mseed: " + ifile
-						self.WriteLog(err,"Endian","red")
-						err= "\t\tFile removed from Trace db"
-						self.WriteLog(err,"Endian","red")
-						err= "\t\tRecord: " + str(n)
-						self.WriteLog(err,"Endian","red")
-						err= "\t\tUnrecognized Blockette: " + str(blktype)
-						self.WriteLog(err,"Endian","red")
-						msfile.close()
-						self.UndoEndian(ifile, n, b, endian)
-						#remove file from list
-						outlist.pop()
-						#set error flag
-						ErrFlag=1
-						#ensure outer while block will end
-						n+=numblocks
-						break
-					else:
-						bytes_written=PutBlk(blktype, blklist, endian, seekval)
-					addseek=next
-					b+=1
-				n+=1
-			if not ErrFlag:
-				corr_files+=1
-				msfile.close()
-
-		#flush endian list to prevent redoing process
-		if endian == "big":
-			self.LittleEndianList=inlist
-			self.BigEndianList=outlist
-		else:
-			self.BigEndianList=inlist
-			self.LittleEndianList=outlist
-
-		self.NumBigFiles.set(len(self.BigEndianList))
-		self.NumLittleFiles.set(len(self.LittleEndianList))
-
-		#write log and user information
-		logtext= "\n\tConverted " + str(corr_files) + " traces to " + endian + " endian headers"
-		self.WriteLog(logtext, "Endian", 'black')
-		self.WriteLog("<end>", "Endian", 'blue')
-
-		infotext= "\nDone. Converted: " + str(corr_files) + " files."
-		self.addTextInfoBar(infotext, 'green')
+    def ChangeEndian(self):
+        """
+        rewrites all blockettes in either big or little endian
+        """
+
+        if not BATCHMODE:
+            self.CancelTL(self.RunChangeEndian, "Change Endianess")
+
+        self.ActiveText.set("Changing Endianess")
+        endian=self.ToEndian.get()
+        if endian == "big":
+            inlist=self.LittleEndianList
+            outlist=self.BigEndianList
+            numfiles=len(self.LittleEndianList)
+            if not numfiles:
+                err="No Little Endian Files Found"
+                self.addTextInfoBar(err, "red")
+                return
+        else:
+            inlist=self.BigEndianList
+            outlist=self.LittleEndianList
+            numfiles=len(self.BigEndianList)
+            if not numfiles:
+                err="No Big Endian Files Found"
+                self.addTextInfoBar(err, "red")
+                return
+
+        files_left=numfiles
+        textstr="Files Remaining: "
+        self.wait(textstr, files_left)
+
+
+        #write log and user information
+        self.WriteLog("\n<Change Endianess>", "Endian", "blue")
+        logtext= "\tSelected " + str(numfiles) + " traces to convert to " + \
+            endian + " endian headers"
+        self.WriteLog(logtext, "Endian", "black")
+
+        # loop over files reading & writing blockettes
+        corr_files=0
+        while inlist:
+            ErrFlag=0
+            #respond to cancel requests
+            if not self.RunChangeEndian.get():
+                break
+            ifile=inlist.pop()
+            #         info for user
+            if mod(files_left, 5):
+                pass
+            else:
+                self.wait(textstr, files_left)
+            files_left-=1
+
+            msfile=Mseed(ifile)
+            #local variables'
+            fixedhdr = msfile.fixedhdr
+            WriteFixedHdr = msfile.WriteFixedHdr
+            typenxt = msfile.typenxt
+            GetBlk = msfile.GetBlk
+            PutBlk = msfile.PutBlk
+
+            filesize = msfile.filesize
+            blksize = msfile.blksize
+            (numblocks, odd_size) = divmod(filesize, blksize)
+            outlist.append(ifile)
+
+            blk_err=0
+            n=0
+            while n < numblocks:
+                #read & rewrite fixed header
+                hdrs = fixedhdr(n*blksize)
+                bytes_written = WriteFixedHdr(hdrs, n*blksize, endian)
+                numblk = hdrs[3][3]
+                addseek = hdrs[3][6]
+                b = 0
+                # loop over number of blockettes following fixed header at
+                # block n
+                while b < numblk:
+                    seekval = (n*blksize)+addseek
+                    (blktype, next) = typenxt(seekval)
+                    blklist = GetBlk(blktype, seekval)
+                    if not blklist:
+                        # if blockette error encountered bail and undo endian
+                        # changes
+                        err = "\n\tCorrupt mseed: " + ifile
+                        self.WriteLog(err,"Endian","red")
+                        err = "\t\tFile removed from Trace db"
+                        self.WriteLog(err,"Endian","red")
+                        err = "\t\tRecord: " + str(n)
+                        self.WriteLog(err,"Endian","red")
+                        err = "\t\tUnrecognized Blockette: " + str(blktype)
+                        self.WriteLog(err,"Endian","red")
+                        msfile.close()
+                        self.UndoEndian(ifile, n, b, endian)
+                        #remove file from list
+                        outlist.pop()
+                        #set error flag
+                        ErrFlag = 1
+                        #ensure outer while block will end
+                        n += numblocks
+                        break
+                    else:
+                        bytes_written = PutBlk(
+                            blktype, blklist, endian, seekval)
+                    addseek = next
+                    b += 1
+                n += 1
+            if not ErrFlag:
+                corr_files += 1
+                msfile.close()
+
+        #flush endian list to prevent redoing process
+        if endian == "big":
+            self.LittleEndianList = inlist
+            self.BigEndianList = outlist
+        else:
+            self.BigEndianList = inlist
+            self.LittleEndianList = outlist
+
+        self.NumBigFiles.set(len(self.BigEndianList))
+        self.NumLittleFiles.set(len(self.LittleEndianList))
+
+        #write log and user information
+        logtext = "\n\tConverted " + str(corr_files) + " traces to " + \
+            endian + " endian headers"
+        self.WriteLog(logtext, "Endian", 'black')
+        self.WriteLog("<end>", "Endian", 'blue')
+
+        infotext = "\nDone. Converted: " + str(corr_files) + " files."
+        self.addTextInfoBar(infotext, 'green')
 
 #########################################################
-	def UndoEndian(self, infile, recnum, blknum, endian):
-		"""
-		changes a corrupt mseed file back to original endianess
-		after ChangeEndian catches problem while reading file.
-		This approach is taken rather than scanning entire file first
-		that would take more time for non-problematic files.
-		"""
-		msfile=Mseed(infile)
-#		(filesize,blksize)=msfile.sizes()
-		filesize=msfile.filesize
-		blksize=msfile.blksize
-
-		n=0
-		# reverse endian
-		if endian == "big":
-			endian ="little"
-		else:
-			endian="big"
-		# loop upto position that gave a problem
-		while n <= recnum:
-			#read & rewrite fixed header
-			hdrs=msfile.fixedhdr(n*blksize)
-			bytes_written = msfile.WriteFixedHdr(hdrs, n*blksize, endian)
-			numblk=hdrs[3][3]
-			addseek=hdrs[3][6]
-			b=0
-			#correct upto the blockette that gave problems
-			while b < blknum:
-				seekval=(n*blksize)+addseek
-				(blktype, next)=msfile.typenxt(seekval)
-				blklist=msfile.GetBlk(blktype, seekval)
-				bytes_written=msfile.PutBlk(blktype, blklist, endian, seekval)
-				addseek=next
-				b+=1
-			n+=1
-		msfile.close()
-		return
+    def UndoEndian(self, infile, recnum, blknum, endian):
+        """
+        changes a corrupt mseed file back to original endianess
+        after ChangeEndian catches problem while reading file.
+        This approach is taken rather than scanning entire file first
+        that would take more time for non-problematic files.
+        """
+        msfile = Mseed(infile)
+        # (filesize,blksize)=msfile.sizes()
+        filesize = msfile.filesize
+        blksize = msfile.blksize
+
+        n = 0
+        # reverse endian
+        if endian == "big":
+            endian = "little"
+        else:
+            endian = "big"
+        # loop upto position that gave a problem
+        while n <= recnum:
+            #read & rewrite fixed header
+            hdrs = msfile.fixedhdr(n*blksize)
+            bytes_written = msfile.WriteFixedHdr(hdrs, n*blksize, endian)
+            numblk = hdrs[3][3]
+            addseek = hdrs[3][6]
+            b = 0
+            #correct upto the blockette that gave problems
+            while b < blknum:
+                seekval = (n*blksize)+addseek
+                (blktype, next) = msfile.typenxt(seekval)
+                blklist = msfile.GetBlk(blktype, seekval)
+                bytes_written = msfile.PutBlk(
+                    blktype, blklist, endian, seekval)
+                addseek = next
+                b += 1
+            n += 1
+        msfile.close()
+        return
 #########################################################
-	def SetFlag(self, instr, position, action="set"):
-		"""
-		sets/unsets flag in string representation of byte
-		"""
-		newstr=""
-		b=len(instr)-1
-		for a in instr:
-			if (b)==position:
-				if action=="set":
-					a="1"
-				else:
-					a="0"
-			newstr = newstr + a
-			b-=1
-		return newstr
+    def SetFlag(self, instr, position, action="set"):
+        """
+        sets/unsets flag in string representation of byte
+        """
+        newstr = ""
+        b = len(instr)-1
+        for a in instr:
+            if (b) == position:
+                if action == "set":
+                    a = "1"
+                else:
+                    a = "0"
+            newstr = newstr + a
+            b -= 1
+        return newstr
 #########################################################
-	def ListTrace(self, master):
-		"""
-		provide a toplevel window listing traces for a given key
-		"""
-		if not self.StationName.get():
-			self.addTextInfoBar("No Sta:Chan:Loc:Net:Sps selected", 'orange')
-			return
-		tracekey=self.StationName.get()
-
-		try:
-			self.tl_State = self.TraceList_tl.winfo_exists()
-		except:
-			self.tl_State = 0
-
-		if self.tl_State == 1:
-			self.TraceList_tl.tkraise()
-			self.TraceListText.clear()
-			#display info on selected block
-
-		else:
-			self.TraceList_tl = Toplevel(master)
-#			self.TraceList_tl.title("Trace Listing")
-
-			self.ExitTraceList_b = Button(self.TraceList_tl,
-						      activebackground = 'red',
-						      cursor = 'pirate',
-						      background = 'lightblue',
-						      text="Dismiss",
-						      command = Command(self.killWindow, self.TraceList_tl)
-						      )
-			self.ExitTraceList_b.pack(side='bottom', fill='x', expand=1)
-
-			self.TraceListText = Pmw.ScrolledText(self.TraceList_tl,
-							      borderframe=1)
-			self.TraceListText.pack(side='bottom', fill='both', expand=1)
-
-		self.TraceListText.tag_config("odd", background="lightblue")
-
-		cnt=len(self.TraceDict[tracekey])
-		wtitle= "Trace Listing: " + str(cnt) + " files listed"
-		self.TraceList_tl.title(wtitle)
-		self.TraceDict[tracekey].sort()
-		c=0
-		for infile in self.TraceDict[tracekey]:
-			if c :
-				self.TraceListText.insert("end", """%s\n""" % infile, "odd")
-				c=0
-			else :
-				self.TraceListText.insert("end", """%s\n""" % infile)
-				c+=1
+    def ListTrace(self, master):
+        """
+        provide a toplevel window listing traces for a given key
+        """
+        if not self.StationName.get():
+            self.addTextInfoBar("No Sta:Chan:Loc:Net:Sps selected", 'orange')
+            return
+        tracekey = self.StationName.get()
+
+        try:
+            self.tl_State = self.TraceList_tl.winfo_exists()
+        except Exception as e:
+            self.tl_State = 0
+
+        if self.tl_State == 1:
+            self.TraceList_tl.tkraise()
+            self.TraceListText.clear()
+            #display info on selected block
+
+        else:
+            self.TraceList_tl = Toplevel(master)
+#                        self.TraceList_tl.title("Trace Listing")
+
+            self.ExitTraceList_b = Button(self.TraceList_tl,
+                                          activebackground = 'red',
+                                          cursor = 'pirate',
+                                          background = 'lightblue',
+                                          text="Dismiss",
+                                          command = Command(self.killWindow,
+                                                            self.TraceList_tl)
+                                          )
+            self.ExitTraceList_b.pack(side='bottom', fill='x', expand=1)
+
+            self.TraceListText = Pmw.ScrolledText(self.TraceList_tl,
+                                                  borderframe=1)
+            self.TraceListText.pack(side='bottom', fill='both', expand=1)
+
+        self.TraceListText.tag_config("odd", background="lightblue")
+
+        cnt=len(self.TraceDict[tracekey])
+        wtitle= "Trace Listing: " + str(cnt) + " files listed"
+        self.TraceList_tl.title(wtitle)
+        self.TraceDict[tracekey] = sorted(self.TraceDict[tracekey])
+        c = 0
+        for infile in self.TraceDict[tracekey]:
+            if c :
+                self.TraceListText.insert("end", """%s\n""" % infile, "odd")
+                c = 0
+            else :
+                self.TraceListText.insert("end", """%s\n""" % infile)
+                c += 1
 
 #########################################################
-	def ListTimeCor(self, master):
-		"""
-		provide a toplevel window listing time corrections in fixed headers of traces for a given key
-		"""
-		if not self.TimeShiftName.get():
-			self.addTextInfoBar("No Sta:Loc:Net selected", 'orange')
-			return
-		tracekey=self.TimeShiftName.get()
-
-		try:
-			self.tl_State = self.TimeCorList_tl.winfo_exists()
-		except:
-			self.tl_State = 0
-
-		if self.tl_State == 1:
-			self.TimeCorList_tl.tkraise()
-			self.TimeCorListText.clear()
-			#display info on selected block
-
-		else:
-			self.TimeCorList_tl = Toplevel(master)
-			self.TimeCorList_tl.title("Time Corrections")
-
-			self.ExitTimeCorList_b = Button(self.TimeCorList_tl,
-							activebackground = 'red',
-							cursor = 'pirate',
-							background = 'lightblue',
-							text="Dismiss",
-							command = Command(self.killWindow, self.TimeCorList_tl)
-							)
-			self.ExitTimeCorList_b.pack(side='bottom', fill='x', expand=1)
-
-			self.TimeCorListText = Pmw.ScrolledText(self.TimeCorList_tl,
-								borderframe=1)
-			self.TimeCorListText.pack(side='bottom', fill='both', expand=1)
-
-		self.TimeCorListText.tag_config("odd", background="lightblue")
-		self.TimeCorListText.tag_config("yellow", background="yellow")
-		self.TimeCorListText.tag_config("orange", background="orange")
-
-		TimeDict=self.GetTimeCor()
-		self.TimeCorListText.clear()
-		c=0
-		addtext="\t******************************************"
-		self.TimeCorListText.insert("end", """%s\n""" % addtext, "yellow")
-		addtext="\t* Time Corrections Found in File Headers *"
-		self.TimeCorListText.insert("end", """%s\n""" % addtext, "yellow")
-		addtext="\t******************************************"
-		self.TimeCorListText.insert("end", """%s\n""" % addtext, "yellow")
-		tracelist=TimeDict.keys()
-		tracelist.sort()
-		for key in tracelist:
-#		for key in TimeDict.keys():
-			if c :
-				self.TimeCorListText.insert("end", """%s\n""" % key, "odd")
-				addtext=4*SPACE + "Block Start Time" + 6*SPACE + "Cor(s)" + 8*SPACE + "Status" + 14*SPACE + "Timing Questionable"
-				self.TimeCorListText.insert("end", """%s\n""" % addtext, "odd")
-				for tup in TimeDict[key]:
-					addtext=4*SPACE + str(tup[0])
-					splen=26-len(addtext)
-					addtext=addtext + splen*SPACE + str(tup[1])
-					splen=40-len(addtext)
-					addtext=addtext + splen*SPACE + str(tup[2])
-					splen=60-len(addtext)
-					addtext=addtext + splen*SPACE + str(tup[3])
-					self.TimeCorListText.insert("end", """%s\n""" % addtext, "odd")
-				c=0
-			else :
-				self.TimeCorListText.insert("end", """%s\n""" % key)
-				addtext=4*SPACE + "Block Start Time" + 6*SPACE + "Cor(s)" + 8*SPACE + "Status" + 14*SPACE + "Timing Questionable"
-				self.TimeCorListText.insert("end", """%s\n""" % addtext)
-				for tup in TimeDict[key]:
-					addtext=4*SPACE + str(tup[0])
-					splen=26-len(addtext)
-					addtext=addtext + splen*SPACE + str(tup[1])
-					splen=40-len(addtext)
-					addtext=addtext + splen*SPACE + str(tup[2])
-					splen=60-len(addtext)
-					addtext=addtext + splen*SPACE + str(tup[3])
-					self.TimeCorListText.insert("end", """%s\n""" % addtext)
-				c+=1
+    def ListTimeCor(self, master):
+        """
+        provide a toplevel window listing time corrections in fixed headers
+        of traces for a given key
+        """
+        if not self.TimeShiftName.get():
+            self.addTextInfoBar("No Sta:Loc:Net selected", 'orange')
+            return
+        tracekey=self.TimeShiftName.get()
+
+        try:
+            self.tl_State = self.TimeCorList_tl.winfo_exists()
+        except Exception as e:
+            self.tl_State = 0
+
+        if self.tl_State == 1:
+            self.TimeCorList_tl.tkraise()
+            self.TimeCorListText.clear()
+            #display info on selected block
+
+        else:
+            self.TimeCorList_tl = Toplevel(master)
+            self.TimeCorList_tl.title("Time Corrections")
+
+            self.ExitTimeCorList_b = Button(self.TimeCorList_tl,
+                                            activebackground = 'red',
+                                            cursor = 'pirate',
+                                            background = 'lightblue',
+                                            text="Dismiss",
+                                            command = Command(
+                                                self.killWindow,
+                                                self.TimeCorList_tl)
+                                            )
+            self.ExitTimeCorList_b.pack(side='bottom', fill='x', expand=1)
+
+            self.TimeCorListText = Pmw.ScrolledText(self.TimeCorList_tl,
+                                                    borderframe=1)
+            self.TimeCorListText.pack(side='bottom', fill='both', expand=1)
+
+        self.TimeCorListText.tag_config("odd", background="lightblue")
+        self.TimeCorListText.tag_config("yellow", background="yellow")
+        self.TimeCorListText.tag_config("orange", background="orange")
+
+        TimeDict=self.GetTimeCor()
+        self.TimeCorListText.clear()
+        c=0
+        addtext="\t******************************************"
+        self.TimeCorListText.insert("end", """%s\n""" % addtext, "yellow")
+        addtext="\t* Time Corrections Found in File Headers *"
+        self.TimeCorListText.insert("end", """%s\n""" % addtext, "yellow")
+        addtext="\t******************************************"
+        self.TimeCorListText.insert("end", """%s\n""" % addtext, "yellow")
+        tracelist = sorted(list(TimeDict.keys()))
+        for key in tracelist:
+
+            if c :
+                self.TimeCorListText.insert("end", """%s\n""" % key, "odd")
+                addtext = 4*SPACE + "Block Start Time" + 6*SPACE + "Cor(s)" \
+                    + 8*SPACE + "Status" + 14*SPACE + "Timing Questionable"
+                self.TimeCorListText.insert(
+                    "end", """%s\n""" % addtext, "odd")
+                for tup in TimeDict[key]:
+                    addtext = 4*SPACE + str(tup[0])
+                    splen = 26 - len(addtext)
+                    addtext = addtext + splen*SPACE + str(tup[1])
+                    splen = 40 - len(addtext)
+                    addtext = addtext + splen*SPACE + str(tup[2])
+                    splen = 60 - len(addtext)
+                    addtext = addtext + splen*SPACE + str(tup[3])
+                    self.TimeCorListText.insert(
+                        "end", """%s\n""" % addtext, "odd")
+                c = 0
+            else :
+                self.TimeCorListText.insert("end", """%s\n""" % key)
+                addtext = 4*SPACE + "Block Start Time" + 6*SPACE + "Cor(s)" \
+                    + 8*SPACE + "Status" + 14*SPACE + "Timing Questionable"
+                self.TimeCorListText.insert("end", """%s\n""" % addtext)
+                for tup in TimeDict[key]:
+                    addtext = 4*SPACE + str(tup[0])
+                    splen = 26 - len(addtext)
+                    addtext=addtext + splen*SPACE + str(tup[1])
+                    splen = 40 - len(addtext)
+                    addtext=addtext + splen*SPACE + str(tup[2])
+                    splen = 60 - len(addtext)
+                    addtext=addtext + splen*SPACE + str(tup[3])
+                    self.TimeCorListText.insert("end", """%s\n""" % addtext)
+                c += 1
 
 #########################################################
-	def GetTimeCor(self):
-		"""
-		Get time corrections from trace headers
-		"""
-		#local variables
-		stringjoin=string.join
-
-		FileCorDict={}
-		timeid = self.TimeShiftName.get()
-		(keystat,keyloc,keynet)=string.split(timeid, ":")
-		cnt=0
-		for key in self.TraceDict.keys():
-			(stat,chan,loc,net,sps)=string.split(key, ":")
-			if keystat == stat and keynet == net and \
-			   (keyloc == loc or keyloc == "*"):
-				for infile in self.TraceDict[key]:
-					if mod(cnt, 10):
-						pass
-					else:
-#						self.TimeCorListText.insert("end", """%s\n""" % timeid)
-						textstr="Key: " + timeid + " Examining Trace: "
-						self.wait(textstr, cnt)
-					cnt+=1
-
-# at this point all files in TraceDict should be mseed files, so not testing here
-					msfile = Mseed(infile)
-					fixedhdr=msfile.fixedhdr #local var
-
-					filesize=msfile.filesize
-					blksize=msfile.blksize
-					(numblocks, odd_size)=divmod(filesize, blksize)
-
-					n=0
-					while n < numblocks:
-						hdrs=msfile.fixedhdr(n*blksize)
-						(Year, Day, Hour, Min, Sec, junk, Micro)=hdrs[1]
-						Day=self.AddZero(Day,3)
-						Hour=self.AddZero(Hour,2)
-						Min=self.AddZero(Min,2)
-						Sec=self.AddZero(Sec,2)
-						hdtime=stringjoin(map(str,(Year, Day, Hour, Min, Sec)), ":")
-						(act, io, DQual, numblk, timcorr, bdata, bblock)=hdrs[3]
-						# has time correction been applied
-						if int(act[6]):
-							corr="applied"
-						else:
-							corr="not applied"
-						# is timing questionable flag set
-						if hdrs[3][2][0] == "1":
-							timequest = "set"
-						else:
-							timequest = "unset"
-
-						timcorr=float(timcorr)/10000.
-						try:
-							FileCorDict[infile].append((hdtime, timcorr, corr, timequest))
-						except KeyError:
-							FileCorDict[infile]=[]
-							FileCorDict[infile].append((hdtime, timcorr, corr, timequest))
-
-						n+=1
-					msfile.close()
-			else:
-				continue
-		return FileCorDict
+    def GetTimeCor(self):
+        """
+        Get time corrections from trace headers
+        """
+        #local variables
+
+        FileCorDict = {}
+        timeid = self.TimeShiftName.get()
+        (keystat,keyloc,keynet) = timeid.split(":")
+        cnt = 0
+        for key in self.TraceDict:
+            (stat,chan,loc,net,sps) = key.split(":")
+            if keystat == stat and keynet == net and \
+               (keyloc == loc or keyloc == "*"):
+                for infile in self.TraceDict[key]:
+                    if mod(cnt, 10):
+                        pass
+                    else:
+                        #self.TimeCorListText.insert(
+                        # "end", """%s\n""" % timeid)
+                        textstr="Key: " + timeid + " Examining Trace: "
+                        self.wait(textstr, cnt)
+                    cnt+=1
+
+                    # at this point all files in TraceDict should be mseed
+                    # files, so not testing here
+                    msfile = Mseed(infile)
+                    fixedhdr = msfile.fixedhdr #local var
+
+                    filesize = msfile.filesize
+                    blksize = msfile.blksize
+                    (numblocks, odd_size) = divmod(filesize, blksize)
+
+                    n = 0
+                    while n < numblocks:
+                        hdrs = msfile.fixedhdr(n*blksize)
+                        (Year, Day, Hour, Min, Sec, junk, Micro) = hdrs[1]
+                        Day = self.AddZero(Day,3)
+                        Hour = self.AddZero(Hour,2)
+                        Min = self.AddZero(Min,2)
+                        Sec = self.AddZero(Sec,2)
+                        hdtime = ":".join(map(str,(
+                            Year, Day, Hour, Min, Sec)))
+
+                        (act, io, DQual, numblk, timcorr, bdata, bblock) = \
+                            hdrs[3]
+                        # has time correction been applied
+                        if int(act[6]):
+                            corr = "applied"
+                        else:
+                            corr="not applied"
+                        # is timing questionable flag set
+                        if hdrs[3][2][0] == "1":
+                            timequest = "set"
+                        else:
+                            timequest = "unset"
+
+                        timcorr=float(timcorr)/10000.
+                        try:
+                            FileCorDict[infile].append((
+                                hdtime, timcorr, corr, timequest))
+                        except KeyError:
+                            FileCorDict[infile]=[]
+                            FileCorDict[infile].append((
+                                hdtime, timcorr, corr, timequest))
+
+                        n+=1
+                    msfile.close()
+            else:
+                continue
+        return FileCorDict
 
 #########################################################
-	def AddZero(self, var, num):
-		"""
-		pad header values to specified length with blank space
-		right justified
-		"""
-		var=str(var)
-		varlength=len(var)
-		if varlength == num:
-			return var
-		elif varlength < num:
-			pad=num-varlength
-			newvar= "0"*pad + var
-			return newvar
-
-
+    def AddZero(self, var, num):
+        """
+        pad header values to specified length with blank space
+        right justified
+        """
+        var = str(var)
+        varlength = len(var)
+        if varlength == num:
+            return var
+        elif varlength < num:
+            pad = num-varlength
+            newvar = "0"*pad + var
+            return newvar
 
 #########################################################
-	def DumpUpdateDicts(self, type=""):
-		"""
-		dump UpdateHdrDict to Log notebook
-		"""
-		#make sure any current window edits get added
-		if self.StationName.get():
-			self.UpdateHdr(self.StationName.get())
-#		self.TimeDictSet()
-
-		if not self.UpdateHdrDict and not self.UpdateTimeDict:
-			err="No updates to dump."
-			self.addTextInfoBar(err, 'red')
-			return
-
-		if type == "dump" or type == "load" or type == "mod":
-			applied = "applied"
-			not_applied = "not applied"
-		else:
-			applied = "saved"
-			not_applied = "saved"
-
-		#set color of entry based on whether applied or not
-		if self.UpdateHdrDict:
-			if type == "dump":
-				self.WriteLog("\n<Dump Update Dictionary>","Header","blue")
-			inlist = self.UpdateHdrDict.keys()
-			inlist.sort()
-	#		for key in self.UpdateHdrDict.keys():
-			for key in inlist:
-				self.WriteLog(key,"Header","black")
-				for subkey in self.UpdateHdrDict[key].keys():
-					value = "\t" + subkey + SPACE + self.UpdateHdrDict[key][subkey]
-					addsp = 25 - len(value)
-					if self.SetHdrDict.has_key(key):
-						if self.SetHdrDict[key].has_key(subkey):
-							value = value + SPACE*addsp + applied
-							tset = 'black'
-						else:
-							value = value + SPACE*addsp + not_applied
-							tset = 'red'
-					else:
-						value = value + SPACE*addsp + not_applied
-						tset = 'red'
-			#insert info on Log notebook
-					self.WriteLog(value,"Header",tset)
-			if type == "dump":
-				self.WriteLog("<end>","Header","blue")
-
-		if self.UpdateTimeDict:
-			if type == "dump":
-				self.WriteLog("\n<Dump Update Dictionary>","Time","blue")
-			inlist = self.UpdateTimeDict.keys()
-			inlist.sort()
-			for key in inlist:
-				self.WriteLog(key,"Time","black")
-				for var in self.ShiftVars:
-					if self.UpdateTimeDict[key].has_key(var[0]):
-						addsp = 15 - len(var[0])
-						value = "\t" + var[0] + SPACE*addsp + str(self.UpdateTimeDict[key][var[0]])
-						addsp = 35 - len(value)
-						if self.SetTimeDict.has_key(key):
-							if self.SetTimeDict[key].has_key(var[0]):
-								value = value + SPACE*addsp + applied
-								tset = 'black'
-							else:
-								value = value + SPACE*addsp + not_applied
-								tset = 'red'
-						else:
-							value = value + SPACE*addsp + not_applied
-							tset = 'red'
-				#insert info on Log notebook
-						self.WriteLog(value,"Time",tset)
-			if type == "dump":
-				self.WriteLog("<end>","Time","blue")
+    def DumpUpdateDicts(self, type=""):
+        """
+        dump UpdateHdrDict to Log notebook
+        """
+        #make sure any current window edits get added
+        if self.StationName.get():
+            self.UpdateHdr(self.StationName.get())
+#                self.TimeDictSet()
+
+        if not self.UpdateHdrDict and not self.UpdateTimeDict:
+            err = "No updates to dump."
+            self.addTextInfoBar(err, 'red')
+            return
+
+        if type == "dump" or type == "load" or type == "mod":
+            applied = "applied"
+            not_applied = "not applied"
+        else:
+            applied = "saved"
+            not_applied = "saved"
+
+        #set color of entry based on whether applied or not
+        if self.UpdateHdrDict:
+            if type == "dump":
+                self.WriteLog("\n<Dump Update Dictionary>","Header","blue")
+            inlist = sorted(list(self.UpdateHdrDict.keys()))
+ 
+            for key in inlist:
+                self.WriteLog(key,"Header","black")
+                for subkey in self.UpdateHdrDict[key]:
+                    value = "\t" + subkey + SPACE + \
+                        self.UpdateHdrDict[key][subkey]
+                    addsp = 25 - len(value)
+                    if key in self.SetHdrDict:
+                        if subkey in self.SetHdrDict[key]:
+                            value = value + SPACE*addsp + applied
+                            tset = 'black'
+                        else:
+                            value = value + SPACE*addsp + not_applied
+                            tset = 'red'
+                    else:
+                        value = value + SPACE*addsp + not_applied
+                        tset = 'red'
+            #insert info on Log notebook
+                    self.WriteLog(value,"Header",tset)
+            if type == "dump":
+                self.WriteLog("<end>","Header","blue")
+
+        if self.UpdateTimeDict:
+            if type == "dump":
+                self.WriteLog("\n<Dump Update Dictionary>","Time","blue")
+            inlist = sorted(list(self.UpdateTimeDict.keys()))
+            for key in inlist:
+                self.WriteLog(key,"Time","black")
+                for var in self.ShiftVars:
+                    if var[0] in self.UpdateTimeDict[key]:
+                        addsp = 15 - len(var[0])
+                        value = "\t" + var[0] + SPACE*addsp + \
+                            str(self.UpdateTimeDict[key][var[0]])
+                        addsp = 35 - len(value)
+                        if key in self.SetTimeDict:
+                            if var[0] in self.SetTimeDict[key]:
+                                value = value + SPACE*addsp + applied
+                                tset = 'black'
+                            else:
+                                value = value + SPACE*addsp + not_applied
+                                tset = 'red'
+                        else:
+                            value = value + SPACE*addsp + not_applied
+                            tset = 'red'
+                #insert info on Log notebook
+                        self.WriteLog(value,"Time",tset)
+            if type == "dump":
+                self.WriteLog("<end>","Time","blue")
 
 ##################################################################
-	def Exit(self):
-		"""
-		a no questions asked exit
-		"""
-		sys.exit(0)
+    def Exit(self):
+        """
+        a no questions asked exit
+        """
+        sys.exit(0)
 
 ##################################################################
-	def ExitCheck(self):
-		"""
-		before exitting test to see if any UpdateHdrDict values
-		have not yet been applied and allow user to apply before
-		exiting
-		"""
-		#need to deal with case when neither of below are true
-		self.UpdateHdr()
-		for var in self.UpdateHdrDict.keys():
-			self.addTextInfoBar(" " + var + "...", 'orange')
-			if not self.SetHdrDict.has_key(var):
-				self.ExitWidget(self.root)
-				return
-			else:
-				for subkey in self.UpdateHdrDict[var].keys():
-					if not self.SetHdrDict[var].has_key(subkey):
-						self.ExitWidget(self.root)
-						return
-		sys.exit(0)
+    def ExitCheck(self):
+        """
+        before exitting test to see if any UpdateHdrDict values
+        have not yet been applied and allow user to apply before
+        exiting
+        """
+        #need to deal with case when neither of below are true
+        self.UpdateHdr()
+        for var in self.UpdateHdrDict:
+            self.addTextInfoBar(" " + var + "...", 'orange')
+            if var not in self.SetHdrDict:
+                self.ExitWidget(self.root)
+                return
+            else:
+                for subkey in self.UpdateHdrDict[var]:
+                    if subkey not in self.SetHdrDict[var]:
+                        self.ExitWidget(self.root)
+                        return
+        sys.exit(0)
 
 ##################################################################
-	def ExitWidget(self,master):
-		"""
-		Allow user to apply UpdateHdrDict entries that have not
-		been applied
-		"""
+    def ExitWidget(self,master):
+        """
+        Allow user to apply UpdateHdrDict entries that have not
+        been applied
+        """
 # first see if we got here from ExitCheck. If so kill window
-		try:
-			self.tl_State = self.Check_tl.winfo_exists()
-			if self.tl_State :
-				self.killWindow(self.Check_tl)
-		except:
-			pass
+        try:
+            self.tl_State = self.Check_tl.winfo_exists()
+            if self.tl_State :
+                self.killWindow(self.Check_tl)
+        except Exception as e:
+            pass
 
 # Check to see if this window is lingering around. If so raise,
 # else create
-		try:
-			self.tl_State = self.Exit_tl.winfo_exists()
-		except:
-			self.tl_State = 0
-
-		if self.tl_State == 1:
-			self.addTextInfoBar("Exit Already Open", 'orange')
-			self.Exit_tl.tkraise()
-		else:
-			self.Exit_tl = Toplevel(master)
-			self.Exit_tl.title("Exit")
-
-			box_length = 25
-
-			self.Exit_b = Button(self.Exit_tl,
-					     text="Exit",
-					     relief = "ridge",
-					     cursor='pirate',
-					     activebackground='red',
-					     command= Command(self.Exit)
-					     )
-			self.Exit_b.pack(side='bottom', fill='x')
-
-			self.Return_b = Button(self.Exit_tl,
-					       text="Cancel",
-					       relief = "ridge",
-					       cursor='pirate',
-					       activebackground='orange',
-					       command= Command(self.killWindow, self.Exit_tl)
-					       )
-			self.Return_b.pack(side='bottom', fill='x')
-
-			self.ExitEntry_fm = Frame(self.Exit_tl,
-						  relief = 'groove',
-						  borderwidth=2
-						  )
-			self.ExitEntry_fm.pack(side='left',
-					       fill='x',
-					       pady=5
-					       )
-
-			Label(self.ExitEntry_fm,
-			      text="WARNING:\nNot All Entries Have Been Applied.",
-			      background='orange'
-			      ).pack(side='left', anchor='w')
+        try:
+            self.tl_State = self.Exit_tl.winfo_exists()
+        except Exception as e:
+            self.tl_State = 0
+
+        if self.tl_State == 1:
+            self.addTextInfoBar("Exit Already Open", 'orange')
+            self.Exit_tl.tkraise()
+        else:
+            self.Exit_tl = Toplevel(master)
+            self.Exit_tl.title("Exit")
+
+            box_length = 25
+
+            self.Exit_b = Button(self.Exit_tl,
+                                 text="Exit",
+                                 relief = "ridge",
+                                 cursor='pirate',
+                                 activebackground='red',
+                                 command= Command(self.Exit)
+                                 )
+            self.Exit_b.pack(side='bottom', fill='x')
+
+            self.Return_b = Button(self.Exit_tl,
+                                   text="Cancel",
+                                   relief = "ridge",
+                                   cursor='pirate',
+                                   activebackground='orange',
+                                   command= Command(
+                                       self.killWindow, self.Exit_tl)
+                                   )
+            self.Return_b.pack(side='bottom', fill='x')
+
+            self.ExitEntry_fm = Frame(self.Exit_tl,
+                                      relief = 'groove',
+                                      borderwidth=2
+                                      )
+            self.ExitEntry_fm.pack(side='left',
+                                   fill='x',
+                                   pady=5
+                                   )
+
+            Label(self.ExitEntry_fm,
+                  text="WARNING:\nNot All Entries Have Been Applied.",
+                  background='orange'
+                  ).pack(side='left', anchor='w')
 
 #########################################
-	def killWindow(self, widget):
-		"""
-		Destroy Widget and Set InfoBar to Default
-		"""
-		widget.destroy()
-		self.addTextInfoBar()
+    def killWindow(self, widget):
+        """
+        Destroy Widget and Set InfoBar to Default
+        """
+        widget.destroy()
+        self.addTextInfoBar()
 
 ##################################################################
-	def ClearAllTrace(self, all=0):
-		"""
-		clear values in UpdateHdrDict if the associated trace
-		headers have not already been applied.
-		"""
-		if all:
-			self.UpdateHdrDict={}
-			self.SetHdrDict={}
-		else:
-			try:
-				del self.UpdateHdrDict[self.StationName.get()]
-				del self.SetHdrDict[self.StationName.get()]
-			except:
-				pass
-
-		#clear entry boxes and check boxes
-		self.ClearAll(self.NewVars)
-		self.ClearAll(self.StatChanListVars)
-		self.ClearAll(self.SetHdrVars)
+    def ClearAllTrace(self, all=0):
+        """
+        clear values in UpdateHdrDict if the associated trace
+        headers have not already been applied.
+        """
+        if all:
+            self.UpdateHdrDict = {}
+            self.SetHdrDict = {}
+        else:
+            try:
+                del self.UpdateHdrDict[self.StationName.get()]
+                del self.SetHdrDict[self.StationName.get()]
+            except Exception as e:
+                pass
+
+        #clear entry boxes and check boxes
+        self.ClearAll(self.NewVars)
+        self.ClearAll(self.StatChanListVars)
+        self.ClearAll(self.SetHdrVars)
 
 ##################################################################
-	def ClearAllGlobal(self, varlist):
-		"""
-		clear GU values and set global match to wildcard
-		"""
-		self.addTextInfoBar()
-		for var in varlist :
-			self.setValue(var[1], "*")
-			self.setValue(var[3])
+    def ClearAllGlobal(self, varlist):
+        """
+        clear GU values and set global match to wildcard
+        """
+        self.addTextInfoBar()
+        for var in varlist :
+            self.setValue(var[1], "*")
+            self.setValue(var[3])
 
 #######################################
-	def ResetTimeShift(self):
-		"""
-		set vars to display input format
-		"""
+    def ResetTimeShift(self):
+        """
+        set vars to display input format
+        """
 
-#		self.addTextInfoBar()
-		self.TypeTimeCor.set(0)
-		self.TSShift.set(0.0)
-		self.TimeTagQuest.set("")
-		self.TimeShiftName.set("")
-		self.TSStartTime.set("yyyy:ddd:hh:mm:ss")
-		self.TSEndTime.set("yyyy:ddd:hh:mm:ss")
-		self.WildButton.configure(state="normal")
+#                self.addTextInfoBar()
+        self.TypeTimeCor.set(0)
+        self.TSShift.set(0.0)
+        self.TimeTagQuest.set("")
+        self.TimeShiftName.set("")
+        self.TSStartTime.set("yyyy:ddd:hh:mm:ss")
+        self.TSEndTime.set("yyyy:ddd:hh:mm:ss")
+        self.WildButton.configure(state="normal")
 
-		self.SetTime.set(0)
-		self.SetTQuest.set(0)
+        self.SetTime.set(0)
+        self.SetTQuest.set(0)
 
-		self.WildLoc.set(0)
+        self.WildLoc.set(0)
 
 ##################################################################
-	def ClearAll(self, varlist) :
-		"""
-		clear a variable list
-		"""
-		self.addTextInfoBar()
-		for var in varlist :
-			self.setValue(var[1])
+    def ClearAll(self, varlist) :
+        """
+        clear a variable list
+        """
+        self.addTextInfoBar()
+        for var in varlist :
+            self.setValue(var[1])
 
 ##################################################################
-	def ClearTxt(self, var) :
-		"""
-		clear text
-		"""
-		var.clear()
+    def ClearTxt(self, var) :
+        """
+        clear text
+        """
+        var.clear()
 
 #######################################
-	def setValue(self, var, value=''):
-		"""
-		Sets Value of var
-		"""
-		var.set(value)
+    def setValue(self, var, value=''):
+        """
+        Sets Value of var
+        """
+        var.set(value)
 
 #######################################
-	def addTextInfoBar(self, str='', bg='yellow'):
-		"""
-		Adds Text To InfoBar
-		"""
-		#only bell if error, e.g. color red
-		# don't ring bell if clearing text or progress info (e.g. color == yellow/lightblue)
-		if BATCHMODE:
-			if str:
-				if string.count(str,'Examining') or string.count(str, 'Modifying') \
-				   or string.count(str,'Correcting') or string.count(str,'Remaining'):
-					print "\r" + str,
-#					print ".",
-					sys.stdout.flush()
-				else:
-					print str
-		else:
-			if bg != "yellow" and bg != "lightblue":
-				self.root.bell()
-			self.InfoString_l.configure(background=bg, text=str)
+    def addTextInfoBar(self, str='', bg='yellow'):
+        """
+        Adds Text To InfoBar
+        """
+        # only bell if error, e.g. color red
+        # don't ring bell if clearing text or progress info
+        # (e.g. color == yellow/lightblue)
+        if BATCHMODE:
+            if str:
+                if str.count('Examining') or str.count('Modifying') \
+                   or str.count('Correcting') or str.count('Remaining'):
+                    print("\r" + str,)
+                    sys.stdout.flush()
+                else:
+                    print(str)
+        else:
+            if bg != "yellow" and bg != "lightblue":
+                self.root.bell()
+            self.InfoString_l.configure(background=bg, text=str)
 
 #######################################
-	def wait(self, words, cnt):
-		"""
-		puts words plus cnt to info bar
-		"""
-		txt = words + str(cnt)
-		if not BATCHMODE:
-			self.root.update()
-		self.addTextInfoBar(txt, 'lightblue')
+    def wait(self, words, cnt):
+        """
+        puts words plus cnt to info bar
+        """
+        txt = words + str(cnt)
+        if not BATCHMODE:
+            self.root.update()
+        self.addTextInfoBar(txt, 'lightblue')
 
 #######################################
-	def ButtonState(self, newstate="normal"):
-		"""
-		changes state of activity buttons
-		"""
-		#buttons that should be deactivated during activity
-		ButtonList = (
-			self.BuildTrcList_b,
-			self.ModHdr_b,
-			self.GlobalSet_b,
-			self.ApplyTime_b,
-			self.ToBig_b,
-			self.ToLittle_b,
-			self.UndoTimeCor_b
-		)
-		for item in ButtonList:
-			item.configure(state=newstate)
+    def ButtonState(self, newstate="normal"):
+        """
+        changes state of activity buttons
+        """
+        #buttons that should be deactivated during activity
+        ButtonList = (
+            self.BuildTrcList_b,
+            self.ModHdr_b,
+            self.GlobalSet_b,
+            self.ApplyTime_b,
+            self.ToBig_b,
+            self.ToLittle_b,
+            self.UndoTimeCor_b
+        )
+        for item in ButtonList:
+            item.configure(state=newstate)
 ##########################################
-	def getPath (self, var, clear=1) :
-		"""
-		Concatonate paths
-		"""
-		self.var=var
-		if clear:
-			self.var.set('')
-		newpath_dd = DirectoryDialog (self.root)
-		self.path = newpath_dd.go (dir_or_file = os.getcwd())
-		if self.path != None :
-			if self.var.get():
-				self.var.set(self.var.get() + ':')
-			if len(self.path) == 1 and self.path[0] == "/":
-				self.var.set(self.var.get() + self.path)
-			elif self.path[-1] == "/":
-				self.var.set(self.var.get() + self.path[:-1])
-			else:
-				self.var.set(self.var.get() + self.path)
+    def getPath (self, var, clear=1) :
+        """
+        Concatonate paths
+        """
+        self.var=var
+        if clear:
+            self.var.set('')
+        newpath_dd = DirectoryDialog (self.root)
+        self.path = newpath_dd.go (dir_or_file = os.getcwd())
+        if self.path != None :
+            if self.var.get():
+                self.var.set(self.var.get() + ':')
+            if len(self.path) == 1 and self.path[0] == "/":
+                self.var.set(self.var.get() + self.path)
+            elif self.path[-1] == "/":
+                self.var.set(self.var.get() + self.path[:-1])
+            else:
+                self.var.set(self.var.get() + self.path)
 
 #######################################
-	def CancelTL(self, runvar, title):
-		"""
-		creates a window for canceling trace modifications
-
-		"""
-		#disable all buttons that write to traces
-		self.ButtonState("disabled")
-
-		self.Cancel_tl = Toplevel(self.root)
-		self.Cancel_tl.title(title)
-		self.Cancel_b = Button(self.Cancel_tl,
-				       text="Cancel",
-				       cursor='pirate',
-				       relief = "ridge",
-				       activebackground='red',
-#			command= Command(self.setValue, runvar, 0)
+    def CancelTL(self, runvar, title):
+        """
+        creates a window for canceling trace modifications
+
+        """
+        #disable all buttons that write to traces
+        self.ButtonState("disabled")
+
+        self.Cancel_tl = Toplevel(self.root)
+        self.Cancel_tl.title(title)
+        self.Cancel_b = Button(self.Cancel_tl,
+                               text="Cancel",
+                               cursor='pirate',
+                               relief = "ridge",
+                               activebackground='red',
+#                        command= Command(self.setValue, runvar, 0)
 command= Command(self.KillCancelTL, runvar)
 )
-		self.Cancel_b.pack(side='bottom', fill='x')
-
-		self.Text_fm = Frame(self.Cancel_tl,
-				     relief = 'groove',
-				     borderwidth=2
-				     )
-		self.Text_fm.pack(side='top',
-				  fill='x',
-				  pady=5
-				  )
-
-		infotext = "   " + title + " Active. Please Wait   "
-		Label(self.Text_fm,
-		      text=infotext,
-		      background='yellow'
-		      ).pack(side='left', anchor='w')
+        self.Cancel_b.pack(side='bottom', fill='x')
+
+        self.Text_fm = Frame(self.Cancel_tl,
+                             relief = 'groove',
+                             borderwidth=2
+                             )
+        self.Text_fm.pack(side='top',
+                          fill='x',
+                          pady=5
+                          )
+
+        infotext = "   " + title + " Active. Please Wait   "
+        Label(self.Text_fm,
+              text=infotext,
+              background='yellow'
+              ).pack(side='left', anchor='w')
 #######################################
-	def KillCancelTL(self, runvar):
-		"""
-		kills cancel window and unsets runvar
-		"""
-		self.killWindow(self.Cancel_tl)
-		self.setValue(runvar, 0)
-		self.ButtonState()
+    def KillCancelTL(self, runvar):
+        """
+        kills cancel window and unsets runvar
+        """
+        self.killWindow(self.Cancel_tl)
+        self.setValue(runvar, 0)
+        self.ButtonState()
 
 #######################################
-	def WarnWidget(self, master, action):
-		"""
-		Toplevel to warn user if headers have been modified
-		"""
-		self.CancelWarn.set(0)
-		try:
-			self.tl_State = self.WarnWidget_tl.winfo_exists()
-		except:
-			self.tl_State = 0
-
-		if self.tl_State == 1:
-			self.WarnWidget_tl.tkraise()
-		else:
-			# setup output file name
-			title = "Warning"
-
-			self.WarnWidget_tl = Toplevel(master)
-			self.WarnWidget_tl.title(title)
-			self.WarnWidgetCancel_b = Button(self.WarnWidget_tl,
-							 text="Cancel",
-							 cursor='pirate',
-							 relief = "ridge",
-							 background='red',
-							 activebackgroun='red',
-							 command= Command(self.CancelWarnTL)
-							 )
-			self.WarnWidgetCancel_b.pack(side='bottom', fill='x')
-
-			if action == "headers":
-				self.WarnWidgetDismiss_b = Button(self.WarnWidget_tl,
-								  text="Apply without rebuild",
-								  cursor='pirate',
-								  relief = "ridge",
-								  activebackground='orange',
-								  command= Command(self.Ignore, action)
-								  )
-				self.WarnWidgetDismiss_b.pack(side='bottom', fill='x')
-
-				self.ReBuildTrcList_b = Button(self.WarnWidget_tl,
-							       activebackground = 'green',
-							       relief = "ridge",
-							       background='lightblue',
-							       text = "Rebuild db Now",
-							       command = Command(self.BuildTrcList)
-							       )
-				self.ReBuildTrcList_b.pack(side='bottom', fill='x')
-
-			elif action == "time":
-				self.WarnWidgetDismiss_b = Button(self.WarnWidget_tl,
-								  text="Apply All",
-								  cursor='pirate',
-								  relief = "ridge",
-								  activebackground='orange',
-								  command= Command(self.Ignore, action)
-								  )
-				self.WarnWidgetDismiss_b.pack(side='bottom', fill='x')
-
-				self.NewOnly_b = Button(self.WarnWidget_tl,
-							activebackground = 'green',
-							relief = "ridge",
-							background='lightblue',
-							text = "Apply Unapplied Only",
-							command = Command(self.NewOnlyTime)
-							)
-				self.NewOnly_b.pack(side='bottom', fill='x')
-
-			elif action == "undo":
-				self.WarnWidgetDismiss_b = Button(self.WarnWidget_tl,
-								  text="Ignore & Undo Corrections",
-								  cursor='pirate',
-								  relief = "ridge",
-								  activebackground='orange',
-								  command= Command(self.Ignore, action)
-								  )
-				self.WarnWidgetDismiss_b.pack(side='bottom', fill='x')
-
-			self.Text_fm = Frame(self.WarnWidget_tl,
-					     relief = 'groove',
-					     borderwidth=2
-					     )
-			self.Text_fm.pack(side='top',
-					  fill='x',
-					  pady=5
-					  )
-			if action == "undo":
-				infotext="This will only remove single and cumulative corrections." \
-					"\nReview \'List Time Corrections\' to better understand corrections" \
-					"\nalready applied to trace headers. Consider recalculating start"\
-					"\nand end times before continuing"
-			else:
-				infotext=self.AlteredText.get()
-				headerkeys=self.SetHdrDict.keys()
-				headerkeys= "Headers Changed: " + string.join(map(str, headerkeys), ",\n") + "\n"
-				timekeys=self.SetTimeDict.keys()
-				timekeys= "Blockette Times Changed: " + string.join(map(str, timekeys), ",\n")
-
-				infotext = infotext + headerkeys + timekeys
-
-			Label(self.Text_fm,
-			      text=infotext,
-			      background='orange'
-			      ).pack(side='left', anchor='w')
+    def WarnWidget(self, master, action):
+        """
+        Toplevel to warn user if headers have been modified
+        """
+        self.CancelWarn.set(0)
+        try:
+            self.tl_State = self.WarnWidget_tl.winfo_exists()
+        except Exception as e:
+            self.tl_State = 0
+
+        if self.tl_State == 1:
+            self.WarnWidget_tl.tkraise()
+        else:
+            # setup output file name
+            title = "Warning"
+
+            self.WarnWidget_tl = Toplevel(master)
+            self.WarnWidget_tl.title(title)
+            self.WarnWidgetCancel_b = Button(self.WarnWidget_tl,
+                                             text="Cancel",
+                                             cursor='pirate',
+                                             relief = "ridge",
+                                             background='red',
+                                             activebackgroun='red',
+                                             command=Command(
+                                                 self.CancelWarnTL)
+                                             )
+            self.WarnWidgetCancel_b.pack(side='bottom', fill='x')
+
+            if action == "headers":
+                self.WarnWidgetDismiss_b = Button(self.WarnWidget_tl,
+                                                  text="Apply without rebuild",
+                                                  cursor='pirate',
+                                                  relief="ridge",
+                                                  activebackground='orange',
+                                                  command=Command(
+                                                      self.Ignore, action)
+                                                  )
+                self.WarnWidgetDismiss_b.pack(side='bottom', fill='x')
+
+                self.ReBuildTrcList_b = Button(self.WarnWidget_tl,
+                                               activebackground = 'green',
+                                               relief = "ridge",
+                                               background='lightblue',
+                                               text="Rebuild db Now",
+                                               command=Command(
+                                                   self.BuildTrcList)
+                                               )
+                self.ReBuildTrcList_b.pack(side='bottom', fill='x')
+
+            elif action == "time":
+                self.WarnWidgetDismiss_b = Button(self.WarnWidget_tl,
+                                                  text="Apply All",
+                                                  cursor='pirate',
+                                                  relief="ridge",
+                                                  activebackground='orange',
+                                                  command=Command(
+                                                      self.Ignore, action)
+                                                  )
+                self.WarnWidgetDismiss_b.pack(side='bottom', fill='x')
+
+                self.NewOnly_b = Button(self.WarnWidget_tl,
+                                        activebackground = 'green',
+                                        relief = "ridge",
+                                        background='lightblue',
+                                        text = "Apply Unapplied Only",
+                                        command = Command(self.NewOnlyTime)
+                                        )
+                self.NewOnly_b.pack(side='bottom', fill='x')
+
+            elif action == "undo":
+                self.WarnWidgetDismiss_b = Button(self.WarnWidget_tl,
+                                                  text="Ignore & Undo Corrections",
+                                                  cursor='pirate',
+                                                  relief="ridge",
+                                                  activebackground='orange',
+                                                  command= Command(
+                                                      self.Ignore, action)
+                                                  )
+                self.WarnWidgetDismiss_b.pack(side='bottom', fill='x')
+
+            self.Text_fm = Frame(self.WarnWidget_tl,
+                                 relief = 'groove',
+                                 borderwidth=2
+                                 )
+            self.Text_fm.pack(side='top',
+                              fill='x',
+                              pady=5
+                              )
+            if action == "undo":
+                infotext="This will only remove single and cumulative "\
+                    "corrections.\nReview 'List Time Corrections\' to "\
+                    "better understand corrections\nalready applied to "\
+                    "trace headers. Consider recalculating start"\
+                    "\nand end times before continuing"
+            else:
+                infotext = self.AlteredText.get()
+                headerkeys = list(self.SetHdrDict.keys())
+                headerkeys = "Headers Changed: " + \
+                    ",\n".join(map(str, headerkeys)) + "\n"
+                timekeys = list(self.SetTimeDict.keys())
+                timekeys = "Blockette Times Changed: " + \
+                    ",\n".join(map(str, timekeys))
+
+                infotext = infotext + headerkeys + timekeys
+
+            Label(self.Text_fm,
+                  text=infotext,
+                  background='orange'
+                  ).pack(side='left', anchor='w')
 
 #######################################
-	def CancelWarnTL(self):
-		self.killWindow(self.WarnWidget_tl)
-		self.ActiveText.set("")
-		self.AlteredText.set("")
-		self.CancelWarn.set(1)
+    def CancelWarnTL(self):
+        self.killWindow(self.WarnWidget_tl)
+        self.ActiveText.set("")
+        self.AlteredText.set("")
+        self.CancelWarn.set(1)
 
 #######################################
-	def Ignore(self, action):
-		"""
-		here user has ignored recommendation to rebuild db before proceeding
-		"""
-
-		self.killWindow(self.WarnWidget_tl)
-		self.ActiveText.set("")
-		self.AlteredText.set("")
-		# let user know they may have problems
-		if action == "time":
-			text = "\n*****************************************"
-			self.WriteLog(text,"Time","red")
-			text = "* WARNING: Ignored advice to rebuild db *"
-			self.WriteLog(text,"Time","red")
-			text = "*****************************************"
-			self.WriteLog(text,"Time","red")
-			self.IgnoreWarn.set(1)
-		elif action == "headers":
-			text = "\n*****************************************"
-			self.WriteLog(text,"Header","red")
-			text = "* WARNING: Ignored advice to rebuild db *"
-			self.WriteLog(text,"Header","red")
-			text = "*****************************************"
-			self.WriteLog(text,"Header","red")
-			self.IgnoreWarn.set(1)
-		elif action == "undo":
-			self.IgnoreWarn.set(1)
+    def Ignore(self, action):
+        """
+        here user has ignored recommendation to rebuild db before proceeding
+        """
+
+        self.killWindow(self.WarnWidget_tl)
+        self.ActiveText.set("")
+        self.AlteredText.set("")
+        # let user know they may have problems
+        if action == "time":
+            text = "\n*****************************************"
+            self.WriteLog(text,"Time","red")
+            text = "* WARNING: Ignored advice to rebuild db *"
+            self.WriteLog(text,"Time","red")
+            text = "*****************************************"
+            self.WriteLog(text,"Time","red")
+            self.IgnoreWarn.set(1)
+        elif action == "headers":
+            text = "\n*****************************************"
+            self.WriteLog(text,"Header","red")
+            text = "* WARNING: Ignored advice to rebuild db *"
+            self.WriteLog(text,"Header","red")
+            text = "*****************************************"
+            self.WriteLog(text,"Header","red")
+            self.IgnoreWarn.set(1)
+        elif action == "undo":
+            self.IgnoreWarn.set(1)
 
 #######################################
-	def saveWidget(self, master, type=""):
-		"""
-		Toplevel to save update dictionary or log text to file
-		"""
-
-		try:
-			self.tl_State = self.saveWidget_tl.winfo_exists()
-		except:
-			self.tl_State = 0
-
-		if self.tl_State == 1:
-			self.addTextInfoBar("Save As Already Open", 'orange')
-			self.saveWidget_tl.tkraise()
-		else:
-			# setup output file name
-			(year, month, day, hour, minute, second, weekday, yearday, daylight) = time.localtime(time.time())
-			now = string.join(map(str, (year, yearday, hour, minute)), ".")
-			if type == "templ":
-				self.Savefile.set("fixhdr_tmpl." + now)
-				title = "Save Template File As:"
-			elif type == "log":
-				if self.LogVar.get() == 0: self.Savefile.set("fixhdr_LogAll." + now)
-				if self.LogVar.get() == 1: self.Savefile.set("fixhdr_LogHeader." + now)
-				if self.LogVar.get() == 2: self.Savefile.set("fixhdr_LogTime." + now)
-				if self.LogVar.get() == 3: self.Savefile.set("fixhdr_LogEndian." + now)
-				if self.LogVar.get() == 4: textlist=self.Savefile.set("fixhdr_Summary." + now)
-				title = "Save Log File As:"
-
-			box_length = len(self.Savefile.get()) + 15
-			self.saveWidget_tl = Toplevel(master)
-			self.saveWidget_tl.title(title)
-			self.saveWidgetCancel_b = Button(self.saveWidget_tl,
-							 text="Cancel",
-							 cursor='pirate',
-							 relief = "ridge",
-							 activebackground='red',
-							 command= Command(self.killWindow, self.saveWidget_tl)
-							 )
-			self.saveWidgetCancel_b.pack(side='bottom', fill='x')
-
-			self.saveWidgetSave_b = Button(self.saveWidget_tl,
-						       text="Save",
-						       background='lightblue',
-						       relief = "ridge",
-						       activebackground='green',
-						       command = Command(self.writeFile, self.saveWidget_tl, self.Savefile, type)
-						       )
-			self.saveWidgetSave_b.pack(side='bottom', fill='x')
-
-			self.saveWidgetEntry_fm = Frame(self.saveWidget_tl,
-							relief = 'groove',
-							borderwidth=2
-							)
-			self.saveWidgetEntry_fm.pack(side='left',
-						     fill='x',
-						     pady=5
-						     )
-
-			self.saveWidgetEntry_e = Entry(self.saveWidgetEntry_fm,
-						       textvariable = self.Savefile,
-						       width = box_length
-						       )
-			self.saveWidgetEntry_e.pack(side='left', anchor='w', fill='x', expand=1)
+    def saveWidget(self, master, type=""):
+        """
+        Toplevel to save update dictionary or log text to file
+        """
+
+        try:
+            self.tl_State = self.saveWidget_tl.winfo_exists()
+        except Exception as e:
+            self.tl_State = 0
+
+        if self.tl_State == 1:
+            self.addTextInfoBar("Save As Already Open", 'orange')
+            self.saveWidget_tl.tkraise()
+        else:
+            # setup output file name
+            (year, month, day, hour, minute, second, weekday, yearday,
+             daylight) = time.localtime(time.time())
+            now = ".".join(map(str, (year, yearday, hour, minute)), )
+            if type == "templ":
+                self.Savefile.set("fixhdr_tmpl." + now)
+                title = "Save Template File As:"
+            elif type == "log":
+                if self.LogVar.get() == 0:
+                    self.Savefile.set("fixhdr_LogAll." + now)
+                if self.LogVar.get() == 1:
+                    self.Savefile.set("fixhdr_LogHeader." + now)
+                if self.LogVar.get() == 2:
+                    self.Savefile.set("fixhdr_LogTime." + now)
+                if self.LogVar.get() == 3:
+                    self.Savefile.set("fixhdr_LogEndian." + now)
+                if self.LogVar.get() == 4:
+                    textlist=self.Savefile.set("fixhdr_Summary." + now)
+                title = "Save Log File As:"
+
+            box_length = len(self.Savefile.get()) + 15
+            self.saveWidget_tl = Toplevel(master)
+            self.saveWidget_tl.title(title)
+            self.saveWidgetCancel_b = Button(self.saveWidget_tl,
+                                             text="Cancel",
+                                             cursor='pirate',
+                                             relief = "ridge",
+                                             activebackground='red',
+                                             command= Command(
+                                                 self.killWindow,
+                                                 self.saveWidget_tl)
+                                             )
+            self.saveWidgetCancel_b.pack(side='bottom', fill='x')
+
+            self.saveWidgetSave_b = Button(self.saveWidget_tl,
+                                           text="Save",
+                                           background='lightblue',
+                                           relief = "ridge",
+                                           activebackground='green',
+                                           command = Command(
+                                               self.writeFile,
+                                               self.saveWidget_tl,
+                                               self.Savefile, type)
+                                           )
+            self.saveWidgetSave_b.pack(side='bottom', fill='x')
+
+            self.saveWidgetEntry_fm = Frame(self.saveWidget_tl,
+                                            relief = 'groove',
+                                            borderwidth=2
+                                            )
+            self.saveWidgetEntry_fm.pack(side='left',
+                                         fill='x',
+                                         pady=5
+                                         )
+
+            self.saveWidgetEntry_e = Entry(self.saveWidgetEntry_fm,
+                                           textvariable = self.Savefile,
+                                           width = box_length
+                                           )
+            self.saveWidgetEntry_e.pack(
+                side='left', anchor='w', fill='x', expand=1)
 
 ##########################################
-	def writeFile(self, master, file, type=""):
-		"""
-		Write File to disk
-		"""
-
-		if os.path.isfile(file.get()):
-			self.Continue_dl = Pmw.MessageDialog(master,
-							     title = "WARNING",
-							     defaultbutton = 1,
-							     buttons = ('Overwrite', 'Cancel'),
-							     message_text = 'The File exists!'
-							     )
-			self.Result = self.Continue_dl.activate()
-		else:
-			self.Result = "Overwrite"
-
-		if ( self.Result == "Cancel"):
-			self.addTextInfoBar()
-		elif ( self.Result == "Overwrite"):
-			master.destroy()
-
-		if type == "templ":
-			try:
-				#make sure current entries are included
-				self.UpdateHdr(self.StationName.get())
-				if self.UpdateHdrDict or self.UpdateTimeDict:
-					outfile=open(file.get(), "w")
-					if self.UpdateHdrDict:
-						outfile.write("%s\n" % "# Header Changes")
-						outfile.write("%s\n" % "# stat:chan:loc:net:sps   stat:chan:loc:net")
-						outfile.write("%s\n" % "hdrlist{")
-						inlist = self.UpdateHdrDict.keys()
-						inlist.sort()
-						for key in inlist:
-							if self.UpdateHdrDict[key].has_key("Station_Name"):
-								newkey=self.UpdateHdrDict[key]["Station_Name"]
-							else:
-								newkey=""
-							if self.UpdateHdrDict[key].has_key("Channel"):
-								newkey=newkey + ":" + self.UpdateHdrDict[key]["Channel"]
-							else:
-								newkey=newkey + ":"
-							if self.UpdateHdrDict[key].has_key("Location_Code"):
-								newkey=newkey + ":" + self.UpdateHdrDict[key]["Location_Code"]
-							else:
-								newkey=newkey + ":"
-							if self.UpdateHdrDict[key].has_key("Network_Code"):
-								newkey=newkey + ":" + self.UpdateHdrDict[key]["Network_Code"]
-							else:
-								newkey=newkey + ":"
-							outfile.write("%s\t%s\n" % (key, newkey))
-						outfile.write("%s\n" % "}")
-					if self.UpdateTimeDict.keys():
-						outfile.write("%s\n" % "# Timing Corrections")
-						outfile.write("%s\n" % "# sta:loc:net Start_Time        End_Time          Time_Shift_sec Time_Tag_Quest  Corr_Type")
-						outfile.write("%s\n" % "# sta:loc:net yyyy:ddd:hh:mm:ss yyyy:ddd:hh:mm:ss float/NA       set/unset/NA    add/replace/NA")
-
-						outfile.write("%s\n" % "timelist{")
-						inlist = self.UpdateTimeDict.keys()
-						inlist.sort()
-						for key in inlist:
-							timekey=key
-							for var in self.ShiftVars:
-								if self.UpdateTimeDict[key].has_key(var[0]):
-									if var[0] == "Corr_Type":
-										if self.UpdateTimeDict[key][var[0]]:
-											timekey = timekey + "\treplace"
-										else:
-											timekey = timekey + "\tadd"
-									elif not self.UpdateTimeDict[key][var[0]]:
-										timekey = timekey + "\tNA"
-									else:
-										timekey = timekey + "\t" + str(self.UpdateTimeDict[key][var[0]])
-								else:
-									timekey = timekey + "\tNA"
-							outfile.write("%s\n" % (timekey))
-						outfile.write("%s\n" % "}")
-					outfile.close()
-
-					# Write some log info
-					if self.UpdateHdrDict:
-						self.WriteLog("\n<Save Template>","Header","blue")
-						self.WriteLog("File: %s" % file.get(),"Header","dkgreen")
-					if self.UpdateTimeDict:
-						self.WriteLog("\n<Save Template>","Time","blue")
-						self.WriteLog("File: %s" % file.get(),"Time","dkgreen")
-					if self.UpdateHdrDict or self.UpdateTimeDict:
-						self.DumpUpdateDicts()
-					if self.UpdateHdrDict: self.WriteLog("<end>","Header","blue")
-					if self.UpdateTimeDict: self.WriteLog("<end>","Time","blue")
-
-					self.addTextInfoBar("Wrote Template File: %s " % file.get(), 'green')
-				else:
-					err = "Dictionaries are empty. Nothing to save!"
-					self.addTextInfoBar(err, 'orange')
-			except IOError, e:
-				err = "Can't Create %s" % file.get(), e
-				self.addTextInfoBar(err, 'red')
-		elif type == "log":
-			if len(self.LogText.get()) == 1:
-				err = "LogText is empty, nothing to save!"
-				self.addTextInfoBar(err, 'orange')
-			else:
-				try:
-					self.LogText.exportfile(file.get())
-					self.WriteLog("\n<Save Log>","All","blue")
-					self.WriteLog("File: %s" % file.get(),"All","dkgreen")
-					self.WriteLog("<end>","All","blue")
-					self.addTextInfoBar("Wrote Log File: %s " % file.get(), 'green')
-				except IOError, e:
-					err = "Can't Create %s" % file.get(), e
-					self.addTextInfoBar(err, 'red')
-		self.DisplayLog()
+    def writeFile(self, master, file, type=""):
+        """
+        Write File to disk
+        """
+
+        if os.path.isfile(file.get()):
+            self.Continue_dl = Pmw.MessageDialog(
+                master,title="WARNING",defaultbutton=1,
+                buttons=('Overwrite', 'Cancel'),
+                message_text='The File exists!'
+            )
+            self.Result = self.Continue_dl.activate()
+        else:
+            self.Result = "Overwrite"
+
+        if ( self.Result == "Cancel"):
+            self.addTextInfoBar()
+        elif ( self.Result == "Overwrite"):
+            master.destroy()
+
+        if type == "templ":
+            try:
+                #make sure current entries are included
+                self.UpdateHdr(self.StationName.get())
+                if self.UpdateHdrDict or self.UpdateTimeDict:
+                    outfile = open(file.get(), "w")
+                    if self.UpdateHdrDict:
+                        outfile.write("%s\n" % "# Header Changes")
+                        outfile.write(
+                            "%s\n" %
+                            "# stat:chan:loc:net:sps   stat:chan:loc:net")
+                        outfile.write("%s\n" % "hdrlist{")
+                        inlist = sorted(list(self.UpdateHdrDict.keys()))
+
+                        for key in inlist:
+                            if "Station_Name" in self.UpdateHdrDict[key]:
+                                newkey = \
+                                    self.UpdateHdrDict[key]["Station_Name"]
+                            else:
+                                newkey = ""
+                            if "Channel" in self.UpdateHdrDict[key]:
+                                newkey = newkey + ":" + \
+                                    self.UpdateHdrDict[key]["Channel"]
+                            else:
+                                newkey = newkey + ":"
+                            if "Location_Code" in self.UpdateHdrDict[key]:
+                                newkey = newkey + ":" + \
+                                    self.UpdateHdrDict[key]["Location_Code"]
+                            else:
+                                newkey = newkey + ":"
+                            if "Network_Code" in self.UpdateHdrDict[key]:
+                                newkey = newkey + ":" + \
+                                    self.UpdateHdrDict[key]["Network_Code"]
+                            else:
+                                newkey = newkey + ":"
+                            outfile.write("%s\t%s\n" % (key, newkey))
+                        outfile.write("%s\n" % "}")
+                    if self.UpdateTimeDict:
+                        outfile.write("%s\n" % "# Timing Corrections")
+                        outfile.write(
+                            "%s\n" % "# sta:loc:net Start_Time        "
+                            "End_Time          Time_Shift_sec Time_Tag_Quest"
+                            "  Corr_Type")
+                        outfile.write(
+                            "%s\n" % "# sta:loc:net yyyy:ddd:hh:mm:ss "
+                            "yyyy:ddd:hh:mm:ss float/NA       "
+                            "set/unset/NA    add/replace/NA")
+
+                        outfile.write("%s\n" % "timelist{")
+                        inlist = sorted(list(self.UpdateTimeDict.keys()))
+                        for key in inlist:
+                            timekey=key
+                            for var in self.ShiftVars:
+                                if var[0] in self.UpdateTimeDict[key]:
+                                    if var[0] == "Corr_Type":
+                                        if self.UpdateTimeDict[key][var[0]]:
+                                            timekey = timekey + "\treplace"
+                                        else:
+                                            timekey = timekey + "\tadd"
+                                    elif not self.UpdateTimeDict[key][var[0]]:
+                                        timekey = timekey + "\tNA"
+                                    else:
+                                        timekey = timekey + "\t" + \
+                                            str(self.UpdateTimeDict[
+                                                key][var[0]])
+                                else:
+                                    timekey = timekey + "\tNA"
+                            outfile.write("%s\n" % (timekey))
+                        outfile.write("%s\n" % "}")
+                    outfile.close()
+
+                    # Write some log info
+                    if self.UpdateHdrDict:
+                        self.WriteLog("\n<Save Template>","Header","blue")
+                        self.WriteLog("File: %s" % file.get(),
+                                      "Header","dkgreen")
+                    if self.UpdateTimeDict:
+                        self.WriteLog("\n<Save Template>","Time","blue")
+                        self.WriteLog("File: %s" % file.get(),
+                                      "Time","dkgreen")
+                    if self.UpdateHdrDict or self.UpdateTimeDict:
+                        self.DumpUpdateDicts()
+                    if self.UpdateHdrDict:
+                        self.WriteLog("<end>","Header","blue")
+                    if self.UpdateTimeDict:
+                        self.WriteLog("<end>","Time","blue")
+
+                    self.addTextInfoBar("Wrote Template File: %s " %
+                                        file.get(), 'green')
+                else:
+                    err = "Dictionaries are empty. Nothing to save!"
+                    self.addTextInfoBar(err, 'orange')
+            except IOError as e:
+                err = "Can't Create %s" % file.get(), e
+                self.addTextInfoBar(err, 'red')
+        elif type == "log":
+            if len(self.LogText.get()) == 1:
+                err = "LogText is empty, nothing to save!"
+                self.addTextInfoBar(err, 'orange')
+            else:
+                try:
+                    self.LogText.exportfile(file.get())
+                    self.WriteLog("\n<Save Log>","All","blue")
+                    self.WriteLog("File: %s" % file.get(),"All","dkgreen")
+                    self.WriteLog("<end>","All","blue")
+                    self.addTextInfoBar("Wrote Log File: %s " % file.get(),
+                                        'green')
+                except IOError as e:
+                    err = "Can't Create %s" % file.get(), e
+                    self.addTextInfoBar(err, 'red')
+        self.DisplayLog()
 
 ##########################################
 
-	def LoadTemplate(self):
-		"""
-		Find a file and import into text window
-		"""
-# 		timelist=[]
-# 		hdrlist=[]
-		if self.BatchFile.get():
-			selection=self.BatchFile.get()
-		else:
-# 			if not self.DataDirList:
-# 				err = "You must build a Trace db before loading template"
-# 				self.addTextInfoBar(err, 'red')
-# 				return
-			selection = tkFileDialog.askopenfilename\
-				  (filetypes=[("All", "*")])
-		if selection:
-			try:
-				inputfile=open(selection,"r")
-				self.UpdateHdrDict={}
-				self.SetHdrDict={}
-				self.UpdateTimeDict={}
-				self.SetTimeDict={}
-				self.ClearAll(self.NewVars)
-				self.ClearAll(self.SetHdrVars)
-				self.ClearAll(self.ShiftVars)
-				while 1:
-					newline = inputfile.readline()
-					if not newline : break
-					if newline[0] == "#" or newline[:-1] == "": continue
-					if newline[0] == "}":
-						print  "ERROR in Template File Format"
-					if newline[:7] == "hdrlist" :
-						while 1:
-							newline = inputfile.readline()
-							if not newline : break
-							if newline[0] == "#" or newline[:-1] == "": continue
-							if newline[0] == "}": break
-							if len(string.split(newline[:-1])) != 2 :
-								self.UpdateTimeDict={}
-								break
-							try:
-								(key, newkey) = string.split(newline[:-1])
-							except:
-								print "ERROR in Template File Format"
-								break
-							if not self.UpdateHdrDict.has_key(key) :
-								self.UpdateHdrDict[key] = {}
-							(stat,chan,loc,net) = string.split(newkey, ":")
-							if stat:
-								stat=string.upper(stat)
-								self.UpdateHdrDict[key]["Station_Name"]=stat
-							if chan:
-								chan=string.upper(chan)
-								self.UpdateHdrDict[key]["Channel"]=chan
-							if loc:
-								loc=string.upper(loc)
-								self.UpdateHdrDict[key]["Location_Code"]=loc
-							if net:
-								net=string.upper(net)
-								self.UpdateHdrDict[key]["Network_Code"]=net
-					elif newline[:8] == "timelist" :
-						while 1:
-							newline = inputfile.readline()
-							if not newline : break
-							if newline[0] == "#" or newline[:-1] == "": continue
-							if newline[0] == "}": break
-							if len(string.split(newline[:-1])) != 6 :
-								self.UpdateTimeDict={}
-								break
-							(id, stime,etime,shift,quest,type) = string.split(newline[:-1])
-							if not self.UpdateTimeDict.has_key(id):
-								self.UpdateTimeDict[id]={}
-							if stime:
-								self.UpdateTimeDict[id]["Start_Time"]=string.strip(stime)
-							if etime:
-								self.UpdateTimeDict[id]["End_Time"]=string.strip(etime)
-							if shift:
-								if shift != "NA" and shift != "na":
-									self.UpdateTimeDict[id]["Time_Shift_sec"]=float(shift)
-								else:
-									self.UpdateTimeDict[id]["Time_Shift_sec"]=0.0
-							if quest:
-								if quest != "NA" and quest != "na":
-									self.UpdateTimeDict[id]["Time_Tag_Quest"]=string.strip(quest)
-							if type:
-								if shift != "NA" and shift != "na":
-									if string.strip(type) == "add": type=0
-									elif string.strip(type) == "replace": type=1
-								else:
-									type=0
-								self.UpdateTimeDict[id]["Corr_Type"]=type
-				if not self.UpdateHdrDict and not self.UpdateTimeDict:
-					err="ERROR: Template file not in correct format"
-					self.addTextInfoBar(err, 'red')
-					if BATCHMODE:
-						sys.exit(1)
-					else:
-						return
-				inputfile.close()
-				if not BATCHMODE:
-				# Write some log info
-					if self.UpdateHdrDict:
-						self.WriteLog("\n<Load Template>","Header","blue")
-						self.WriteLog("File: %s" % selection,"Header","dkgreen")
-					if self.UpdateTimeDict:
-						self.WriteLog("\n<Load Template>","Time","blue")
-						self.WriteLog("File: %s" % selection,"Time","dkgreen")
-					if self.UpdateHdrDict or self.UpdateTimeDict:
-						self.DumpUpdateDicts("load")
-					if self.UpdateHdrDict: self.WriteLog("<end>","Header","blue")
-					if self.UpdateTimeDict: self.WriteLog("<end>","Time","blue")
-				info = "Load Template: %s successful" % selection
-				self.addTextInfoBar(info, 'green')
-
-			except IOError, e:
-				err = "ERROR: Can't Load Template: %s" % selection, e
-				self.addTextInfoBar(err, 'red')
-				if BATCHMODE: sys.exit(1)
-
-		if not BATCHMODE:
-			self.DisplayLog()
+    def LoadTemplate(self):
+        """
+        Find a file and import into text window
+        """
+#                 timelist=[]
+#                 hdrlist=[]
+        if self.BatchFile.get():
+            selection = self.BatchFile.get()
+        else:
+            #if not self.DataDirList:
+                #err = "You must build a Trace db before loading template"
+                #self.addTextInfoBar(err, 'red')
+                #return
+            selection = askopenfilename\
+                (filetypes = [("All", "*")])
+        if selection:
+            try:
+                inputfile = open(selection,"r")
+                self.UpdateHdrDict = {}
+                self.SetHdrDict = {}
+                self.UpdateTimeDict = {}
+                self.SetTimeDict = {}
+                self.ClearAll(self.NewVars)
+                self.ClearAll(self.SetHdrVars)
+                self.ClearAll(self.ShiftVars)
+                while 1:
+                    newline = inputfile.readline()
+                    if not newline :
+                        break
+                    if newline[0] == "#" or newline[:-1] == "":
+                        continue
+                    if newline[0] == "}":
+                        print("ERROR in Template File Format")
+                    if newline[:7] == "hdrlist" :
+                        while 1:
+                            newline = inputfile.readline()
+                            if not newline :
+                                break
+                            if newline[0] == "#" or newline[:-1] == "":
+                                continue
+                            if newline[0] == "}": break
+                            if len(newline[:-1].split()) != 2 :
+                                self.UpdateTimeDict = {}
+                                break
+                            try:
+                                (key, newkey) = newline[:-1].split()
+                            except Exception as e:
+                                print("ERROR in Template File Format")
+                                break
+                            if key not in self.UpdateHdrDict :
+                                self.UpdateHdrDict[key] = {}
+                            (stat,chan,loc,net) = newkey.split(":")
+                            if stat:
+                                stat = stat.upper()
+                                self.UpdateHdrDict[key]["Station_Name"] = stat
+                            if chan:
+                                chan = chan.upper()
+                                self.UpdateHdrDict[key]["Channel"] = chan
+                            if loc:
+                                loc = loc.upper()
+                                self.UpdateHdrDict[key]["Location_Code"] = loc
+                            if net:
+                                net = net.upper()
+                                self.UpdateHdrDict[key]["Network_Code"] = net
+                    elif newline[:8] == "timelist" :
+                        while 1:
+                            newline = inputfile.readline()
+                            if not newline : break
+                            if newline[0] == "#" or newline[:-1] == "":
+                                continue
+                            if newline[0] == "}":
+                                break
+                            if len(newline[:-1].split()) != 6 :
+                                self.UpdateTimeDict={}
+                                break
+                            (id, stime,etime,shift,quest,type) = \
+                                newline[:-1].split()
+                            if id not in self.UpdateTimeDict:
+                                self.UpdateTimeDict[id] = {}
+                            if stime:
+                                self.UpdateTimeDict[id]["Start_Time"] = \
+                                    stime.strip()
+                            if etime:
+                                self.UpdateTimeDict[id]["End_Time"] = \
+                                    etime.strip()
+                            if shift:
+                                if shift != "NA" and shift != "na":
+                                    self.UpdateTimeDict[id]["Time_Shift_sec"]\
+                                        = float(shift)
+                                else:
+                                    self.UpdateTimeDict[id]["Time_Shift_sec"]\
+                                        = 0.0
+                            if quest:
+                                if quest != "NA" and quest != "na":
+                                    self.UpdateTimeDict[id]["Time_Tag_Quest"]\
+                                        = quest.strip()
+                            if type:
+                                if shift != "NA" and shift != "na":
+                                    if type.strip() == "add":\
+                                       type = 0
+                                    elif type.strip() == "replace":
+                                        type = 1
+                                else:
+                                    type = 0
+                                self.UpdateTimeDict[id]["Corr_Type"] = type
+                if not self.UpdateHdrDict and not self.UpdateTimeDict:
+                    err = "ERROR: Template file not in correct format"
+                    self.addTextInfoBar(err, 'red')
+                    if BATCHMODE:
+                        sys.exit(1)
+                    else:
+                        return
+                inputfile.close()
+                if not BATCHMODE:
+                # Write some log info
+                    if self.UpdateHdrDict:
+                        self.WriteLog("\n<Load Template>", "Header","blue")
+                        self.WriteLog("File: %s" % selection,
+                                      "Header","dkgreen")
+                    if self.UpdateTimeDict:
+                        self.WriteLog("\n<Load Template>", "Time","blue")
+                        self.WriteLog("File: %s" % selection,
+                                      "Time","dkgreen")
+                    if self.UpdateHdrDict or self.UpdateTimeDict:
+                        self.DumpUpdateDicts("load")
+                    if self.UpdateHdrDict:
+                        self.WriteLog("<end>","Header","blue")
+                    if self.UpdateTimeDict:
+                        self.WriteLog("<end>","Time","blue")
+                info = "Load Template: %s successful" % selection
+                self.addTextInfoBar(info, 'green')
+
+            except IOError as e:
+                err = "ERROR: Can't Load Template: %s" % selection, e
+                self.addTextInfoBar(err, 'red')
+                if BATCHMODE: sys.exit(1)
+
+        if not BATCHMODE:
+            self.DisplayLog()
 
 ##########################################
 
-	def killWindow(self, widget):
-		"""
-		Destroy Widget and Set InfoBar to Default
-		"""
-		widget.destroy()
-#		self.addTextInfoBar()
+    def killWindow(self, widget):
+        """
+        Destroy Widget and Set InfoBar to Default
+        """
+        widget.destroy()
+#                self.addTextInfoBar()
 
 
 #######################################
-	def buildHelp(self,master):
-		"""
-		Populate Help NoteBook
-		"""
-
-		self.Help_nb = master.add('Help')
-
-		self.TemplateFormat_b = Button(self.Help_nb,
-					       activebackground = 'green',
-					       background = 'lightblue',
-					       text="Template Format",
-					       activeforeground= 'black',
-					       command = Command(self.TemplateFormat, self.Help_nb)
-					       )
-		self.TemplateFormat_b.pack(side='top', anchor='e', padx=5, pady=5)
-		self.balloon.bind(self.TemplateFormat_b, "Display example format \nfor 'Template' file.")
-
-		self.HelpText = Pmw.ScrolledText(self.Help_nb,
-						 borderframe=1)
-		self.HelpText.pack(side='bottom', fill='both', expand=1)
-		#local variables
-		HelpTextinsert=self.HelpText.insert
-
-		self.HelpText.tag_config("hdr1", foreground="blue")
-		self.HelpText.tag_config("hdr2", foreground="darkgreen")
-		self.HelpText.tag_config("bttn", foreground="red")
-
-		HelpTextinsert("end", "NAME", "hdr1")
-		HelpTextinsert("end", """
+    def buildHelp(self,master):
+        """
+        Populate Help NoteBook
+        """
+
+        self.Help_nb = master.add('Help')
+
+        self.TemplateFormat_b = Button(self.Help_nb,
+                                       activebackground = 'green',
+                                       background = 'lightblue',
+                                       text="Template Format",
+                                       activeforeground= 'black',
+                                       command = Command(
+                                           self.TemplateFormat, self.Help_nb)
+                                       )
+        self.TemplateFormat_b.pack(side='top', anchor='e', padx=5, pady=5)
+        self.balloon.bind(self.TemplateFormat_b, "Display example format \nfor 'Template' file.")
+
+        self.HelpText = Pmw.ScrolledText(self.Help_nb,
+                                         borderframe=1)
+        self.HelpText.pack(side='bottom', fill='both', expand=1)
+        #local variables
+        HelpTextinsert = self.HelpText.insert
+
+        self.HelpText.tag_config("hdr1", foreground="blue")
+        self.HelpText.tag_config("hdr2", foreground="darkgreen")
+        self.HelpText.tag_config("bttn", foreground="red")
+
+        HelpTextinsert("end", "NAME", "hdr1")
+        HelpTextinsert("end", """
    fixhdr - a GUI to modify mseed file header fields
       ('Station Name', 'Channel', 'Location Code', and 'Network Code'),
       to apply time shifts and to convert header endianess.\n""")
 
-		HelpTextinsert("end", "\nVERSION", "hdr1")
-		HelpTextinsert("end", """
+        HelpTextinsert("end", "\nVERSION", "hdr1")
+        HelpTextinsert("end", """
    %s\n""" % VERSION)
 
-		HelpTextinsert("end", "\nSYNOPSIS", "hdr1")
-		HelpTextinsert("end", """
+        HelpTextinsert("end", "\nSYNOPSIS", "hdr1")
+        HelpTextinsert("end", """
    fixhdr
    fixhdr -#
    fixhdr -h
    fixhdr  [-d DataDirs] [-m batch_file] [-t batch_file] [-e endianess]\n""")
 
-		HelpTextinsert("end", "\nOPTIONS", "hdr1")
-		HelpTextinsert("end", """
+        HelpTextinsert("end", "\nOPTIONS", "hdr1")
+        HelpTextinsert("end", """
    -# returns version number
    -h returns usage
    -d DataDirs colon separated list of data directories [default: cwd]
    -m batch_file correct mseed headers in batch mode using batch_file
    -t batch_file correct trace timing in batch mode using batch_file
    -e endianess convert trace headers to endianess [big or little]
-   
+
    NOTE: -m, -t & -e are mutually exclusive. If you wish to do
    both timing and headers, run time corrections first.\n""")
 
-		HelpTextinsert("end", "\nDESCRIPTION", "hdr1")
-		HelpTextinsert("end", """
+        HelpTextinsert("end", "\nDESCRIPTION", "hdr1")
+        HelpTextinsert("end", """
    fixhdr has seven notebooks: """)
-		HelpTextinsert("end", "[Trace Headers], [Global Modify], [Time Shift],\n   [Endianess], [Log], [Help]", "hdr2")
-		HelpTextinsert("end", """ and """)
-		HelpTextinsert("end", "[MSEED format]", "hdr2")
-		HelpTextinsert("end", """. """)
-		HelpTextinsert("end", "[Trace Headers]", "hdr2")
-		HelpTextinsert("end", """ and """)
-		HelpTextinsert("end", "[Global Modify]\n", "hdr2")
-		HelpTextinsert("end", """   provide a means to read and modify mseed header fields (station, channel,
+        HelpTextinsert("end", "[Trace Headers], [Global Modify], "
+                       "[Time Shift],\n   [Endianess], [Log], [Help]", "hdr2")
+        HelpTextinsert("end", """ and """)
+        HelpTextinsert("end", "[MSEED format]", "hdr2")
+        HelpTextinsert("end", """. """)
+        HelpTextinsert("end", "[Trace Headers]", "hdr2")
+        HelpTextinsert("end", """ and """)
+        HelpTextinsert("end", "[Global Modify]\n", "hdr2")
+        HelpTextinsert("end", """   provide a means to read and modify mseed header fields (station, channel,
    location code, and network code) for files found beneath a specified 
    directory list. """)
-		HelpTextinsert("end", "[Time Shift] ", "hdr2")
-		HelpTextinsert("end", """allows the user to apply a bulk time shift to
+        HelpTextinsert("end", "[Time Shift] ", "hdr2")
+        HelpTextinsert("end", """allows the user to apply a bulk time shift to
    traces that fall between a start and end time and to set a header
    flag indicating that the time tag is questionable. """)
-		HelpTextinsert("end", "[Endianess] ", "hdr2")
-		HelpTextinsert("end", """converts traces
+        HelpTextinsert("end", "[Endianess] ", "hdr2")
+        HelpTextinsert("end", """converts traces
    between little and big, or big and little endian headers. The """)
-		HelpTextinsert("end", "[Log]", "hdr2")
-		HelpTextinsert("end", """ notebook 
+        HelpTextinsert("end", "[Log]", "hdr2")
+        HelpTextinsert("end", """ notebook 
    maintains records of key events.\n""")
 
-		HelpTextinsert("end", "\n   [Root Window]\n", "hdr2")
-		HelpTextinsert("end", """   Buttons:\n""")
-		HelpTextinsert("end", "      <Load Template>", "bttn")
-		HelpTextinsert("end", """: loads a previously saved or user created mapping
+        HelpTextinsert("end", "\n   [Root Window]\n", "hdr2")
+        HelpTextinsert("end", """   Buttons:\n""")
+        HelpTextinsert("end", "      <Load Template>", "bttn")
+        HelpTextinsert("end", """: loads a previously saved or user created mapping
          of header and timing modification that then can be applied.\n""")
-		HelpTextinsert("end", "      <Save Template>", "bttn")
-		HelpTextinsert("end", """: saves a map of all header and timing modifications.\n""")
-		HelpTextinsert("end", "      <Exit>", "bttn")
-		HelpTextinsert("end", """: Exits fixhdr and will query if not all mappings in
+        HelpTextinsert("end", "      <Save Template>", "bttn")
+        HelpTextinsert("end", """: saves a map of all header and timing modifications.\n""")
+        HelpTextinsert("end", "      <Exit>", "bttn")
+        HelpTextinsert("end", """: Exits fixhdr and will query if not all mappings in
          Updata_Dictionary have been applied.\n""")
 
-		HelpTextinsert("end", "\n   [Trace Headers]", "hdr2")
-		HelpTextinsert("end", """
+        HelpTextinsert("end", "\n   [Trace Headers]", "hdr2")
+        HelpTextinsert("end", """
    General:
       >> specify/load directories for header investigation/modifications
       >> manipulate/edit individual <sta><chn><loc><net> entries for
@@ -3897,57 +4111,57 @@ command= Command(self.KillCancelTL, runvar)
          for _ALL_ loaded headers
       >> store and recall header modification templates
    Buttons:\n""")
-		HelpTextinsert("end", "      <Build Trace db>", "bttn")
-		HelpTextinsert("end", """: Searchs the directories listed in the "Data-
+        HelpTextinsert("end", "      <Build Trace db>", "bttn")
+        HelpTextinsert("end", """: Searchs the directories listed in the "Data-
          Directories" entry box (a colon separated list) and builds a list of mseed
          files found indexing them on unique values of <sta><chn><loc><net><sps>.
          You can narrow your search by entering stations in the "Find Only Stations"
          entry box (a colon separated list).\n""")
-		HelpTextinsert("end", "      <Find>", "bttn")
-		HelpTextinsert("end", """: Launches a file browser allowing the user to
+        HelpTextinsert("end", "      <Find>", "bttn")
+        HelpTextinsert("end", """: Launches a file browser allowing the user to
          add directories to the "Data Directories" entry box. Double clicking selects
          the new directory.\n""")
-		HelpTextinsert("end", "      <Clear>", "bttn")
-		HelpTextinsert("end", """: Clears the "Data Directories" entry box.\n""")
-		HelpTextinsert("end", "      <List Traces>", "bttn")
-		HelpTextinsert("end", """: Lists all traces for the selected Sta:Chan:Loc:Net:Sps.\n""")
-		HelpTextinsert("end", "      <Modify Headers>", "bttn")
-		HelpTextinsert("end", """: Applies all current values in the Update_Dictionary
+        HelpTextinsert("end", "      <Clear>", "bttn")
+        HelpTextinsert("end", """: Clears the "Data Directories" entry box.\n""")
+        HelpTextinsert("end", "      <List Traces>", "bttn")
+        HelpTextinsert("end", """: Lists all traces for the selected Sta:Chan:Loc:Net:Sps.\n""")
+        HelpTextinsert("end", "      <Modify Headers>", "bttn")
+        HelpTextinsert("end", """: Applies all current values in the Update_Dictionary
          (that can be viewed in the """)
-		HelpTextinsert("end", "[Log] ", "hdr2")
-		HelpTextinsert("end", """notebook) to the current trace list that
+        HelpTextinsert("end", "[Log] ", "hdr2")
+        HelpTextinsert("end", """notebook) to the current trace list that
          was built using """)
-		HelpTextinsert("end", "<Build Trace db>\n", "bttn")
-		HelpTextinsert("end", "      <Clear Current>", "bttn")
-		HelpTextinsert("end", """: clears all entries in the Update_Dictionary and 
+        HelpTextinsert("end", "<Build Trace db>\n", "bttn")
+        HelpTextinsert("end", "      <Clear Current>", "bttn")
+        HelpTextinsert("end", """: clears all entries in the Update_Dictionary and 
          display for the currently selected sta:chan:loc:net:sps that 
          have not been applied.\n""")
-		HelpTextinsert("end", "      <Clear All>", "bttn")
-		HelpTextinsert("end", """: clears all entries in the Update_Dictionary that
+        HelpTextinsert("end", "      <Clear All>", "bttn")
+        HelpTextinsert("end", """: clears all entries in the Update_Dictionary that
          have not been applied.\n""")
 
-		HelpTextinsert("end", "\n   [Global Modify]", "hdr2")
-		HelpTextinsert("end", """
+        HelpTextinsert("end", "\n   [Global Modify]", "hdr2")
+        HelpTextinsert("end", """
    General:
       >> specify header values in "For Headers Matching:" column, using drop-
          down menus. Wildcards are allowed and are the default.
       >> enter new header values in "Substitute Values:"
    Buttons:\n""")
-		HelpTextinsert("end", "      <Global Set>", "bttn")
-		HelpTextinsert("end", """: inserts the values in "Substitute Values" into the "
+        HelpTextinsert("end", "      <Global Set>", "bttn")
+        HelpTextinsert("end", """: inserts the values in "Substitute Values" into the "
          Update_Dictionary using For Headers Matching" entries to determine
          which <sta><chn><loc><net><sps> to modify. This only creates entries
          in the dictionary and does NOT apply them to the mseed headers. You must
          use""")
-		HelpTextinsert("end", " [Trace Headers]->", "hdr2")
-		HelpTextinsert("end", "<Modify Headers> ", "bttn")
-		HelpTextinsert("end", """to apply these updates.\n""")
-		HelpTextinsert("end", "      <Clear All>", "bttn")
-		HelpTextinsert("end", """: clears all current entries. This does not
+        HelpTextinsert("end", " [Trace Headers]->", "hdr2")
+        HelpTextinsert("end", "<Modify Headers> ", "bttn")
+        HelpTextinsert("end", """to apply these updates.\n""")
+        HelpTextinsert("end", "      <Clear All>", "bttn")
+        HelpTextinsert("end", """: clears all current entries. This does not
          affect the Update_Dictionary.\n""")
 
-		HelpTextinsert("end", "\n   [Time Shift]", "hdr2")
-		HelpTextinsert("end", """
+        HelpTextinsert("end", "\n   [Time Shift]", "hdr2")
+        HelpTextinsert("end", """
    General:
       >> specify header values in "For Traces Matching:" column, using drop-
          down menus. Once selected first and last sample times will be displayed.
@@ -3959,133 +4173,135 @@ command= Command(self.KillCancelTL, runvar)
       >> "Applied" indicators notify a user when corrections have been
          appied in this instance of fixhdr.
    Buttons:\n""")
-		HelpTextinsert("end", "      <How to Treat Existing Corrections>", "bttn")
-		HelpTextinsert("end", """: you can choose to either add to any 
+        HelpTextinsert("end", "      <How to Treat Existing Corrections>", "bttn")
+        HelpTextinsert("end", """: you can choose to either add to any 
          correction listed in the Fixed Header or Replace 
          any existing correction with the one entered.\n""")
-		HelpTextinsert("end", "      <Undo Time Corrections>", "bttn")
-		HelpTextinsert("end", """: Allows user to un-apply previously 
+        HelpTextinsert("end", "      <Undo Time Corrections>", "bttn")
+        HelpTextinsert("end", """: Allows user to un-apply previously 
          applied timing corrections. Note: Use with caution. This 
          will only remove single and cumulative corrections. 
          Review 'List Time Corrections' to better understand 
          corrections already applied to trace headers.\n""")
-		HelpTextinsert("end", "      <List Time Corrections>", "bttn")
-		HelpTextinsert("end", """: Displays time corrections for traces
+        HelpTextinsert("end", "      <List Time Corrections>", "bttn")
+        HelpTextinsert("end", """: Displays time corrections for traces
          matching the selected Stat:Loc:Net key.\n""")
-		HelpTextinsert("end", "      <Apply Time Correction> ", "bttn")
-		HelpTextinsert("end", """to apply these updates.\n""")
-		HelpTextinsert("end", "      <Time Set>", "bttn")
-		HelpTextinsert("end", """: Allows user to build a dictionary of timing corrections 
+        HelpTextinsert("end", "      <Apply Time Correction> ", "bttn")
+        HelpTextinsert("end", """to apply these updates.\n""")
+        HelpTextinsert("end", "      <Time Set>", "bttn")
+        HelpTextinsert("end", """: Allows user to build a dictionary of timing corrections 
          to be applied with the "Apply Time Corrections" button. i.e. 
          timing corrections for multiple Stat:Loc:Net selections can
          be set prior to applying in a single instance.\n""")
-		HelpTextinsert("end", "      <Recalc Start/End>", "bttn")
-		HelpTextinsert("end", """: resets the start and end times from the trace 
+        HelpTextinsert("end", "      <Recalc Start/End>", "bttn")
+        HelpTextinsert("end", """: resets the start and end times from the trace 
          headers. The first time a trace is read in the start and end 
          times are cached for future use. If you change these times, 
          this button is used to update the cache and display.\n""")
-		HelpTextinsert("end", "      <Clear All>", "bttn")
-		HelpTextinsert("end", """: clears all current entries.\n""")
+        HelpTextinsert("end", "      <Clear All>", "bttn")
+        HelpTextinsert("end", """: clears all current entries.\n""")
 
-		HelpTextinsert("end", "\n   [Endianess]", "hdr2")
-		HelpTextinsert("end", """
+        HelpTextinsert("end", "\n   [Endianess]", "hdr2")
+        HelpTextinsert("end", """
    General:
       >> displays the number of big and little endian files found. Allows user to
          convert between big and little endian headers.
    Buttons:\n""")
-		HelpTextinsert("end", "      <Convert to Big>", "bttn")
-		HelpTextinsert("end", """: Converts headers from little to big endian\n""")
-		HelpTextinsert("end", "      <Convert to Little>", "bttn")
-		HelpTextinsert("end", """: Converts headers from big to little endian\n""")
+        HelpTextinsert("end", "      <Convert to Big>", "bttn")
+        HelpTextinsert("end", """: Converts headers from little to big endian\n""")
+        HelpTextinsert("end", "      <Convert to Little>", "bttn")
+        HelpTextinsert("end", """: Converts headers from big to little endian\n""")
 
-		HelpTextinsert("end", "\n   [Log]", "hdr2")
-		HelpTextinsert("end", """
+        HelpTextinsert("end", "\n   [Log]", "hdr2")
+        HelpTextinsert("end", """
    General:
       >> displays key events (e.g. "Build Trace db", "Modify Headers", etc.). Radio
          buttons allow you to select all log messages or window only those messages
          related to Header events, Time events, or changes in endianess
    Buttons:\n""")
-		HelpTextinsert("end", "      <Dump UpdateHdrDict>", "bttn")
-		HelpTextinsert("end", """: Dumps the current values in the Update_Dictionary and
+        HelpTextinsert("end", "      <Dump UpdateHdrDict>", "bttn")
+        HelpTextinsert("end", """: Dumps the current values in the Update_Dictionary and
          indicates whether or not they have been applied (i.e.""")
-		HelpTextinsert("end", " <Modify Headers>\n", "bttn")
-		HelpTextinsert("end", """         has been run).\n""")
-		HelpTextinsert("end", "      <Save Log File>", "bttn")
-		HelpTextinsert("end", """: Saves text window to an output file.\n""")
-		HelpTextinsert("end", "      <Clear Log File>", "bttn")
-		HelpTextinsert("end", """: Clears text window and flushes buffer.\n""")
+        HelpTextinsert("end", " <Modify Headers>\n", "bttn")
+        HelpTextinsert("end", """         has been run).\n""")
+        HelpTextinsert("end", "      <Save Log File>", "bttn")
+        HelpTextinsert("end", """: Saves text window to an output file.\n""")
+        HelpTextinsert("end", "      <Clear Log File>", "bttn")
+        HelpTextinsert("end", """: Clears text window and flushes buffer.\n""")
 
-		HelpTextinsert("end", "\nKEYWORDS", "hdr1")
-		HelpTextinsert("end", """   mseed; header information; header modification\n""")
+        HelpTextinsert("end", "\nKEYWORDS", "hdr1")
+        HelpTextinsert("end", """   mseed; header information; header modification\n""")
 
-		HelpTextinsert("end", "\nSEE ALSO", "hdr1")
-		HelpTextinsert("end", """   mseedhdr & SEED manual\n""")
+        HelpTextinsert("end", "\nSEE ALSO", "hdr1")
+        HelpTextinsert("end", """   mseedhdr & SEED manual\n""")
 
-		HelpTextinsert("end", "\nAUTHOR", "hdr1")
-		HelpTextinsert("end", """
+        HelpTextinsert("end", "\nAUTHOR", "hdr1")
+        HelpTextinsert("end", """
    Bruce Beaudoin <bruce@passcal.nmt.edu>
 """)
 
 ########################################
 
-	def TemplateFormat(self,master):
-		"""
-		Template file format help and examples
-		"""
-
-		try:
-			self.tl_State = self.helpFileFormat_tl.winfo_exists()
-		except:
-			self.tl_State = 0
-
-		if self.tl_State == 1:
-			self.addTextInfoBar("Template Format Already Open", 'orange')
-			self.helpFileFormat_tl.tkraise()
-		else:
-			self.helpFileFormat_tl = Toplevel(master)
-			self.helpFileFormat_tl.title("Template Format")
-
-			self.ExitFileHelp_b = Button(self.helpFileFormat_tl,
-						     activebackground = 'red',
-						     cursor = 'pirate',
-						     background = 'lightblue',
-						     text="Done",
-						     command = Command(self.killWindow, self.helpFileFormat_tl)
-						     )
-			self.ExitFileHelp_b.pack(side='bottom', fill='x', expand=1)
-			self.FileFormatText = Pmw.ScrolledText(self.helpFileFormat_tl,
-							       borderframe=1,
-							       )
-			self.FileFormatText.pack(side='bottom', fill='both', expand=1)
-			#local variable
-			FileFormatTextinsert=self.FileFormatText.insert
-
-			self.FileFormatText.tag_config("highlight", foreground="red")
-			self.FileFormatText.tag_config("example", foreground="blue")
-
-			FileFormatTextinsert("end", """
+    def TemplateFormat(self,master):
+        """
+        Template file format help and examples
+        """
+
+        try:
+            self.tl_State = self.helpFileFormat_tl.winfo_exists()
+        except Exception as e:
+            self.tl_State = 0
+
+        if self.tl_State == 1:
+            self.addTextInfoBar("Template Format Already Open", 'orange')
+            self.helpFileFormat_tl.tkraise()
+        else:
+            self.helpFileFormat_tl = Toplevel(master)
+            self.helpFileFormat_tl.title("Template Format")
+
+            self.ExitFileHelp_b = Button(self.helpFileFormat_tl,
+                                         activebackground = 'red',
+                                         cursor = 'pirate',
+                                         background = 'lightblue',
+                                         text="Done",
+                                         command = Command(
+                                             self.killWindow,
+                                             self.helpFileFormat_tl)
+                                         )
+            self.ExitFileHelp_b.pack(side='bottom', fill='x', expand=1)
+            self.FileFormatText = Pmw.ScrolledText(self.helpFileFormat_tl,
+                                                   borderframe=1,
+                                                   )
+            self.FileFormatText.pack(side='bottom', fill='both', expand=1)
+            #local variable
+            FileFormatTextinsert = self.FileFormatText.insert
+
+            self.FileFormatText.tag_config("highlight", foreground="red")
+            self.FileFormatText.tag_config("example", foreground="blue")
+
+            FileFormatTextinsert("end", """
  The Template file consists of two lists: """)
-			FileFormatTextinsert("end", "hdrlist", "highlight")
-			FileFormatTextinsert("end", """ and """)
-			FileFormatTextinsert("end", "timelist", "highlight")
-			FileFormatTextinsert("end", """.
+            FileFormatTextinsert("end", "hdrlist", "highlight")
+            FileFormatTextinsert("end", """ and """)
+            FileFormatTextinsert("end", "timelist", "highlight")
+            FileFormatTextinsert("end", """.
  These list are delimitted by '{}'. Comments are allowed in the template file
  and are denoted by a '#' in the first column. 
 
  For the """)
-			FileFormatTextinsert("end", "hdrlist", "highlight")
-			FileFormatTextinsert("end", """ the columns are:
+            FileFormatTextinsert("end", "hdrlist", "highlight")
+            FileFormatTextinsert("end", """ the columns are:
  stat:chan:loc:net:sps   stat:chan:loc:net
 
  For the """)
-			FileFormatTextinsert("end", "timelist", "highlight")
-			FileFormatTextinsert("end", """ the columns are:
+            FileFormatTextinsert("end", "timelist", "highlight")
+            FileFormatTextinsert("end", """ the columns are:
  sta:loc:net Start_Time        End_Time          Shift(s) Time_Tag     Corr_Type
  sta:loc:net yyyy:ddd:hh:mm:ss yyyy:ddd:hh:mm:ss float/NA set/unset/NA add/replace/NA
 
  EXAMPLE:""")
-			FileFormatTextinsert("end","""
-     
+            FileFormatTextinsert("end","""
+
      # Header Changes
      # stat:chan:loc:net:sps   stat:chan:loc:net
      hdrlist{
@@ -4102,18 +4318,18 @@ command= Command(self.KillCancelTL, runvar)
          \n""", "example")
 
 ##################################################################
-	def buildMSformat(self,master):
-		"""
-		Populate MSEED format definition noteBook
-		"""
-		self.MSformat_nb = master.add('MSEED format')
+    def buildMSformat(self,master):
+        """
+        Populate MSEED format definition noteBook
+        """
+        self.MSformat_nb = master.add('MSEED format')
 
-		self.MSformatText = Pmw.ScrolledText(self.MSformat_nb,
-						     borderframe=1)
-		self.MSformatText.pack(side='bottom', fill='both', expand=1)
+        self.MSformatText = Pmw.ScrolledText(self.MSformat_nb,
+                                             borderframe=1)
+        self.MSformatText.pack(side='bottom', fill='both', expand=1)
 
 
-		self.MSformatText.settext("""Appendix A From "SEED Reference Manual, v2.3, Feb. 1993:
+        self.MSformatText.settext("""Appendix A From "SEED Reference Manual, v2.3, Feb. 1993:
 Channel Naming
 Contributed by Scott Halbert
 
@@ -4145,19 +4361,19 @@ Band Code
 The first letter specifies the general sampling rate and the
 response band of the instrument. (The "A" code is reserved for
 administrative functions such as miscellaneous state of health.)
-	Band code   Band type                Sample rate (Hz)   Corner period (sec)
-	E           Extremely Short Period   >= 80              < 10 sec
-	S           Short Period             >= 10 to < 80      < 10 sec
-	H           High Broad Band          >= 80              >= 10 sec
-	B           Broad Band               >= 10 to < 80      >= 10 sec
-	M           Mid Period               > 1 to < 10
-	L           Long Period              ~ 1
-	V           Very Long Period         ~ 0.1
-	U           Ultra Long Period        ~ 0.01
-	R           Extremely Long Period    ~ 0.001
-	A           Administrative
-	W           Weather/Environmental
-	X           Experimental
+        Band code   Band type                Sample rate (Hz)   Corner period (sec)
+        E           Extremely Short Period   >= 80              < 10 sec
+        S           Short Period             >= 10 to < 80      < 10 sec
+        H           High Broad Band          >= 80              >= 10 sec
+        B           Broad Band               >= 10 to < 80      >= 10 sec
+        M           Mid Period               > 1 to < 10
+        L           Long Period              ~ 1
+        V           Very Long Period         ~ 0.1
+        U           Ultra Long Period        ~ 0.01
+        R           Extremely Long Period    ~ 0.001
+        A           Administrative
+        W           Weather/Environmental
+        X           Experimental
 
 
 Instrument Code and Orientation Code
@@ -4168,36 +4384,36 @@ parameters as specified for each instrument.
 
 Seismometer: Measures displacement/velocity/acceleration along a
 line defined by the dip and azimuth.
-	Instrument Code
-	H                 High Gain Seismometer
-	L                 Low Gain Seismometer
-	G                 Gravimeter
-	M                 Mass Position Seismometer
-	N*                 Accelerometer
-	*historically some channels from accelerometers have used
-	instrumentation codes of L and G. The use of N is the FDSN
-	convention as defined in August 2000.
-	Orientation Code
-	Z N E              Traditional (Vertical, North-South, East-West)
-	A B C              Triaxial (Along the edges of a cube turned up on a corner)
-	T R                For formed beams (Transverse, Radial)
-	1 2 3              Orthogonal components but non traditional orientations
-	U V W              Optional components
-	Dip/Azimuth:       Ground motion vector (reverse dip/azimuth
-		if signal polarity incorrect)
-	Signal Units:      M, M/S, M/S**2, (for G & M) M/S**2 (usually)
-	Channel Flags:     G
+        Instrument Code
+        H                 High Gain Seismometer
+        L                 Low Gain Seismometer
+        G                 Gravimeter
+        M                 Mass Position Seismometer
+        N*                 Accelerometer
+        *historically some channels from accelerometers have used
+        instrumentation codes of L and G. The use of N is the FDSN
+        convention as defined in August 2000.
+        Orientation Code
+        Z N E              Traditional (Vertical, North-South, East-West)
+        A B C              Triaxial (Along the edges of a cube turned up on a corner)
+        T R                For formed beams (Transverse, Radial)
+        1 2 3              Orthogonal components but non traditional orientations
+        U V W              Optional components
+        Dip/Azimuth:       Ground motion vector (reverse dip/azimuth
+                if signal polarity incorrect)
+        Signal Units:      M, M/S, M/S**2, (for G & M) M/S**2 (usually)
+        Channel Flags:     G
 
 Tilt Meter: Measures tilt from the horizontal plane. Azimuth is
 typically N/S or E/W.
-	Instrument Code
-	A
-	Orientation Code
-	N E                Traditional
-	Dip/Azimuth:       Ground motion vector (reverse dip/azimuth
-		if signal polarity incorrect)
-	Signal Units:      Radians
-	Channel Flags:     G
+        Instrument Code
+        A
+        Orientation Code
+        N E                Traditional
+        Dip/Azimuth:       Ground motion vector (reverse dip/azimuth
+                if signal polarity incorrect)
+        Signal Units:      Radians
+        Channel Flags:     G
 
 Creep Meter: Measures the absolute movement between two sides of
 a fault by means of fixing a metal beam on one side of the fault
@@ -4210,13 +4426,13 @@ Positive/Negative travel would be arbitrary, but would be noted
 in the dip/azimuth. Another type of Creep Meter involves using a
 wire that is stretched across the fault. Changes in wire length
 are triangulated to form movement vector.
-	Instrument Code
-	B
-	Orientation Code
-	Unknown
-	Dip/Azimuth:       Along the fault or wire vector
-	Signal Units:      M
-	Channel Flags:     G
+        Instrument Code
+        B
+        Orientation Code
+        Unknown
+        Dip/Azimuth:       Along the fault or wire vector
+        Signal Units:      M
+        Channel Flags:     G
 
 Calibration Input: Usually only used for seismometers or other
 magnetic coil instruments. This signal monitors the input signal
@@ -4224,40 +4440,40 @@ to the coil to be used in response evaluation. Usually tied to a
 specific instrument. Sometimes all instruments are calibrated
 together, sometimes horizontals are done separately from
 verticals.
-	Instrument Code
-	C
-	Orientation Code
-	A B C D... for when there are only a few cal sources for many devices.
-	Blank if there is only one calibrator at a time or, Match
-	Calibrated Channel (i.s. Z, N or E)
+        Instrument Code
+        C
+        Orientation Code
+        A B C D... for when there are only a few cal sources for many devices.
+        Blank if there is only one calibrator at a time or, Match
+        Calibrated Channel (i.s. Z, N or E)
 
 Pressure: A barometer, or microbarometer measures pressure. Used
 to measure the weather pressure or sometimes for state of health
 monitoring down hole. This includes infrasonic and hydrophone
 measurements.
-	Instrument Code
-	D
-	Orientation Code
-	O                  Outside
-	I                  Inside
-	D                  Down Hole
-	F                  Infrasound
-	H                  Hydrophone
-	U                  Underground
-	Dip/Azimuth:       Not applicable - Should be zero.
-	Signal Units:      Pa (Pascals)
-	Channel Flags:     W or H
+        Instrument Code
+        D
+        Orientation Code
+        O                  Outside
+        I                  Inside
+        D                  Down Hole
+        F                  Infrasound
+        H                  Hydrophone
+        U                  Underground
+        Dip/Azimuth:       Not applicable - Should be zero.
+        Signal Units:      Pa (Pascals)
+        Channel Flags:     W or H
 
 Electronic Test Point: Used to monitor circuitry inside recording
 system, local power or seismometer. Usually for power supply
 voltages, or line voltages.
-	Instrument Code
-	E
-	Orientation code
-	Designate as desired, make mnemonic as possible, use numbers
-		for test points, etc.
-	Dip/Azimuth:       Not applicableSignal Units: V, A, Hz, Etc.
-	Channel Flags:     H
+        Instrument Code
+        E
+        Orientation code
+        Designate as desired, make mnemonic as possible, use numbers
+                for test points, etc.
+        Dip/Azimuth:       Not applicableSignal Units: V, A, Hz, Etc.
+        Channel Flags:     H
 
 Magnetometer: Measures the magnetic field where the instrument is
 sitting. They measure the part of the field vector which is
@@ -4270,27 +4486,27 @@ to magnetic north, the azimuth would be + 103 for the E channel.
 Some magnetometers do not record any vector quantity associated
 with the signal, but record the total intensity. So, these would
 not have any dip/azimuth.
-	Instrument Code
-	F
-	Orientation Code
-	Z N E              Magnetic
-	Signal Units:      T - Teslas
-	Channel Flags:     G
+        Instrument Code
+        F
+        Orientation Code
+        Z N E              Magnetic
+        Signal Units:      T - Teslas
+        Channel Flags:     G
 
 Humidity: Absolute/Relative measurements of the humidity.
 Temperature recordings may also be essential for meaningful
 results.
-	Instrument Code
-	I
-	Orientation Code
-	O                  Outside Environment
-	I                  Inside Building
-	D                  Down Hole
-	1 2 3 4            Cabinet Sources
-	All other letters available for mnemonic source types.
-	Dip/Azimuth:       Not applicable - Should be zero.
-	Signal Units:      %
-	Channel Flags:     W
+        Instrument Code
+        I
+        Orientation Code
+        O                  Outside Environment
+        I                  Inside Building
+        D                  Down Hole
+        1 2 3 4            Cabinet Sources
+        All other letters available for mnemonic source types.
+        Dip/Azimuth:       Not applicable - Should be zero.
+        Signal Units:      %
+        Channel Flags:     W
 
 Temperature: Measurement of the temperature at some location.
 Typically used for measuring:
@@ -4298,61 +4514,61 @@ Typically used for measuring:
    2. State of Health - Inside recording building
    - Down hole
    - Inside electronics
-	Instrument Code
-	K
-	Orientation Code
-	O                  Outside Environment
-	I                  Inside Building
-	D                  Down Hole
-	1 2 3 4            Cabinet sources
-	All other letters available for mnemonic types.
-	Dip Azimuth:       Not applicable - Should be zero.
-	Signal Units:      deg C or deg K
-	Channel Flags:     W or H
+        Instrument Code
+        K
+        Orientation Code
+        O                  Outside Environment
+        I                  Inside Building
+        D                  Down Hole
+        1 2 3 4            Cabinet sources
+        All other letters available for mnemonic types.
+        Dip Azimuth:       Not applicable - Should be zero.
+        Signal Units:      deg C or deg K
+        Channel Flags:     W or H
 
 Water Current: This measurement measures the velocity of water in
 a given direction. The measurement may be at depth, within a
 borehole, or a variety of other locations.
-	Instrument Code
-	O
-	Orientation Code
-	Unknown
-	Dip/Azimuth:       Along current direction
-	Signal Units:      M/S
-	Channel Flags:     G
+        Instrument Code
+        O
+        Orientation Code
+        Unknown
+        Dip/Azimuth:       Along current direction
+        Signal Units:      M/S
+        Channel Flags:     G
 
 Geophone: Very short period seismometer, with natural frequency 5
 - 10 Hz or higher.
-	Instrument Code
-	P
-	Orientation Code
-	Z N E              Traditional
-	Dip/Azimuth:       Ground Motion Vector (Reverse dip/azimuth
-		if signal polarity incorrect)
-	Signal Units:      M, M/S, M/S
-	Channel Flags:     G
+        Instrument Code
+        P
+        Orientation Code
+        Z N E              Traditional
+        Dip/Azimuth:       Ground Motion Vector (Reverse dip/azimuth
+                if signal polarity incorrect)
+        Signal Units:      M, M/S, M/S
+        Channel Flags:     G
 
 Electric Potential: Measures the Electric Potential between two
 points. This is normally done using a high impedance voltmeter
 connected to two electrodes driven into the ground. In the case
 of magnetotelleuric work, this is one parameter that must be
 measured.
-	Instrument Code
-	Q
-	Orientation Code
-	Unknown
-	Signal Units:      V - Volts
-	Channel Flags:     G
+        Instrument Code
+        Q
+        Orientation Code
+        Unknown
+        Signal Units:      V - Volts
+        Channel Flags:     G
 
 Rainfall: Measures total rainfall, or an amount per sampling
 interval.
-	Instrument Code
-	R
-	Orientation Code
-	Unknown
-	Dip/Azimuth:       Not applicable - Should be zero.
-	Signal Units:      M, M/S
-	Channel Flags:     W
+        Instrument Code
+        R
+        Orientation Code
+        Unknown
+        Dip/Azimuth:       Not applicable - Should be zero.
+        Signal Units:      M, M/S
+        Channel Flags:     W
 
 Linear Strain: One typical application is to build a very
 sensitive displacement measuring device, typically a long quartz
@@ -4363,69 +4579,69 @@ also some interferometry projects which measure distance with
 lasers. Dip/Azimuth are the line of the movement being measured.
 Positive values are obtained when stress/distance increases,
 negative, when they decrease.
-	Instrument Code
-	S
-	Orientation Code
-	Z N E Vertical,    North-South, East-West
-	Dip/Azimuth:       Along axis of instrument
-	Signal Units:      M/M
-	Channel Flags:     G
+        Instrument Code
+        S
+        Orientation Code
+        Z N E Vertical,    North-South, East-West
+        Dip/Azimuth:       Along axis of instrument
+        Signal Units:      M/M
+        Channel Flags:     G
 
 Tide : Not to be confused with lunar tidal filters or gravimeter
 output. Tide instruments measure the depth of the water at the
 monitoring site.
-	Instrument Code
-	T
-	Orientation Code
-	Z                  Always vertical
-	Dip/Azimuth:       Always vertical
-	Signal Units:      M - Relative to sea level or local ocean depth
-	Channel Flags:     G
+        Instrument Code
+        T
+        Orientation Code
+        Z                  Always vertical
+        Dip/Azimuth:       Always vertical
+        Signal Units:      M - Relative to sea level or local ocean depth
+        Channel Flags:     G
 
 Bolometer: Infrared instrument used to evaluate average cloud
 cover. Used in astronomy to determine observability of sky.
-	Instrument Code
-	U
-	Orientation Code
-	Unknown
-	Dip/Azimuth:       Not applicable - Should be zero.
-	. Signal Units:    Unknown
-	Channel Flags:     W
-	
+        Instrument Code
+        U
+        Orientation Code
+        Unknown
+        Dip/Azimuth:       Not applicable - Should be zero.
+        . Signal Units:    Unknown
+        Channel Flags:     W
+
 Volumetric Strain: Unknown
-	Instrument Code
-	V
-	Orientation Code
-	Unknown
-	Dip/Azimuth:       Not Applicable - Should be zero.
-	Signal Units:      M**3/M**3
-	Channel Flags:     G
+        Instrument Code
+        V
+        Orientation Code
+        Unknown
+        Dip/Azimuth:       Not Applicable - Should be zero.
+        Signal Units:      M**3/M**3
+        Channel Flags:     G
 
 Wind: Measures the wind vector or velocity. Normal notion of dip
 and azimuth does not apply.
-	Instrument Code
-	W
-	Orientation Code
-	S                  Wind speed
-	D                  Wind Direction Vector - Relative to geographic North
-	Dip/Azimuth:       Not Applicable - Should be zero.
-	Channel Flags:     W
+        Instrument Code
+        W
+        Orientation Code
+        S                  Wind speed
+        D                  Wind Direction Vector - Relative to geographic North
+        Dip/Azimuth:       Not Applicable - Should be zero.
+        Channel Flags:     W
 
 Synthesized Beams: This is used when forming beams from
 individual elements of an array. Refer to blockettes 35, 400, &
 405.
-	Instrument Code
-	Z
-	Orientation Code
-	I                  Incoherent Beam
-	C                  Coherent Beam
-	F                  FK Beam		
-	O                  Origin Beam
-	Dip/Azimuth:       Ground motion vector (reverse dip/azimuth
-		if signal polarity incorrect)
-	Signal Units:      M, M/S, M/S**2, (for G & M) M/S**2 (usually)
-	Channel Flags:     G
-		
+        Instrument Code
+        Z
+        Orientation Code
+        I                  Incoherent Beam
+        C                  Coherent Beam
+        F                  FK Beam                
+        O                  Origin Beam
+        Dip/Azimuth:       Ground motion vector (reverse dip/azimuth
+                if signal polarity incorrect)
+        Signal Units:      M, M/S, M/S**2, (for G & M) M/S**2 (usually)
+        Channel Flags:     G
+
 
 
 Channel Code
@@ -4436,14 +4652,14 @@ health channels should begin with the "A" code; the source and
 orientation fields can then be used in any way.
 
 Here are some typical channel arrangements used by a GSN system:
-	Channel       Description
-	EHZ/EHN/EHE   Short Period 100 sps
-	BHZ/BHN/BHE   Broad Band 20 sps
-	LHZ/LHN/LHE   Long Period 1 sps
-	VHZ/VHN/VHE   Very Long Period 0.1 sps
-	BCI           Broad Band Calibration Signal
-	ECI           Short Period Cal
-	LOG           Console Log
+        Channel       Description
+        EHZ/EHN/EHE   Short Period 100 sps
+        BHZ/BHN/BHE   Broad Band 20 sps
+        LHZ/LHN/LHE   Long Period 1 sps
+        VHZ/VHN/VHE   Very Long Period 0.1 sps
+        BCI           Broad Band Calibration Signal
+        ECI           Short Period Cal
+        LOG           Console Log
 
 NOTE: Log Records: Log records has a channel identifier code of
 "LOG" and a sample rate of zero. The number of samples field is
@@ -4461,8 +4677,8 @@ def main():
         mw = MainWindow("fixhdr %s" % VERSION)
         mw.root.geometry("650x400")
         mw.root.mainloop()
-    #	import profile
-    #	profile.run("mw.root.mainloop()")
+    #        import profile
+    #        profile.run("mw.root.mainloop()")
 
 if __name__ == '__main__' :
     main()