diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6524a3fd7cb85e8093c49e99c381fdbc7c0230c9
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,36 @@
+image: python
+
+# Change pip's cache directory to be inside the project directory since we can
+# only cache local items.
+variables:
+  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache"
+
+# Pip's cache doesn't store the python packages
+# https://pip.pypa.io/en/stable/reference/pip_install/#caching
+#
+# If you want to also cache the installed packages, you have to install
+# them in a virtualenv and cache it as well.
+cache:
+  paths:
+    - .cache/pip
+
+stages:
+- test
+
+before_script:
+- pip install -e .[dev]
+
+
+python2:
+  image: python:2.7
+  tags:
+  - passoft
+  stage: test
+  script: tox -e py27
+
+python3:
+  image: python:3.6
+  tags:
+  - passoft
+  stage: test
+  script: tox -e py36
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 2c685e63b491669adf6c524d2381769b5a12e92f..2bd1c65d78181c1413cb027982434a3d85689043 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -32,7 +32,7 @@ wanted" is open to whoever wants to implement it.
 Implement Features
 ~~~~~~~~~~~~~~~~~~
 
-Look through the GitHub issues for features. Anything tagged with "enhancement"
+Look through the GitLab issues for features. Anything tagged with "enhancement"
 and "help wanted" is open to whoever wants to implement it.
 
 Write Documentation
@@ -65,7 +65,7 @@ Ready to contribute? Here's how to set up `fixhdr` for local development.
 
 3. Install your local copy::
 
-    $ python setup.py develop
+    $ pip install -e .[dev]
 
 4. Create a branch for local development::
 
@@ -88,10 +88,10 @@ Ready to contribute? Here's how to set up `fixhdr` for local development.
 Pull Request Guidelines
 -----------------------
 
-Before you submit a pull request, check that it meets these guidelines:
+Before you submit a merge request, check that it meets these guidelines:
 
-1. The pull request should include tests.
-2. If the pull request adds functionality, the docs should be updated. Put
+1. The merge request should include tests.
+2. If the merge request adds functionality, the docs should be updated. Put
    your new functionality into a function with a docstring, and add the
    feature to the list in README.rst.
 3. The pull request should work for Python 2.7
diff --git a/HISTORY.rst b/HISTORY.rst
index 53188249591583cad74358f06e7ad957e1da2e6b..fb69cdf9e027842ee58d78873a8afc50e0af5b73 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -2,7 +2,7 @@
 History
 =======
 
-2009.175 (2018-05-22)
+2009.175 (2018-06-07)
 ------------------
 
 * First release on new build system.
diff --git a/LICENSE b/LICENSE
index 00981d2036665d22ebcd05fa656518e5870cbe9e..2524e40cc3facbb6f4284d7cbdcad544d4e5435a 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,7 @@
 GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007
 
-    Modifies mseed headers.
+    Modifies mseed headers
     Copyright (C) 2018  IRIS PASSCAL
 
     This program is free software: you can redistribute it and/or modify
diff --git a/README.rst b/README.rst
index ae5e6279948ac6a3411f703e722c78af34f4104e..f401ff8bfe459721e0d9c71bfce3e1186adddd73 100644
--- a/README.rst
+++ b/README.rst
@@ -3,7 +3,7 @@ fixhdr
 ======
 
 
-Modifies mseed headers.
+Modifies mseed headers
 
 
 * Free software: GNU General Public License v3 (GPLv3)
@@ -18,7 +18,7 @@ Features
 Credits
 -------
 
-This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.
+This package was created with Cookiecutter_ and the `passoft/cookiecutter`_ project template.
 
 .. _Cookiecutter: https://github.com/audreyr/cookiecutter
-.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage
+.. _`passoft/cookiecutter`: https://git.passcal.nmt.edu/passoft/cookiecutter
diff --git a/conda.recipe/meta.yaml b/conda.recipe/meta.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..2ca8a2c0933613f75ab2d0d508f0fe795125f037
--- /dev/null
+++ b/conda.recipe/meta.yaml
@@ -0,0 +1,24 @@
+package:
+  name: fixhdr
+  version: 2009.175
+
+source:
+  path: ..
+
+build:
+  # If the installation is complex, or different between Unix and Windows, use
+  # separate bld.bat and build.sh files instead of this key.  Add the line
+  # "skip: True  # [py<35]" (for example) to limit to Python 3.5 and newer, or
+  # "skip: True  # [not win]" to limit to Windows.
+  script: python setup.py install --single-version-externally-managed --record=record.txt
+
+requirements:
+  build:
+    - python
+    - setuptools
+  run:
+    - python
+
+about:
+  home: https://git.passcal.nmt.edu/passoft/fixhdr
+  summary: Modifies mseed headers
diff --git a/fixhdr/LibTrace.py b/fixhdr/LibTrace.py
new file mode 100755
index 0000000000000000000000000000000000000000..0aa5923ae379c056cc8dcd5efc5f3132d755ce4f
--- /dev/null
+++ b/fixhdr/LibTrace.py
@@ -0,0 +1,1651 @@
+#!/usr/bin/env python
+
+#
+# LibTrace
+#
+# classes for Segy & Mseed
+#	identify file types
+#	read mseed headers
+#
+# author: bcb
+
+# Notes 2004.101
+
+# SEED
+# build a writer
+
+# SEGY
+# SEGY needs to be expanded
+# build a writer
+
+##########################
+# 2004.141
+# Modification
+# Author: bcb
+#
+# MSEED
+#	created UbytetoStr to decompose Ubyte to bit fields
+#	modified blks 200, 201, 300, 310, 320, 390 and fixhdr to utilize
+
+##########################
+# 2004.295
+# Modification
+# Author: bcb
+#
+# corrected bug in mseed.calcrate
+
+##########################
+# 2005.026
+# Modification
+# Author: bcb
+#
+# added blockette 2000 to Mseed class
+# Blockettes with BTime time definitions now pass the BTime
+#    as a tuple within the blk list
+# changed unpack formats to use native byte order with standard size & alignment
+
+##########################
+# 2005.035
+# Modification
+# Author: bcb
+#
+# 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.
+
+##########################
+# 2005.138
+# Modification
+# Author: bcb
+#
+# added
+# Mseed.Pad, Mseed.FlagStrtoInt, Mseed.WriteFixedHdr and all of Mseed.Writeblk???
+# fixed improper casting of Time Correction in Mseed.fixedhdr to signed long
+##########################
+# 2006.179
+# bug fix
+# Author: bcb
+#
+# text for little endian in class Segy:ByteOrder had an error such that
+# little endian files would never be found
+##########################
+# 2006.271
+# bug fix
+# Author: bcb
+#
+# index error in Mseed:tracelength that caused trace length calculation
+# to be 1 sample too long.
+##########################
+# 2006.335
+# bug fix
+# Author: bcb
+#
+# changed Mseed.__init__ to populate identification header fields
+# fixed oversight in handling flags in blk100 reads (forgot to 
+#    implement UbyteToStr
+# fixed improper handling of res fields in blk100, blk201 and blk400
+##########################
+# 2007.342
+# cleanup
+# Author: bcb
+#
+# Re-organized WriteFixedHdr to pack all packets prior to any writes. Avoids
+#    partially written fixed header
+##########################
+# 2008.038
+#
+# Author: bcb
+#
+# added GetBlk, PutBlk
+##########################
+# 2008.179
+#
+# Author: bcb
+#
+# minimized file reads
+# introduced FixedHeader class
+# maintained old functionality for now.
+##########################
+# 2008.204
+#
+# Author: bcb
+#
+# corrected typo from DHQaul to DHQual
+# added local variables to class Mseed
+
+import os, string, sys, struct, exceptions, time
+SPACE = " "
+
+#VERSION = "2008.204"
+
+class futils:
+	"""
+	file utilities class
+	"""
+	def __init__(self,infile):
+		self.infile = open(infile, 'r+b')
+
+	def close(self):
+		self.infile.close()
+
+	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
+#########################################################
+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 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 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 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 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 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 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 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 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
+#
+# 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)
+#########################################################
+	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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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
+# #
+		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 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
+
+
+#########################################################
+### 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 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 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 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 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_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
+# 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)
diff --git a/fixhdr/Makefile b/fixhdr/Makefile
deleted file mode 100644
index 66f21fdf0d6be03fb274e3f64181ab198506f922..0000000000000000000000000000000000000000
--- a/fixhdr/Makefile
+++ /dev/null
@@ -1,46 +0,0 @@
-# Requires sourcing the setup information in setup_passoft
-
-EXEC	=	fixhdr
-PYEXEC	=	fixhdr.py
-
-MODLIB	=	lib/python/$(EXEC)
-
-all:
-
-install:
-		@$(PASSINSTALL) -d -m 0755 $(PASSCAL)/$(MODLIB)
-		@$(PASSCHEXE) $(PYEXEC)
-		@$(PASSCP) $(PYEXEC) $(PASSCAL)/$(MODLIB)
-		@$(PASSCHEXE) $(EXEC)
-		@$(PASSCP) $(EXEC) $(PASSCAL)/bin
-		@$(PASSINSTALL) -d -m 0755 $(PASSCAL)/man/manl
-		@$(PASSCP) $(EXEC).man $(PASSCAL)/man/manl/$(EXEC).l
-
-installl:
-		@$(PASSINSTALL) -d -m 0755 $(PASSOFT)/$(MODLIB)
-		@$(PASSCHEXE) $(PYEXEC)
-		@$(PASSCP) $(PYEXEC) $(PASSOFT)/$(MODLIB)
-		@$(PASSCHEXE) $(EXEC)
-		@$(PASSCP) $(EXEC) $(PASSOFT)/bin/$(EXEC)
-
-tarsrc:
-		@$(PASSINSTALL) -d -m 0755 $(PASSCAL)/tar
-		@$(PASSCP) $(PASSOFT)/src/setup_passoft .
-		@$(PASSTAR) cf $(EXEC)src.tar setup_passoft Makefile \
-			$(EXEC) *.man *.py
-		@$(PASSCP) $(EXEC)src.tar $(PASSCAL)/tar
-
-tarbin:
-		@$(PASSINSTALL) -d -m 0755 $(PASSCAL)/tar
-		@$(PASSCP) $(PASSOFT)/src/setup_passoft .
-		@$(PASSTAR) cf $(EXEC)bin.tar setup_passoft Makefile \
-			$(EXEC) *.man *py
-		@$(PASSCP) $(EXEC)bin.tar $(PASSCAL)/tar
-
-clean:
-		@$(PASSRM) *~
-
-uninstall:
-		@$(PASSRM) $(PASSCAL)/bin/$(EXEC)
-		@$(PASSRM) -r $(PASSCAL)/$(MODLIB)
-		@$(PASSRM) $(PASSCAL)/man/manl/$(EXEC).l
diff --git a/fixhdr/fixhdr b/fixhdr/fixhdr
deleted file mode 100755
index 54bde8d78532dfa2409e507606b59dee6e4400a0..0000000000000000000000000000000000000000
--- a/fixhdr/fixhdr
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash
-#    Launch fixhdr.py
-
-if [ ! -z "${PASSCAL}" ]
-then
-   PYTHON=${PASSCAL}/other/bin/picpython
-   export PYTHON
-   PYTHONPATH=${PASSCAL}/lib:${PASSCAL}/lib/python/libtrace
-   export PYTHONPATH
-else
-   echo "PASSCAL environment variable not set! Cannot continue."
-   exit 1
-fi
-
-if [ $# = 0 ]
-then
-   echo "Starting fixhdr..."
-   ${PYTHON} ${PASSCAL}/lib/python/fixhdr/fixhdr.py $* &
-   exit 0
-fi
-if [ $1 = "-#" ]
-then
-   ${PYTHON} ${PASSCAL}/lib/python/fixhdr/fixhdr.py $*
-   exit 0
-fi
-echo "Starting fixhdr..."
-${PYTHON} ${PASSCAL}/lib/python/fixhdr/fixhdr.py $* &
-
diff --git a/fixhdr/fixhdr.py b/fixhdr/fixhdr.py
index 3ea7f8ccdc2bfec717820c6a01f6bc8bd8747646..f93bb34376830bb1a4f7e9fbdfa722958aef5953 100755
--- a/fixhdr/fixhdr.py
+++ b/fixhdr/fixhdr.py
@@ -46,7 +46,7 @@
 # author: bcb
 # date 2005.027
 #
-# added try/except for directory & file open in self.FindTrace to 
+# added try/except for directory & file open in self.FindTrace to
 # reflect changes in LibTrace.py
 # Optimized FindTrace
 #
@@ -75,7 +75,7 @@
 # 			FillTime
 # 			ClearAllTime
 #			SetFlag
-# 
+#
 #	Endianess notebook
 #		allows user to switch endianess of data headers
 #		associated functions:
@@ -99,7 +99,7 @@
 # 			functions:
 # 				FlushLogs
 # 				DisplayLogs
-# 
+#
 ##########################
 # modification
 # author: bcb
@@ -181,7 +181,7 @@
 # reworked methods
 #	LaunchApplyTimeCor, ApplyTimeCor, UpdateTimeShift, GetStartEnd, writeFile, LoadTemplate, ExitCheck
 #	wait, WriteLog, addTextInfoBar
-#	
+#
 # removed methods
 #	WaitWidget, ModAndExit
 #
@@ -550,7 +550,7 @@ class MainWindow:
 		if BATCHMODE:
 			#address endian change first since unique i.e. no batchfile
 			print "Running in Batch Mode"
-			if RunEndianBatch: 
+			if RunEndianBatch:
 				print "Changing Endianess to: ", Endianess
 				self.ToEndian.set(Endianess)
 				self.RunChangeEndian.set(1)
@@ -564,7 +564,7 @@ class MainWindow:
 				print "Using Template: ", self.BatchFile.get()
 				self.LoadTemplate()
 				if RunTimeBatch:
-					if not self.UpdateTimeDict: 
+					if not self.UpdateTimeDict:
 						print "No Timing Corrections in Template.\nDone"
 						sys.exit(1)
 					print "Finding Files beneath directory: ", self.DataDirs.get()
@@ -572,7 +572,7 @@ class MainWindow:
 					self.RunApplyTimeCor.set(1)
 					self.ApplyTimeCor()
 				if RunHeaderBatch:
-					if not self.UpdateHdrDict: 
+					if not self.UpdateHdrDict:
 						print "No Header Corrections in Template.\nDone"
 						sys.exit(1)
 					print "Finding Files beneath directory: ", self.DataDirs.get()
@@ -2251,7 +2251,7 @@ class MainWindow:
 
 			# 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. 
+			# logic.
 # 			numblk=hdrs[3][3]
 # 			addseek=hdrs[3][6]
 # 			b=0
@@ -2323,7 +2323,7 @@ class MainWindow:
 # 					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]"
@@ -2530,7 +2530,7 @@ class MainWindow:
 		#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
@@ -2564,7 +2564,7 @@ class MainWindow:
 			self.ToEndian.set("big")
 		else:
 			self.ToEndian.set("little")
-		#launch thread 
+		#launch thread
 		#eRun=threading.Thread(target=self.ChangeEndian)
 		self.ChangeEndian()
 		#eRun.start()
@@ -2635,7 +2635,7 @@ class MainWindow:
 			typenxt=msfile.typenxt
 			GetBlk=msfile.GetBlk
 			PutBlk=msfile.PutBlk
-			
+
 			filesize=msfile.filesize
 			blksize=msfile.blksize
 			(numblocks, odd_size)=divmod(filesize, blksize)
@@ -2780,7 +2780,7 @@ class MainWindow:
 			self.TraceList_tl = Toplevel(master)
 #			self.TraceList_tl.title("Trace Listing")
 
-			self.ExitTraceList_b = Button(self.TraceList_tl, 
+			self.ExitTraceList_b = Button(self.TraceList_tl,
 						      activebackground = 'red',
 						      cursor = 'pirate',
 						      background = 'lightblue',
@@ -2832,7 +2832,7 @@ class MainWindow:
 			self.TimeCorList_tl = Toplevel(master)
 			self.TimeCorList_tl.title("Time Corrections")
 
-			self.ExitTimeCorList_b = Button(self.TimeCorList_tl, 
+			self.ExitTimeCorList_b = Button(self.TimeCorList_tl,
 							activebackground = 'red',
 							cursor = 'pirate',
 							background = 'lightblue',
@@ -2898,7 +2898,7 @@ class MainWindow:
 		"""
 		#local variables
 		stringjoin=string.join
-		
+
 		FileCorDict={}
 		timeid = self.TimeShiftName.get()
 		(keystat,keyloc,keynet)=string.split(timeid, ":")
@@ -3071,7 +3071,7 @@ class MainWindow:
 			self.addTextInfoBar(" " + var + "...", 'orange')
 			if not self.SetHdrDict.has_key(var):
 				self.ExitWidget(self.root)
-				return 
+				return
 			else:
 				for subkey in self.UpdateHdrDict[var].keys():
 					if not self.SetHdrDict[var].has_key(subkey):
@@ -3082,7 +3082,7 @@ class MainWindow:
 ##################################################################
 	def ExitWidget(self,master):
 		"""
-		Allow user to apply UpdateHdrDict entries that have not 
+		Allow user to apply UpdateHdrDict entries that have not
 		been applied
 		"""
 # first see if we got here from ExitCheck. If so kill window
@@ -3131,8 +3131,8 @@ class MainWindow:
 						  relief = 'groove',
 						  borderwidth=2
 						  )
-			self.ExitEntry_fm.pack(side='left', 
-					       fill='x', 
+			self.ExitEntry_fm.pack(side='left',
+					       fill='x',
 					       pady=5
 					       )
 
@@ -3316,8 +3316,8 @@ command= Command(self.KillCancelTL, runvar)
 				     relief = 'groove',
 				     borderwidth=2
 				     )
-		self.Text_fm.pack(side='top', 
-				  fill='x', 
+		self.Text_fm.pack(side='top',
+				  fill='x',
 				  pady=5
 				  )
 
@@ -3402,7 +3402,7 @@ command= Command(self.KillCancelTL, runvar)
 							)
 				self.NewOnly_b.pack(side='bottom', fill='x')
 
-			elif action == "undo":	
+			elif action == "undo":
 				self.WarnWidgetDismiss_b = Button(self.WarnWidget_tl,
 								  text="Ignore & Undo Corrections",
 								  cursor='pirate',
@@ -3416,8 +3416,8 @@ command= Command(self.KillCancelTL, runvar)
 					     relief = 'groove',
 					     borderwidth=2
 					     )
-			self.Text_fm.pack(side='top', 
-					  fill='x', 
+			self.Text_fm.pack(side='top',
+					  fill='x',
 					  pady=5
 					  )
 			if action == "undo":
@@ -3529,8 +3529,8 @@ command= Command(self.KillCancelTL, runvar)
 							relief = 'groove',
 							borderwidth=2
 							)
-			self.saveWidgetEntry_fm.pack(side='left', 
-						     fill='x', 
+			self.saveWidgetEntry_fm.pack(side='left',
+						     fill='x',
 						     pady=5
 						     )
 
@@ -3686,7 +3686,7 @@ command= Command(self.KillCancelTL, runvar)
 					newline = inputfile.readline()
 					if not newline : break
 					if newline[0] == "#" or newline[:-1] == "": continue
-					if newline[0] == "}": 
+					if newline[0] == "}":
 						print  "ERROR in Template File Format"
 					if newline[:7] == "hdrlist" :
 						while 1:
@@ -3794,10 +3794,10 @@ command= Command(self.KillCancelTL, runvar)
 		"""
 		Populate Help NoteBook
 		"""
-		
+
 		self.Help_nb = master.add('Help')
 
-		self.TemplateFormat_b = Button(self.Help_nb, 
+		self.TemplateFormat_b = Button(self.Help_nb,
 					       activebackground = 'green',
 					       background = 'lightblue',
 					       text="Template Format",
@@ -4039,7 +4039,7 @@ command= Command(self.KillCancelTL, runvar)
 			self.helpFileFormat_tl = Toplevel(master)
 			self.helpFileFormat_tl.title("Template Format")
 
-			self.ExitFileHelp_b = Button(self.helpFileFormat_tl, 
+			self.ExitFileHelp_b = Button(self.helpFileFormat_tl,
 						     activebackground = 'red',
 						     cursor = 'pirate',
 						     background = 'lightblue',
@@ -4059,7 +4059,7 @@ command= Command(self.KillCancelTL, runvar)
 
 			FileFormatTextinsert("end", """
  The Template file consists of two lists: """)
-			FileFormatTextinsert("end", "hdrlist", "highlight") 
+			FileFormatTextinsert("end", "hdrlist", "highlight")
 			FileFormatTextinsert("end", """ and """)
 			FileFormatTextinsert("end", "timelist", "highlight")
 			FileFormatTextinsert("end", """.
@@ -4067,12 +4067,12 @@ command= Command(self.KillCancelTL, runvar)
  and are denoted by a '#' in the first column. 
 
  For the """)
-			FileFormatTextinsert("end", "hdrlist", "highlight") 
+			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", "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
@@ -4447,11 +4447,17 @@ packed into records until a message falls into a new minute. Log
 records have no blockettes, so the strings start at offset
 48.""")
 ##################################################################
-if BatchFile:
-	mw = MainWindow("fixhdr %s" % VERSION, BatchFile)
-else:
-	mw = MainWindow("fixhdr %s" % VERSION)
-	mw.root.geometry("650x400")
-	mw.root.mainloop()
-#	import profile
-#	profile.run("mw.root.mainloop()")
+
+def main():
+    if BatchFile:
+        mw = MainWindow("fixhdr %s" % VERSION, BatchFile)
+    else:
+        mw = MainWindow("fixhdr %s" % VERSION)
+        mw.root.geometry("650x400")
+        mw.root.mainloop()
+    #	import profile
+    #	profile.run("mw.root.mainloop()")
+
+if __name__ == '__main__' :
+    main()
+
diff --git a/requirements_dev.txt b/requirements_dev.txt
deleted file mode 100644
index a253cec2f07d3bb4b8610c047d2358dabfcd82af..0000000000000000000000000000000000000000
--- a/requirements_dev.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-pip==9.0.1
-bumpversion==0.5.3
-wheel==0.30.0
-watchdog==0.8.3
-flake8==3.5.0
-tox==2.9.1
-coverage==4.5.1
-Sphinx==1.7.1
-twine==1.10.0
-
-
diff --git a/setup.py b/setup.py
index a72fbba94165c2081aba599109289968d1494dc2..5a451add87e851362a3b08c198cdc54c789cd77b 100644
--- a/setup.py
+++ b/setup.py
@@ -22,14 +22,27 @@ setup(
         'Natural Language :: English',
         'Programming Language :: Python :: 2.7',
     ],
-    description="Modifies mseed headers.",
+    description="Modifies mseed headers",
     entry_points={
         'console_scripts': [
             'fixhdr=fixhdr.fixhdr:main',
         ],
     },
-    install_requires=[],
+    install_requires=['Pmw'],
     setup_requires = [],
+    extras_require={
+        'dev': [
+            'pip',
+            'bumpversion',
+            'wheel',
+            'watchdog',
+            'flake8',
+            'tox',
+            'coverage',
+            'Sphinx',
+            'twine',
+        ]
+    },
     license="GNU General Public License v3",
     long_description=readme + '\n\n' + history,
     include_package_data=True,
diff --git a/tox.ini b/tox.ini
index ba176443d41b800abf882f3cca08bd7e443b8b7b..5482bdfbbba7662cec49153b3c31307252b7e8d1 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,9 +1,10 @@
 [tox]
-envlist = py27, flake8
+envlist = py27, py36 flake8
 
 [travis]
 python =
     2.7: py27
+    3.6: py36
 
 [testenv:flake8]
 basepython = python
@@ -13,6 +14,6 @@ commands = flake8 fixhdr
 [testenv]
 setenv =
     PYTHONPATH = {toxinidir}
-python setup.py test
+commands=python setup.py test