General cleanup.

This commit is contained in:
Robert Smallshire
2014-09-01 13:58:34 +02:00
parent 3b8f3ac26c
commit dcac37022d
21 changed files with 1247 additions and 2266 deletions
-105
View File
@@ -1,105 +0,0 @@
#!/usr/bin/env python
#Licence: GPLv2.0
#Copyright: Dave Aitel
import sys
try:
import pygtk
#tell pyGTK, if possible, that we want GTKv2
pygtk.require("2.0")
except:
print "You need to install pyGTK or GTKv2 or set your PYTHONPATH correctly"
print "try: export PYTHONPATH=/usr/local/lib/python2.2/site-packages/"
sys.exit(1)
import gtk
import gtk.glade
import segypy
#now we have both gtk and gtk.glade imported
#Also, we know we are running GTKv2
def insert_row(model,parent,firstcolumn,secondcolumn):
myiter=model.insert_after(parent,None)
model.set_value(myiter,0,firstcolumn)
model.set_value(myiter,1,secondcolumn)
return myiter
class appgui:
def __init__(self):
"""
In this init we are going to display the main serverinfo window
"""
gladefile="project1.glade"
windowname="serverinfo"
self.wTree=gtk.glade.XML (gladefile,windowname)
#we only have one callback to register, but you could register
#any number, or use a special class that
#automatically registers all callbacks
dic = { "on_button1_clicked" : self.button1_clicked,
"on_serverinfo_destroy" : (gtk.mainquit)}
self.wTree.signal_autoconnect (dic)
self.logwindowview=self.wTree.get_widget("textview1")
self.logwindow=gtk.TextBuffer(None)
self.logwindowview.set_buffer(self.logwindow)
import gobject
self.treeview=self.wTree.get_widget("treeview1")
self.treemodel=gtk.TreeStore(gobject.TYPE_STRING,
gobject.TYPE_INT,
gobject.TYPE_STRING)
self.treeview.set_model(self.treemodel)
self.treeview.set_headers_visible(True)
renderer=gtk.CellRendererText()
column=gtk.TreeViewColumn("Name",renderer, text=0)
column.set_resizable(True)
self.treeview.append_column(column)
renderer=gtk.CellRendererText()
column=gtk.TreeViewColumn("Description",renderer, text=1)
column.set_resizable(True)
self.treeview.append_column(column)
self.treeview.show()
model=self.treemodel
treeSTH=insert_row(model,None,'Segy Trace Header', '')
for key in segypy.TRACE_HEADER_DEF.keys():
insert_row(model,treeSTH,key, 'An Empty Row')
treeSH=insert_row(model,None,'Segy Header', 'SH')
for key in segypy.HEADER_DEF.keys():
insert_row(model,treeSH,key, 'An Empty Row')
return
#####CALLLBACKS
def button1_clicked(self,widget):
print "button clicked"
host=self.wTree.get_widget("entry1").get_text()
port=int(self.wTree.get_widget("spinbutton1").get_value())
if host=="":
return
import urllib
page=urllib.urlopen("http://"+host+":"+str(port)+"/")
data=page.read()
try:
#this changed in a revision of pyGTK2
self.logwindow.insert_at_cursor(data,len(data))
except:
self.logwindow.insert_at_cursor(data)
#print data
return
app=appgui()
gtk.main()
-240
View File
@@ -1,240 +0,0 @@
#!/usr/bin/python2.4
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Small test to demonstrate glade.XML.signal_autoconnect on an instance
#
import pygtk
pygtk.require('2.0')
import matplotlib
matplotlib.use('GTK')
from matplotlib.figure import Figure
from matplotlib.axes import Subplot
from matplotlib.backends.backend_gtk import FigureCanvasGTK, NavigationToolbar
from matplotlib.numerix import arange, sin, pi
import Numeric as numpy
import gtk, gtk.glade
import segypy
def insert_row(model,parent,firstcolumn,secondcolumn,thirdcolumn):
myiter=model.insert_after(parent,None)
model.set_value(myiter,0,firstcolumn)
model.set_value(myiter,1,secondcolumn)
model.set_value(myiter,2,thirdcolumn)
# print secondcolumn
# return myiter
def update_segyplot(self):
self.figure = Figure(figsize=(6,4), dpi=72)
self.axis = self.figure.add_subplot(111)
self.axis.set_xlabel('Trace Header')
self.axis.set_ylabel('Time [s]')
self.axis.set_title(self.segy[1]['filename'])
self.axis.grid(True)
self.axis.imshow(self.segy[0])
self.canvas = FigureCanvasGTK(self.figure) # a gtk.DrawingArea
self.canvas.show()
self.graphview = self.xml.get_widget("vbox4")
self.graphview.pack_start(self.canvas, True, True)
def init_treeviews(self):
import gobject
###############################################################
# SEGYHEADER VIEW
self.treeview1 = self.xml.get_widget("treeview1")
self.treemodel1 = gtk.TreeStore(gobject.TYPE_STRING,
gobject.TYPE_STRING,
gobject.TYPE_STRING)
self.treeview1.set_model(self.treemodel1)
self.treeview1.set_headers_visible(True)
# COLUMN 1
renderer= gtk.CellRendererText()
self.tvcolumn1 = gtk.TreeViewColumn('Name', renderer, text=0)
self.tvcolumn1.set_resizable(True)
self.treeview1.append_column(self.tvcolumn1)
# COLUMN 2
renderer= gtk.CellRendererText()
self.tvcolumn2 = gtk.TreeViewColumn('Meaning', renderer, text=1)
self.tvcolumn2.set_resizable(True)
self.treeview1.append_column(self.tvcolumn2)
# COLUMN 3
renderer= gtk.CellRendererText()
self.tvcolumn3 = gtk.TreeViewColumn('Value', renderer, text=2)
self.tvcolumn3.set_resizable(True)
self.treeview1.append_column(self.tvcolumn3)
###############################################################
# SEGYHEADER VIEW
self.treeview2 = self.xml.get_widget("treeview2")
self.treemodel2 = gtk.TreeStore(gobject.TYPE_STRING,
gobject.TYPE_STRING,
gobject.TYPE_STRING)
self.treeview2.set_model(self.treemodel2)
self.treeview2.set_headers_visible(True)
# COLUMN 1
renderer= gtk.CellRendererText()
self.tvcolumn1 = gtk.TreeViewColumn('Name', renderer, text=0)
self.tvcolumn1.set_resizable(True)
self.treeview2.append_column(self.tvcolumn1)
# COLUMN 2
renderer= gtk.CellRendererText()
self.tvcolumn2 = gtk.TreeViewColumn('Meaning', renderer, text=1)
self.tvcolumn2.set_resizable(True)
self.treeview2.append_column(self.tvcolumn2)
# COLUMN 3
renderer= gtk.CellRendererText()
self.tvcolumn3 = gtk.TreeViewColumn('Value', renderer, text=2)
self.tvcolumn3.set_resizable(True)
self.treeview2.append_column(self.tvcolumn3)
def update_segyheader(self):
import gobject
# INSERT INTO TREEMODEL
self.SHtree= {"init": 1}
for key in segypy.HEADER_DEF.keys():
SHkey=segypy.HEADER_DEF[key]
if (SHkey.has_key('descr')):
descr = segypy.HEADER_DEF[key]['descr'][0][self.segy[1][key]]
else:
descr = ''
insert_row(self.treemodel1,None,key,descr,self.segy[1][key])
self.treeview1.show()
def update_segytraceheader(self,itrace=1):
import gobject
# INSERT INTO TREEMODEL
self.STHtree= {"init": 1}
for key in segypy.TRACE_HEADER_DEF.keys():
STHkey=segypy.TRACE_HEADER_DEF[key]
if (STHkey.has_key('descr')):
try:
descr = segypy.TRACE_HEADER_DEF[key]['descr'][0][self.segy[2][key][itrace-1]]
except:
descr='Not Defined'
else:
descr = ''
insert_row(self.treemodel2,None,key,descr,self.segy[2][key][itrace-1])
self.treeview2.show()
class SimpleTest:
def __init__(self):
self.xml = gtk.glade.XML('segygui/segygui.glade')
self.xml.signal_autoconnect(self)
init_treeviews(self)
self.window1 = self.xml.get_widget("window1")
self.window1.resize(600,400)
def on_cut1_activate(self, button):
self.hpaned1= self.xml.get_widget("hpaned1")
self.vbox3= self.xml.get_widget("vbox3")
pos = self.hpaned1.get_position()
if (pos==1):
pos=100
self.vbox3.visible = 1
else:
pos=1
self.vbox3.visible = 0
pos = self.hpaned1.set_position(pos)
print self.vbox3.visible
#width,height = self.vbox3.get_size()
#print width,height
# self.window1.resize(400,400)
def on_about1_activate(self, button):
dialog = gtk.AboutDialog()
dialog.set_name("SegyPY GUI")
dialog.set_version(segypy.version.__str__())
dialog.set_copyright("\302\251 Copyright 200x Thomas Mejer Hansen")
dialog.set_website("http://segymat.sourceforge.net/segypy/")
authors=["Thomas Mejer Hansen"]
dialog.set_authors(authors)
try:
f=open('LICENSE')
license = f.read(100000)
except IOError:
license = 'Could not read license file....';
dialog.set_license(license)
## Close dialog on user response
dialog.connect ("response", lambda d, r: d.destroy())
dialog.show()
def on_open1_activate(self, button):
dialog = gtk.FileChooserDialog("Open..",
None,
gtk.FILE_CHOOSER_ACTION_OPEN,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
dialog.set_default_response(gtk.RESPONSE_OK)
filter = gtk.FileFilter()
filter.set_name("All files")
filter.add_pattern("*")
dialog.add_filter(filter)
filter = gtk.FileFilter()
filter.set_name("SEG-Y files")
filter.add_pattern("*.segy")
filter.add_pattern("*.sgy")
filter.add_pattern("*.seg-y")
dialog.add_filter(filter)
filter = gtk.FileFilter()
filter.set_name("SU files")
filter.add_pattern("*.su")
dialog.add_filter(filter)
response = dialog.run()
if response == gtk.RESPONSE_OK:
print dialog.get_filename(), 'selected'
filename = dialog.get_filename()
dialog.destroy()
self.segy = segypy.read_segy(filename)
update_segyheader(self)
update_segytraceheader(self)
update_segyplot(self)
def on_new1_activate(self, button):
self.segy = segypy.read_segy('../data_4byteINT.segy')
update_segyheader(self)
update_segytraceheader(self,1)
update_segyplot(self)
test = SimpleTest()
gtk.main()
-192
View File
@@ -1,192 +0,0 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkWindow" id="serverinfo">
<property name="visible">True</property>
<property name="title" translatable="yes">Server Info</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<signal name="destroy" handler="on_serverinfo_destroy" last_modification_time="Wed, 15 Jan 2003 16:24:14 GMT"/>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">8</property>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">Host:</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="entry1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="visibility">True</property>
<property name="max_length">0</property>
<property name="text" translatable="yes"></property>
<property name="has_frame">True</property>
<property name="invisible_char">*</property>
<property name="activates_default">False</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkSpinButton" id="spinbutton1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="climb_rate">1</property>
<property name="digits">0</property>
<property name="numeric">False</property>
<property name="update_policy">GTK_UPDATE_ALWAYS</property>
<property name="snap_to_ticks">False</property>
<property name="wrap">False</property>
<property name="adjustment">80 1 65535 1 10 10</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="button1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">GO!</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_button1_clicked" last_modification_time="Wed, 15 Jan 2003 15:10:01 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
<property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
<property name="shadow_type">GTK_SHADOW_NONE</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTextView" id="textview1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">True</property>
<property name="overwrite">False</property>
<property name="accepts_tab">True</property>
<property name="justification">GTK_JUSTIFY_LEFT</property>
<property name="wrap_mode">GTK_WRAP_NONE</property>
<property name="cursor_visible">True</property>
<property name="pixels_above_lines">0</property>
<property name="pixels_below_lines">0</property>
<property name="pixels_inside_wrap">0</property>
<property name="left_margin">0</property>
<property name="right_margin">0</property>
<property name="indent">0</property>
<property name="text" translatable="yes"></property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
<property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
<property name="shadow_type">GTK_SHADOW_NONE</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTreeView" id="treeview1">
<property name="width_request">130</property>
<property name="height_request">226</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">True</property>
<property name="rules_hint">False</property>
<property name="reorderable">False</property>
<property name="enable_search">True</property>
<property name="fixed_height_mode">False</property>
<property name="hover_selection">False</property>
<property name="hover_expand">False</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
-497
View File
@@ -1,497 +0,0 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkWindow" id="window1">
<property name="visible">True</property>
<property name="title" translatable="yes">Segy Viewer</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_CENTER</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="icon_name">stock_chart-reorganize</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<property name="pack_direction">GTK_PACK_DIRECTION_LTR</property>
<property name="child_pack_direction">GTK_PACK_DIRECTION_LTR</property>
<child>
<widget class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="label" translatable="yes">_File</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menuitem1_menu">
<child>
<widget class="GtkImageMenuItem" id="new1">
<property name="visible">True</property>
<property name="label">gtk-new</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_new1_activate" last_modification_time="Sun, 09 Oct 2005 20:43:06 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="open1">
<property name="visible">True</property>
<property name="label">gtk-open</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_open1_activate" last_modification_time="Sun, 09 Oct 2005 20:43:06 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="save1">
<property name="visible">True</property>
<property name="label">gtk-save</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_save1_activate" last_modification_time="Sun, 09 Oct 2005 20:43:06 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="save_as1">
<property name="visible">True</property>
<property name="label">gtk-save-as</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_save_as1_activate" last_modification_time="Sun, 09 Oct 2005 20:43:06 GMT"/>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="quit1">
<property name="visible">True</property>
<property name="label">gtk-quit</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_quit1_activate" last_modification_time="Sun, 09 Oct 2005 20:43:06 GMT"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem2">
<property name="visible">True</property>
<property name="label" translatable="yes">_Edit</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menuitem2_menu">
<child>
<widget class="GtkMenuItem" id="segy_header1">
<property name="visible">True</property>
<property name="label" translatable="yes">Segy Header</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_segy_header1_activate" last_modification_time="Mon, 10 Oct 2005 07:29:34 GMT"/>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="trace_header1">
<property name="visible">True</property>
<property name="label" translatable="yes">Trace Header</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_trace_header1_activate" last_modification_time="Mon, 10 Oct 2005 07:29:34 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="cut1">
<property name="visible">True</property>
<property name="label">gtk-cut</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_cut1_activate" last_modification_time="Sun, 09 Oct 2005 20:43:06 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="copy1">
<property name="visible">True</property>
<property name="label">gtk-copy</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_copy1_activate" last_modification_time="Sun, 09 Oct 2005 20:43:06 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="paste1">
<property name="visible">True</property>
<property name="label">gtk-paste</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_paste1_activate" last_modification_time="Sun, 09 Oct 2005 20:43:06 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="delete1">
<property name="visible">True</property>
<property name="label">gtk-delete</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_delete1_activate" last_modification_time="Sun, 09 Oct 2005 20:43:06 GMT"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem3">
<property name="visible">True</property>
<property name="label" translatable="yes">_View</property>
<property name="use_underline">True</property>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem4">
<property name="visible">True</property>
<property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menuitem4_menu">
<child>
<widget class="GtkMenuItem" id="about1">
<property name="visible">True</property>
<property name="label" translatable="yes">_About</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_about1_activate" last_modification_time="Sun, 09 Oct 2005 20:43:06 GMT"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkHPaned" id="hpaned1">
<property name="width_request">385</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<widget class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkNotebook" id="notebook1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="show_tabs">True</property>
<property name="show_border">True</property>
<property name="tab_pos">GTK_POS_TOP</property>
<property name="scrollable">False</property>
<property name="enable_popup">False</property>
<child>
<placeholder/>
</child>
<child>
<widget class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">Plot</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">tab</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
<property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTreeView" id="treeview1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">True</property>
<property name="rules_hint">False</property>
<property name="reorderable">False</property>
<property name="enable_search">True</property>
<property name="fixed_height_mode">False</property>
<property name="hover_selection">False</property>
<property name="hover_expand">False</property>
</widget>
</child>
</widget>
<packing>
<property name="tab_expand">False</property>
<property name="tab_fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="label" translatable="yes">Header</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">tab</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox5">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkArrow" id="arrow3">
<property name="width_request">15</property>
<property name="visible">True</property>
<property name="arrow_type">GTK_ARROW_LEFT</property>
<property name="shadow_type">GTK_SHADOW_OUT</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<signal name="button_press_event" handler="on_arrow3_button_press_event" last_modification_time="Mon, 17 Oct 2005 10:28:17 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHScale" id="hscale1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="draw_value">False</property>
<property name="value_pos">GTK_POS_TOP</property>
<property name="digits">0</property>
<property name="update_policy">GTK_UPDATE_DISCONTINUOUS</property>
<property name="inverted">False</property>
<property name="adjustment">0 0 100 0 0 0</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkArrow" id="arrow2">
<property name="width_request">15</property>
<property name="visible">True</property>
<property name="arrow_type">GTK_ARROW_RIGHT</property>
<property name="shadow_type">GTK_SHADOW_OUT</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<signal name="button_press_event" handler="on_arrow2_button_press_event" last_modification_time="Mon, 17 Oct 2005 10:28:03 GMT"/>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
<property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTreeView" id="treeview2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">True</property>
<property name="rules_hint">False</property>
<property name="reorderable">False</property>
<property name="enable_search">True</property>
<property name="fixed_height_mode">False</property>
<property name="hover_selection">False</property>
<property name="hover_expand">False</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="tab_expand">False</property>
<property name="tab_fill">True</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="label" translatable="yes">Trace</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">tab</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="shrink">True</property>
<property name="resize">False</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox4">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="shrink">True</property>
<property name="resize">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkStatusbar" id="statusbar1">
<property name="visible">True</property>
<property name="has_resize_grip">True</property>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
-251
View File
@@ -1,251 +0,0 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkWindow" id="window1">
<property name="width_request">800</property>
<property name="height_request">600</property>
<property name="visible">True</property>
<property name="title" translatable="yes">SegyPY GUI</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<child>
<widget class="GtkTable" id="table1">
<property name="width_request">307</property>
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
<property name="n_rows">3</property>
<property name="n_columns">1</property>
<property name="homogeneous">False</property>
<property name="row_spacing">0</property>
<property name="column_spacing">0</property>
<child>
<widget class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<property name="pack_direction">GTK_PACK_DIRECTION_LTR</property>
<property name="child_pack_direction">GTK_PACK_DIRECTION_LTR</property>
<child>
<widget class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="label" translatable="yes">_File</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menuitem1_menu">
<child>
<widget class="GtkImageMenuItem" id="new1">
<property name="visible">True</property>
<property name="label">gtk-new</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_new1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="open1">
<property name="visible">True</property>
<property name="label">gtk-open</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_open1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="save1">
<property name="visible">True</property>
<property name="label">gtk-save</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_save1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="save_as1">
<property name="visible">True</property>
<property name="label">gtk-save-as</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_save_as1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="quit1">
<property name="visible">True</property>
<property name="label">gtk-quit</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_quit1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem2">
<property name="visible">True</property>
<property name="label" translatable="yes">_Edit</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menuitem2_menu">
<child>
<widget class="GtkImageMenuItem" id="cut1">
<property name="visible">True</property>
<property name="label">gtk-cut</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_cut1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="copy1">
<property name="visible">True</property>
<property name="label">gtk-copy</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_copy1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="paste1">
<property name="visible">True</property>
<property name="label">gtk-paste</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_paste1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="delete1">
<property name="visible">True</property>
<property name="label">gtk-delete</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_delete1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem3">
<property name="visible">True</property>
<property name="label" translatable="yes">_View</property>
<property name="use_underline">True</property>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem4">
<property name="visible">True</property>
<property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menuitem4_menu">
<child>
<widget class="GtkMenuItem" id="about1">
<property name="visible">True</property>
<property name="label" translatable="yes">_About</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_about1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkToolbar" id="toolbar1">
<property name="visible">True</property>
<property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
<property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
<property name="tooltips">True</property>
<property name="show_arrow">True</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">fill</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
-250
View File
@@ -1,250 +0,0 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<widget class="GtkWindow" id="window1">
<property name="width_request">800</property>
<property name="height_request">600</property>
<property name="visible">True</property>
<property name="title" translatable="yes">SegyPY GUI</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<child>
<widget class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
<property name="n_rows">3</property>
<property name="n_columns">1</property>
<property name="homogeneous">False</property>
<property name="row_spacing">0</property>
<property name="column_spacing">0</property>
<child>
<widget class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<property name="pack_direction">GTK_PACK_DIRECTION_LTR</property>
<property name="child_pack_direction">GTK_PACK_DIRECTION_LTR</property>
<child>
<widget class="GtkMenuItem" id="menuitem1">
<property name="visible">True</property>
<property name="label" translatable="yes">_File</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menuitem1_menu">
<child>
<widget class="GtkImageMenuItem" id="new1">
<property name="visible">True</property>
<property name="label">gtk-new</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_new1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="open1">
<property name="visible">True</property>
<property name="label">gtk-open</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_open1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="save1">
<property name="visible">True</property>
<property name="label">gtk-save</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_save1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="save_as1">
<property name="visible">True</property>
<property name="label">gtk-save-as</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_save_as1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
<child>
<widget class="GtkSeparatorMenuItem" id="separatormenuitem1">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="quit1">
<property name="visible">True</property>
<property name="label">gtk-quit</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_quit1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem2">
<property name="visible">True</property>
<property name="label" translatable="yes">_Edit</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menuitem2_menu">
<child>
<widget class="GtkImageMenuItem" id="cut1">
<property name="visible">True</property>
<property name="label">gtk-cut</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_cut1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="copy1">
<property name="visible">True</property>
<property name="label">gtk-copy</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_copy1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="paste1">
<property name="visible">True</property>
<property name="label">gtk-paste</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_paste1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="delete1">
<property name="visible">True</property>
<property name="label">gtk-delete</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_delete1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem3">
<property name="visible">True</property>
<property name="label" translatable="yes">_View</property>
<property name="use_underline">True</property>
</widget>
</child>
<child>
<widget class="GtkMenuItem" id="menuitem4">
<property name="visible">True</property>
<property name="label" translatable="yes">_Help</property>
<property name="use_underline">True</property>
<child>
<widget class="GtkMenu" id="menuitem4_menu">
<child>
<widget class="GtkMenuItem" id="about1">
<property name="visible">True</property>
<property name="label" translatable="yes">_About</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_about1_activate" last_modification_time="Sat, 08 Oct 2005 11:26:31 GMT"/>
</widget>
</child>
</widget>
</child>
</widget>
</child>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkToolbar" id="toolbar1">
<property name="visible">True</property>
<property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
<property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
<property name="tooltips">True</property>
<property name="show_arrow">True</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options">fill</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd">
<glade-project>
<name>Test</name>
<program_name>test</program_name>
<gnome_support>FALSE</gnome_support>
</glade-project>
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd">
<glade-project>
<name>Test</name>
<program_name>test</program_name>
<gnome_support>FALSE</gnome_support>
</glade-project>
+357
View File
@@ -0,0 +1,357 @@
from collections import Mapping, Sequence, OrderedDict
from fractions import Fraction
import repr
from util import contains_duplicates, measure_stride, minmax
class CatalogBuilder:
"""Use a catalog builder to construct optimised, immutable mappings.
A CatalogBuilder is useful when, depending on the particular keys and
values used, a more compact or efficient representation of the mapping
is possible than, say, a regular dictionary. The CatalogBuilder
accumulates values and then, once all values have been added, analyzes
the keys and values to produce an more optimized representation of the
mapping.
"""
def __init__(self, mapping=None):
"""Initialize a Catalog Builder.
Args:
mapping: An optional mapping (such as a dictionary) of items.
"""
self._catalog = []
if mapping is not None:
for key, value in mapping.items():
self.add(key, value)
def add(self, index, value):
"""Add an item.
Each index must be unique if create() is to be subsequently called successfully,
although duplicate index values will be accepted by this call without complaint.
"""
self._catalog.append((index, value))
def create(self):
"""Create a possibly more optimized representation of the mapping.
In this worst case, this method returns an object which is essentially an immutable dictionary. In the best
case, the space savings can be vast.
Returns:
A mapping, if a unique mapping from indexes to values is possible, otherwise None.
"""
# This method examines the contents of the mapping using various heuristics to come up with
# a better representation.
if len(self._catalog) < 2:
return DictionaryCatalog(self._catalog)
# In-place sort by index
self._catalog.sort(key=lambda index_value: index_value[0])
if contains_duplicates(index for index, value in self._catalog):
return None
if all(isinstance(index, Sequence) and (len(index) == 2) for index, value in self._catalog):
return self._create_catalog_2()
return self._create_catalog_1()
def _create_catalog_1(self):
"""Create a catalog for one-dimensional integer keys (i.e. scalars)
"""
index_min = self._catalog[0][0]
index_max = self._catalog[-1][0]
index_stride = measure_stride(index for index, value in self._catalog)
if index_stride is None:
# Dictionary strategy - arbitrary keys and values
return DictionaryCatalog(self._catalog)
self._catalog.sort(key=lambda index_value: index_value[1])
value_min = self._catalog[0][1]
value_max = self._catalog[-1][1]
value_stride = measure_stride(value for index, value in self._catalog)
if index_stride is not None and value_stride is None:
# Regular index - regular keys and arbitrary values
return RegularCatalog(index_min, index_max, index_stride, (value for index, value in self._catalog))
assert (index_stride is not None) and (value_stride is not None)
catalog = LinearRegularCatalog(index_min, index_max, index_stride, value_min, value_max, value_stride)
return catalog
def _create_catalog_2(self):
"""Create a catalog for two-dimensional integer keys.
Each key must be a two-element sequence.
"""
i_min, i_max = minmax(i for (i, j), value in self._catalog)
j_min, j_max = minmax(j for (i, j), value in self._catalog)
is_rm, diff = self._is_row_major(i_min, j_min, j_max)
if is_rm:
return RowMajorCatalog(i_min, i_max, j_min, j_max, diff)
def _is_row_major(self, i_min, j_min, j_max):
"""Does row major ordering predict values from keys?
Args:
i_min: The minimum i value.
j_min: The minimum j value.
j_max: The maximum j value.
Returns:
A 2-tuple containing, in the first element True if the values can
be predicted from the keys by assuming a row-major ordering,
otherwise False. If True, the second element will be a constant
offset, otherwise it can be ignored.
ordering
"""
diff = None
for (i, j), actual_value in self._catalog:
proposed_value = (i - i_min) * j_max + (j - j_min)
current_diff = actual_value - proposed_value
if diff is None:
diff = current_diff
if current_diff != diff:
return False, None
return True, diff
return DictionaryCatalog(self._catalog)
class RowMajorCatalog(Mapping):
"""A mapping which assumes a row-major ordering of a two-dimensional matrix.
This is the ordering of items in a two-dimensional matrix where in the (i, j)
key tuple the j value changes fastest when iterating through the items in order.
A RowMajorCatalog predicts the value v from the key (i, j) according to the
following formula:
v = (i - i_min) * j_max + (j - j_min) + c
for
i_min <= i <= i_max
j_min <= j <= j_max
and where c is an integer constant to allow zero- or one-based indexing.
"""
def __init__(self, i_min, i_max, j_min, j_max, c):
"""Initialize a RowMajorCatalog.
Args:
i_min (int): The minimum i value.
i_max (int): The maximum i value.
j_min (int): The minimum j value.
j_max (int): The maximum j value.
c (int): The constant offset
"""
self._i_min = i_min
self._i_max = i_max
self._j_min = j_min
self._j_max = j_max
self._c = c
@property
def i_min(self):
"""Minimum i value"""
return self._i_min
@property
def i_max(self):
"""Maximum i value"""
return self._i_max
@property
def j_min(self):
"""Minimum j value"""
return self._j_min
@property
def j_max(self):
"""Maximum j value"""
return self._j_max
def min(self):
"""Minimum (i, j) value"""
return self._i_min, self._j_min
def max(self):
"""Maximum (i, j) value"""
return self._j_min, self._j_max
def __getitem__(self, key):
i, j = key
if not (self._i_min <= i <= self._i_max) and (self._j_min <= j <= self._j_max):
raise KeyError("{!r} key {!r} out of range".format(self, key))
value = (i - self._i_min) * self._j_max + (j - self._j_min) + self._c
return value
def __contains__(self, key):
i, j = key
return (self._i_min <= i <= self._i_max) and (self._j_min <= j <= self._j_max)
def __len__(self):
return (self._i_max - self._i_min) * (self._j_max - self._j_min)
def __iter__(self):
for i in range(self._i_min, self._i_max + 1):
for j in range(self._j_min, self._j_max + 1):
yield (i, j)
def __repr__(self):
return '{}({}, {}, {}, {}, {})'.format(self.__class__.__name__,
self._i_min, self._i_max, self._j_min, self._j_max, self._c)
class DictionaryCatalog(Mapping):
"""An immutable, ordered, dictionary mapping.
"""
def __init__(self, items):
self._items = OrderedDict(items)
def __getitem__(self, key):
return self._items[key]
def __iter__(self):
return iter(self._items)
def __len__(self):
return len(self._items)
def __contains__(self, item):
return item in self._items
def __repr__(self):
return '{}({})'.format(self.__class__.__name__, repr.repr(self._items.items()))
class RegularCatalog(Mapping):
"""Mapping with keys ordered with regular spacing along the number line.
The values associated with the keys are arbitrary.
"""
def __init__(self, key_min, key_max, key_stride, values):
"""Initialize a RegularCatalog.
The catalog is initialized by provided a description of how the keys
along the number line, and an iterable series of corresponding values.
Args:
key_min: The minimum key.
key_max: The maximum key.
key_stride: The difference between successive keys.
values: An iterable series of values corresponding to the keys.
"""
key_range = key_max - key_min
if key_range % key_stride != 0:
raise ("RegularIndex key range {!r} is not a multiple of stride {!r}".format(key_stride, key_range))
self._key_min = key_min
self._key_max = key_max
self._key_stride = key_stride
self._values = list(values)
num_keys = key_range // key_stride
if num_keys != len(self._values):
raise ValueError("RegularIndex key range and values inconsistent")
def __getitem__(self, key):
if not (self._key_min <= key <= self._key_max):
raise KeyError("{!r} key {!r} out of range".format(self, key))
offset = key - self._key_min
if offset % self._key_stride != 0:
raise KeyError("{!r} does not contain key {!r}".format(self, key))
index = offset // self._key_stride
return self._values[index]
def __len__(self):
return len(self._values)
def __contains__(self, key):
return (self._key_min <= key <= self._key_max) and ((key - self._key_min) % self._key_stride == 0)
def __iter__(self):
return iter(range(self._key_min, self._key_max + 1, self._index_stride))
def __repr__(self):
return '{}({}, {}, {}, {})'.format(self.__class__.__name, self._key_min, self._key_max, self._key_stride,
repr.repr(self._values))
class LinearRegularCatalog(Mapping):
"""A mapping which assumes a linear relationship between keys and values.
This is the ordering of items in a two-dimensional matrix where in the (i, j)
key tuple the j value changes fastest when iterating through the items in order.
A LinearRegularCatalog predicts the value v from the key according to the
following formula:
v = (value_max - value_min) / (key_max - key_min) * (key - key_min) + value_min
"""
def __init__(self, key_min, key_max, key_stride, value_min, value_max, value_stride):
"""Initialize a LinearRegularCatalog.
Args:
key_min: The minimum key.
key_max: The maximum key.
key_stride: The difference between successive keys.
value_min: The minimum value.
value_max: The maximum value.
"""
key_range = key_max - key_min
if key_range % key_stride != 0:
raise ("{} key range {!r} is not a multiple of key stride {!r}".format(
self.__class__.__name__, key_stride, key_range))
self._key_min = key_min
self._key_max = key_max
self._key_stride = key_stride
value_range = value_max - value_min
if value_range % value_stride != 0:
raise ("{} value range {!r} is not a multiple of value stride {!r}".format(
self.__class__.__name__, value_stride, value_range))
self._value_min = value_min
self._value_max = value_max
self._value_stride = value_stride
num_keys = (self._key_max - self._key_min) // self._key_stride
num_values = (self._value_max - self._value_min) // self._value_stride
if num_keys != num_values:
raise ("{} inconsistent number of keys {} and values {}".format(
self.__class__.__name__, num_keys, num_values))
self._m = Fraction(self._value_max - self._value_min, self._key_max - self._key_min)
def __getitem__(self, key):
if not (self._key_min <= key <= self._key_max):
raise KeyError("{!r} key {!r} out of range".format(self, key))
offset = key - self._key_min
if offset % self._key_stride != 0:
raise KeyError("{!r} does not contain key {!r}".format(self, key))
v = self._m * (key - self._key_min) + self._value_min
assert v.denominator == 1
return v.numerator
def __len__(self):
return 1 + (self._key_max - self._key_min) // self._key_stride
def __contains__(self, key):
return (self._key_min <= key <= self._key_max) and ((key - self._key_min) % self._key_stride == 0)
def __iter__(self):
return iter(range(self._key_min, self._key_max + 1, self._key_stride))
def __repr__(self):
return '{}({}, {}, {}, {}, {}, {})'.format(self.__class__.__name__,
self._key_min, self._key_max, self._key_stride, self._value_min, self._value_max, self._value_stride)
+59
View File
@@ -0,0 +1,59 @@
DATA_SAMPLE_FORMAT = {1: 'ibm',
2: 'l',
3: 'h',
5: 'f',
8: 'b'}
# A mapping from SEG Y data types to format characters used by the struct module,
# known a 'ctypes'
CTYPES = {'l': 'l',
'long': 'l',
'int32': 'l',
'L': 'L',
'ulong': 'L',
'uint32': 'L',
'h': 'h',
'short': 'h',
'int16': 'h',
'H': 'H',
'ushort': 'H',
'uint16': 'H',
'c': 'b',
'char': 'b',
'b': 'b',
'B': 'B',
'uchar': 'B',
'f': 'f',
'float': 'f',
'ibm': 'ibm'}
# TODO This is redundant with data in the SH_def below
CTYPE_DESCRIPTION = {'ibm': 'IBM float',
'l': '32 bit signed integer',
'L': '32 bit unsigned integer',
'h': '16 bit signed integer',
'H': '16 bit unsigned integer',
'f': 'IEEE float32',
'b': '8 bit signed char',
'B': '8 bit unsigned char'}
SIZES = dict(l=4,
L=4,
h=2,
H=2,
b=1,
B=1,
f=4,
ibm=4)
def size_in_bytes(ctype):
return SIZES[ctype]
+46 -19
View File
@@ -1,22 +1,49 @@
import struct
import sys
_P24 = float(pow(2, 24))
def ibm2ieee2(ibm_float):
"""
ibm2ieee2(ibm_float)
Used by permission
(C) Secchi Angelo
with thanks to Howard Lightstone and Anton Vredegoor.
"""
dividend = float(16 ** 6)
if sys.version_info >= (3, 0):
if ibm_float == 0:
return 0.0
istic, a, b, c = struct.unpack('>BBBB', ibm_float)
if istic >= 128:
sign = -1.0
istic -= 128
else:
sign = 1.0
mant = float(a << 16) + float(b << 8) + float(c)
return sign * 16 ** (istic - 64) * (mant / dividend)
def ibm2ieee(big_endian_bytes):
"""Interpret a bytes object as a big-endian IBM float.
Args:
big_endian_bytes (bytes): A string containing at least four bytes.
Returns:
The floating point value.
"""
a, b, c, d = big_endian_bytes
if a == b == c == c == 0:
return 0.0
sign = 1 if (a & 0x80) else -1
exponent = a & 0x7f
mantissa = ((b << 16) | (c << 8) | d) / _P24
value = sign * mantissa * pow(16, exponent - 64)
return value
else:
def ibm2ieee(big_endian_bytes):
"""Interpret a byte string as a big-endian IBM float.
Args:
big_endian_bytes (str): A string containing at least four bytes.
Returns:
The floating point value.
"""
a = ord(big_endian_bytes[0])
b = ord(big_endian_bytes[1])
c = ord(big_endian_bytes[2])
d = ord(big_endian_bytes[3])
if a == b == c == c == 0:
return 0.0
sign = 1 if (a & 0x80) else -1
exponent = a & 0x7f
mantissa = ((b << 16) | (c << 8) | d) / _P24
value = sign * mantissa * pow(16, exponent - 64)
return value
-15
View File
@@ -1,15 +0,0 @@
#!/bin/sh
VERSION=0.3
DIR=segypy-$VERSION
mkdir $DIR
cp segypy.py $DIR/.
cp testsegy.py $DIR/.
cp LICENSE $DIR/.
cp README $DIR/.
zip -r $DIR.zip $DIR
tar cvfz $DIR.tgz $DIR
rm -fr $DIR
-34
View File
@@ -1,34 +0,0 @@
def image_segy(Data):
"""
imageSegy(Data)
Image segy Data
"""
import pylab
pylab.imshow(Data)
pylab.title('pymat test')
pylab.grid(True)
pylab.show()
def wiggle(Data, SH, skipt=1, maxval=8, lwidth=0.1):
"""
wiggle(Data, SH)
"""
import pylab
t = range(SH['ns'])
for i in range(0, SH['ntraces'], skipt):
trace = Data[:, i]
trace[0] = 0
trace[SH['ns'] - 1] = 0
pylab.plot(i + trace / maxval, t, color='black', linewidth=lwidth)
for a in range(len(trace)):
if trace[a] < 0:
trace[a] = 0
pylab.fill(i + Data[:, i] / maxval, t, 'k', linewidth=0)
pylab.title(SH['filename'])
pylab.grid(True)
pylab.show()
+25
View File
@@ -0,0 +1,25 @@
import os
from util import file_length
def seekable(fh):
"""Determine whether a file-like object supports seeking.
Args:
fh: The file-like-object to be tested.
Returns:
True if the file supports seeking, otherwise False.
"""
try:
return fh.seekable()
except AttributeError:
try:
pos = fh.tell()
try:
fh.seek(0, os.SEEK_END)
finally:
fh.seek(pos)
except AttributeError:
return False
return True
+383
View File
@@ -0,0 +1,383 @@
from __future__ import print_function
from portability import seekable
from util import file_length, filename_from_handle
from datatypes import DATA_SAMPLE_FORMAT, CTYPE_DESCRIPTION, CTYPES
from toolkit import (extract_revision, bytes_per_sample, read_reel_header, catalog_traces, read_binary_values,
compile_trace_header_format, TraceHeader, REEL_HEADER_NUM_BYTES, TRACE_HEADER_NUM_BYTES)
def create_reader(fh, endian='>'):
"""Create a SegYReader (or one of its subclasses) based on performing a scan of SEG Y data.
This function is the preferred method for creating SegYReader objects. It reads basic header
information and attempts to build indexes for traces, CDP numbers (for 2D surveys), and inline
and cross line co-ordinates (for 3D surveys) to facilitate subsequent random-access to traces.
Args:
fh: A file-like-object open in binary mode positioned such that the
beginning of the reel header will be the next byte to be read. For disk-based
SEG Y files, this is the beginning of the file.
endian: '>' for big-endian data (the standard and default), '<' for
little-endian (non-standard)
Returns:
A SegYReader object. Depending on the exact type of the SegYReader returned different capabilities may be
available. Inspect the returned object to determine these capabilities, or be prepared for capabilities not
defined in the SegYReader base class to be unavailable. The underlying file-like object must remain open
for the duration of use of the returned reader object. It is the caller's responsibility to close the
underlying file.
Example:
with open('my_seismic_data.sgy', 'rb') as fh:
reader = create_reader(fh)
print(reader.num_traces())
"""
if fh.encoding is not None:
raise TypeError("SegYReader must be provided with a binary mode file object")
if not seekable(fh):
raise TypeError("SegYReader must be provided with a seekable file object")
if fh.closed:
raise ValueError("SegYReader must be provided with an open file object")
num_file_bytes = file_length(fh)
if num_file_bytes < REEL_HEADER_NUM_BYTES:
raise ValueError("SEG Y file {!r} of {} bytes is too short".format(filename_from_handle(fh),
num_file_bytes))
if endian not in ('<', '>'):
raise ValueError("Unrecognised endian value {!r}".format(endian))
reel_header = read_reel_header(fh, endian)
revision = extract_revision(reel_header)
bps = bytes_per_sample(reel_header, revision)
trace_catalog, cdp_catalog, line_catalog = catalog_traces(fh, bps, endian)
if cdp_catalog is not None and line_catalog is None:
return SegYReader2D(fh, reel_header, trace_catalog, cdp_catalog, endian)
if cdp_catalog is None and line_catalog is not None:
return SegYReader3D(fh, reel_header, trace_catalog, line_catalog, endian)
return SegYReader(fh, reel_header, trace_catalog, endian)
class SegYReader(object):
"""A basic SEG Y reader.
Use to obtain read the reel header, the trace headers or trace values. Traces can be accessed
only by trace index.
"""
def __init__(self, fh, reel_header, trace_catalog, endian='>'):
"""Initialize a SegYReader around a file-like-object.
Note:
Usually a SegYReader is most easily constructed using the create_reader() function.
Args:
fh: A file-like object, which must support seeking and support binary reading.
reel_header: A dictionary containing reel header data.
trace_catalog: A mapping from zero-based trace index to the byte-offset to
individual traces within the file.
endian: '>' for big-endian data (the standard and default), '<' for
little-endian (non-standard)
"""
self._fh = fh
self._endian = endian
self._trace_header_format = compile_trace_header_format(self._endian)
self._reel_header = reel_header
self._trace_catalog = trace_catalog
self._revision = extract_revision(self._reel_header)
self._bytes_per_sample = bytes_per_sample(self._reel_header, self.revision)
def trace_indexes(self):
"""An iterator over zero-based trace indexes.
Returns:
An iterator which yields integers in the range zero to num_traces() - 1
"""
return iter(self._trace_catalog)
def num_traces(self):
"""The number of traces"""
return len(self._trace_catalog)
def read_trace(self, trace_index):
"""Read a specific trace.
Args:
trace_index: An integer in the range zero to num_traces() - 1
Returns:
A 2-tuple containing a TraceHeader as the first item and a sequence of numeric trace samples
as the second item.
Example:
first_trace_header, first_trace_samples = segy_reader.read_trace(0)
"""
if not (0 <= trace_index < self.num_traces()):
raise ValueError("Trace index out of range.")
trace_header = self.read_trace_header(trace_index)
num_samples = trace_header.ns
dsf = self._reel_header['DataSampleFormat']
ctype = DATA_SAMPLE_FORMAT[dsf]
pos = self._trace_catalog[trace_index] + TRACE_HEADER_NUM_BYTES
trace_values = read_binary_values(self._fh, pos, ctype, num_samples, self._endian)
return trace_header, trace_values
def read_trace_header(self, trace_index):
"""Read a specific trace.
Args:
trace_index: An integer in the range zero to num_traces() - 1
Returns:
A TraceHeader corresponding to the requested trace.
Example:
first_trace_header, first_trace_samples = segy_reader.read_trace(0)
"""
if not (0 <= trace_index < self.num_traces()):
raise ValueError("Trace index out of range.")
pos = self._trace_catalog[trace_index]
self._fh.seek(pos)
data = self._fh.read(TRACE_HEADER_NUM_BYTES)
trace_header = TraceHeader._make(self._trace_header_format.unpack(data))
return trace_header
@property
def dimensionality(self):
"""The spatial dimensionality of the data.
Returns:
3 for 3D seismic volumes, 2 for 2D seismic lines, 1 for a single trace, otherwise 0.
"""
return self._dimensionality()
def _dimensionality(self):
return 1 if self.num_traces() == 1 else 0
@property
def reel_header(self):
"""The reel header, sometimes known as the binary header.
Returns:
A dictionary containing data from the reel header.
"""
return self._reel_header
@property
def filename(self):
"""The filename.
Returns:
The filename if it could be determined, otherwise '<unknown>'
"""
return filename_from_handle(self._fh)
@property
def revision(self):
"""The SEG Y revision.
Returns:
Either datatypes.SEGY_REVISION_0 or datatypes.SEGY_REVISION_1
"""
return self._revision
@property
def bytes_per_sample(self):
"""The number of bytes per trace sample.
"""
return self._bytes_per_sample
@property
def data_sample_format(self):
"""The data type of the samples in machine-readable form.
Returns:
One of the values from datatypes.DATA_SAMPLE_FORMAT
"""
return DATA_SAMPLE_FORMAT[self._reel_header['DataSampleFormat']]
@property
def data_sample_format_description(self):
"""A descriptive human-readable description of the data sample format
"""
return CTYPE_DESCRIPTION[CTYPES[self.data_sample_format]]
class SegYReader3D(SegYReader):
"""A reader for 3D seismic data.
In addition to the capabilities provided by the SegYReader base class, this reader
provides an index to facilitate random access to individual traces via crossline and
inline co-ordinates.
"""
def __init__(self, fh, reel_header, trace_catalog, line_catalog, endian='>'):
"""Initialize a SegYReader3D around a file-like-object.
Note:
Usually a SegYReader is most easily constructed using the create_reader() function.
Args:
fh: A file-like object, which must support seeking and support binary reading.
reel_header: A dictionary containing reel header data.
trace_catalog: A mapping from zero-based trace indexes to the byte-offset to
individual traces within the file.
line_catalog: A mapping from (xline, inline) tuples to trace_indexes.
endian: '>' for big-endian data (the standard and default), '<' for
little-endian (non-standard)
"""
super(SegYReader3D, self).__init__(fh, reel_header, trace_catalog, endian)
self._line_catalog = line_catalog
def _dimensionality(self):
return 3
def num_inlines(self):
"""The number of distinct inlines in the survey
"""
try:
return self._line_catalog.j_max - self._line_catalog.j_min
except AttributeError:
# TODO: Memoize
return len(set(j for i, j in self._line_catalog))
def num_xlines(self):
"""The number of distinct crosslines in the survey
"""
try:
return self._line_catalog.i_max - self._line_catalog.i_min
except AttributeError:
# TODO: Memoize
return len(set(i for i, j in self._line_catalog))
def inline_xlines(self):
"""An iterator over all (xline_number, inline_number) tuples corresponding to traces.
"""
return iter(self._line_catalog)
def trace_index(self, xline, inline):
"""Obtain the trace index given an xline and a inline.
Note:
Do not assume that all combinations of crossline and inline co-ordinates are valid.
The volume may not be rectangular. Valid values can be obtained from the
inline_xlines() iterator.
Furthermore, inline and crossline numbers should not be relied upon to be zero- or one-based
indexes (although they may be).
Args:
xline: A crossline number.
inline: An inline number.
Returns:
A trace index which can be used with read_trace().
"""
return self._line_catalog[(xline, inline)]
class SegYReader2D(SegYReader):
def __init__(self, fh, reel_header, trace_catalog, cdp_catalog, endian='>'):
"""Initialize a SegYReader2D around a file-like-object.
Note:
Usually a SegYReader is most easily constructed using the create_reader() function.
Args:
fh: A file-like object, which must support seeking and support binary reading.
reel_header: A dictionary containing reel header data.
trace_catalog: A mapping from zero-based trace index to the byte-offset to
individual traces within the file.
cdp_catalog: A mapping from CDP numbers to trace_indexes.
endian: '>' for big-endian data (the standard and default), '<' for
little-endian (non-standard)
"""
super(SegYReader2D, self).__init__(fh, reel_header, trace_catalog, endian)
self._cdp_catalog = cdp_catalog
def _dimensionality(self):
return 2
def cdp_numbers(self):
"""An iterator over all cdp numbers corresponding to traces.
"""
return iter(self._cdp_catalog)
def num_cdps(self):
return len(self._cdp_catalog)
def trace_index(self, cdp_number):
"""Obtain the trace index given an xline and a inline.
Note:
Do not assume that all combinations of crossline and inline co-ordinates are valid.
The volume may not be rectangular. Valid values can be obtained from the
inline_xlines() iterator.
Furthermore, inline and crossline numbers should not be relied upon to be zero- or one-based
indexes (although they may be).
Args:
xline: A crossline number.
inline: An inline number.
Returns:
A trace index which can be used with read_trace().
"""
return self._cdp_catalog[cdp_number]
def main(argv=None):
import sys
if argv is None:
argv = sys.argv[1:]
filename = argv[0]
with open(filename, 'rb') as segy_file:
segy_reader = create_reader(segy_file)
print("Filename: ", segy_reader.filename)
print("SEG Y revision: ", segy_reader.revision)
print("Number of traces: ", segy_reader.num_traces())
print("Data format: ", segy_reader.data_sample_format_description)
print("Dimensionality: ", segy_reader.dimensionality)
try:
print("Number of CDPs: ", segy_reader.num_cdps())
except AttributeError:
pass
try:
print("Number of inlines: ", segy_reader.num_inlines())
print("Number of crosslines: ", segy_reader.num_xlines())
except AttributeError:
pass
if __name__ == '__main__':
main()
+6 -2
View File
@@ -1,15 +1,19 @@
SEGY_REVISION_0 = 0x0000
SEGY_REVISION_1 = 0x0100
SEGY_REVISION_0 = 0
SEGY_REVISION_1 = 1
VARIANTS = {SEGY_REVISION_0: SEGY_REVISION_0,
SEGY_REVISION_1: SEGY_REVISION_1,
0: SEGY_REVISION_0,
1: SEGY_REVISION_1,
100: SEGY_REVISION_1,
256: SEGY_REVISION_1}
class SegYRevisionError(Exception):
pass
def canonicalize_revision(revision):
"""Canonicalize a SEG Y revision.
-565
View File
@@ -1,565 +0,0 @@
"""
A Python module for reading/writing/manipulating
SEG-Y formatted files
segy.readSegy : Read SEGY file
segy.read_reel_header : Get SEGY header
segy.read_trace_header : Get SEGY Trace header
segy.read_all_trace_headers : Get all SEGY Trace headers
segy.getSegyTrace : Get SEGY Trace header and trace data for one trace
segy.writeSegy : Write a data to a SEGY file
segy.writeSegyStructure : Writes a segpy data structure to a SEGY file
segy.read_binary_value : Get a value from a binary string
segy.ibm2ieee : Convert IBM floats to IEEE
segy.version : The version of SegyPY
segy.verbose : Amount of verbose information to the screen
"""
#
# segpy : A Python module for reading and writing SEG-Y formatted data
#
# Forked by Robert Smallshire from the original segypy by
#
# (C) Thomas Mejer Hansen, 2005-2006
#
# with contributions from Pete Forman and Andrew Squelch 2007
from collections import namedtuple
import os
import sys
import struct
import logging
from numpy import (transpose, reshape, zeros, arange)
from revisions import canonicalize_revision
from header_definition import HEADER_DEF
from trace_header_definition import TRACE_HEADER_DEF
from ibm_float import ibm2ieee2
FORMAT = '%(asctime)-15s %(levelname)s %(message)s'
logging.basicConfig(level=logging.INFO, format=FORMAT)
logger = logging.getLogger('segpy.segypy')
version = '0.3.1'
REEL_HEADER_NUM_BYTES = 3600
TRACE_HEADER_NUM_BYTES = 240
l_char = struct.calcsize('c')
l_uchar = struct.calcsize('B')
l_float = struct.calcsize('f')
DATA_SAMPLE_FORMAT = {1: 'ibm',
2: 'l',
3: 'h',
5: 'f',
8: 'B'}
CTYPES = {'l': 'l', 'long': 'l', 'int32': 'l',
'L': 'L', 'ulong': 'L', 'uint32': 'L',
'h': 'h', 'short': 'h', 'int16': 'h',
'H': 'H', 'ushort': 'H', 'uint16': 'H',
'c': 'c', 'char': 'c',
'B': 'B', 'uchar': 'B',
'f': 'f', 'float': 'f',
'ibm': 'ibm'}
# TODO This is redundant with data in the SH_def below
CTYPE_DESCRIPTION = {'ibm': 'IBM float',
'l': '32 bit integer',
'h': '16 bit integer',
'f': 'IEEE float',
'B': '8 bit char'}
def size_in_bytes(ctype):
if ctype == 'l' and struct.calcsize(ctype) == 8:
return 4 # 64-bit issue?
return struct.calcsize(ctype) if ctype != 'ibm' else struct.calcsize('f')
def get_default_segy_header(ntraces=100, ns=100):
"""
header = getDefaultSegyHeader()
"""
# TraceSequenceLine
header = {'Job': {'pos': 3200, 'type': 'int32', 'def': 0}}
for key in HEADER_DEF:
header[key] = HEADER_DEF[key].get('def', 0)
header['ntraces'] = ntraces
header['ns'] = ns
return header
def get_default_segy_trace_headers(ntraces=100, ns=100, dt=1000):
"""
SH = getDefaultSegyTraceHeader()
"""
# INITIALIZE DICTIONARY
trace_header = {'TraceSequenceLine': {'pos': 0, 'type': 'int32'}}
for key in TRACE_HEADER_DEF:
trace_header[key] = zeros(ntraces)
for a in range(ntraces):
trace_header['TraceSequenceLine'][a] = a + 1
trace_header['TraceSequenceFile'][a] = a + 1
trace_header['FieldRecord'][a] = 1000
trace_header['TraceNumber'][a] = a + 1
trace_header['ns'][a] = ns
trace_header['dt'][a] = dt
return trace_header
def read_trace_header(f, reel_header, trace_header_name='cdp', endian='>'):
"""Read a particular trace header entry for all traces.
Args:
f: A seekable file-linke-object containing the binary SEG Y data.
reel_header: A dictionary obtained by parsing the reel-header using the read_reel_header() function. The
dictionary must contain integer values for both the 'ntraces' (number of traces) and 'ns' (number of
samples per trace) keys.
trace_header_name: The name of the entry to read from the trace header.
endian: '>' or '<' for big-endian and little-endian respectively.
Returns:
A numpy.ndarray containing the requested header entry values for each trace, in SEG Y file order.
"""
bps = get_byte_per_sample(reel_header)
# MAKE SOME LOOKUP TABLE THAT HOLDS THE LOCATION OF HEADERS
trace_header_pos = TRACE_HEADER_DEF[trace_header_name]['pos']
# TODO: Be consistent between 'type' and 'format' here.
trace_header_format = TRACE_HEADER_DEF[trace_header_name]['type']
ntraces = reel_header['ntraces']
trace_header_values = zeros(ntraces)
binary_reader = create_binary_reader(f, trace_header_format, endian)
start_pos = trace_header_pos + REEL_HEADER_NUM_BYTES
stride = reel_header['ns'] * bps + TRACE_HEADER_NUM_BYTES
end_pos = start_pos + (ntraces - 1) * stride + 1
for i, pos in enumerate(xrange(start_pos, end_pos, stride)):
trace_header_values[i] = binary_reader(pos)
return trace_header_values
def read_all_trace_headers(f, reel_header, endian='>'):
"""Read all trace headers.
Args:
f: A seekable file-linke-object containing the binary SEG Y data.
reel_header: A dictionary obtained by parsing the reel-header using the read_reel_header() function. The
dictionary must contain integer values for both the 'ntraces' (number of traces) and 'ns' (number of
samples per trace) keys.
endian: '>' or '<' for big-endian and little-endian respectively.
Returns:
A dictionary mapping string trace header names to numpy.ndarray trace header values, in SEG Y file order.
"""
trace_headers = {'filename': reel_header['filename']}
logger.debug('read_all_trace_headers : '
'trying to get all segy trace headers')
for i, key in enumerate(TRACE_HEADER_DEF):
trace_header = read_trace_header(f, reel_header, key, endian)
trace_headers[key] = trace_header
logger.info("read_all_trace_headers : {!r} {} of {} ".format(key, i, len(TRACE_HEADER_DEF)))
return trace_headers
TraceAttributeSpec = namedtuple('Record', ['name', 'pos', 'type'])
def compile_trace_header_format(endian='>'):
record_specs = sorted([TraceAttributeSpec(name, TRACE_HEADER_DEF[name]['pos'], TRACE_HEADER_DEF[name]['type']) for name in TRACE_HEADER_DEF],
key=lambda r : r.pos)
fmt = [endian]
length = 0
for record_spec in record_specs:
shortfall = length - record_spec.pos
if shortfall:
fmt.append(str(shortfall) + 'x') # Ignore bytes
length += shortfall
ctype = CTYPES[record_spec.type]
fmt.append(ctype)
length += size_in_bytes(ctype)
assert length == TRACE_HEADER_NUM_BYTES
return struct.Struct(''.join(fmt))
def file_length(f):
pos = f.tell()
f.seek(0, os.SEEK_END)
file_size = f.tell()
f.seek(pos, os.SEEK_SET)
return file_size
def _filename(f):
return f.name if hasattr(f, 'name') else '<unknown>'
def read_segy(f, endian='>'):
"""
data, header, trace_headers = read_reel_header(f)
"""
file_size = file_length(f)
logger.debug("read_segy : Length of data : {0}".format(file_size))
reel_header = read_reel_header(f, endian) # modified by A Squelch
# GET TRACE
index = REEL_HEADER_NUM_BYTES
bytes_per_sample = get_byte_per_sample(reel_header)
num_data = (file_size - REEL_HEADER_NUM_BYTES) / bytes_per_sample
data, reel_header, trace_headers = read_traces(f,
reel_header,
num_data,
bytes_per_sample,
index,
endian)
logger.debug("read_segy : Read segy data") # modified by A Squelch
return data, reel_header, trace_headers
def read_traces(f,
reel_header,
num_data,
bytes_per_sample,
index,
endian='>'): # added by A Squelch
"""Read the trace data.
values, SegyHeader, SegyTraceHeaders = read_traces(data,
reel_header,
num_data,
bytes_per_sample,
index)
"""
# Calculate number of dummy samples needed to account for Trace Headers
num_dummy_samples = TRACE_HEADER_NUM_BYTES / bytes_per_sample
logger.debug("read_traces : num_dummy_samples = " + str(num_dummy_samples))
# READ ALL SEGY TRACE HEADERS
trace_headers = read_all_trace_headers(f, reel_header, endian)
logger.info("read_traces : Reading segy data")
dsf = reel_header['DataSampleFormat']
ctype = DATA_SAMPLE_FORMAT[dsf]
description = CTYPE_DESCRIPTION[ctype]
logger.debug("read_traces : Assuming DSF = {0}, {1}".format(
dsf, description))
values, _ = read_binary_value(f, index, ctype, endian, num_data)
logger.debug("read_traces : - reshaping")
values = reshape(values,
(reel_header['ntraces'],
reel_header['ns'] + num_dummy_samples))
logger.debug("read_traces : - stripping header dummy data")
values = values[:, num_dummy_samples:
(reel_header['ns'] + num_dummy_samples)]
logger.debug("read_traces : - transposing")
values = transpose(values)
# SOMEONE NEEDS TO IMPLEMENT A NICER WAY DO DEAL WITH DSF = 8
if reel_header['DataSampleFormat'] == 8:
for i in arange(reel_header['ntraces']):
for j in arange(reel_header['ns']):
if values[i][j] > 128:
values[i][j] = values[i][j] - 256
logger.debug("read_traces : Finished reading segy data")
return values, reel_header, trace_headers
def read_reel_header(f, endian='>'):
"""
reel_header = read_reel_header(file_handle)
"""
filename = _filename(f)
reel_header = {'filename': filename}
for key in HEADER_DEF:
pos = HEADER_DEF[key]['pos']
format = HEADER_DEF[key]['type']
reel_header[key], index = read_binary_value(f, pos, format, endian)
logger.debug(str(pos) + " " +
str(format) +
" Reading " + key +
"=" + str(reel_header[key]))
# SET NUMBER OF BYTES PER DATA SAMPLE
bps = get_byte_per_sample(reel_header)
file_size = file_length(f)
ntraces = (file_size - REEL_HEADER_NUM_BYTES) / \
(reel_header['ns'] * bps + TRACE_HEADER_NUM_BYTES)
reel_header['ntraces'] = ntraces
logger.debug('read_reel_header : successfully read ' + filename)
return reel_header
def write_segy(filename, data, dt=1000, trace_header_in=None, header_in=None):
"""
write_segy(filename, data, dt)
Write SEGY
See also read_segy
(c) 2005, Thomas Mejer Hansen
MAKE OPTIONAL INPUT FOR ALL SEGYHTRACEHEADER VALUES
"""
if header_in is None:
header_in = {}
if trace_header_in is None:
trace_header_in = {}
logger.debug("write_segy : Trying to write " + filename)
shape = data.shape
ns = shape[0]
ntraces = shape[1]
print ntraces, ns
header = get_default_segy_header(ntraces, ns)
trace_header = get_default_segy_trace_headers(ntraces, ns, dt)
# Add trace_header_in, if exists...
for key in trace_header_in.keys():
print key
for a in range(ntraces):
trace_header[key] = trace_header_in[key][a]
# Add header_in, if exists...
for key in header_in.keys():
print key
header[key] = header_in[key]
write_segy_structure(filename, data, header, trace_header)
def write_segy_structure(filename,
data,
header,
trace_header,
endian='>'): # modified by A Squelch
"""
writeSegyStructure(filename, data, header, trace_header)
Write SEGY file using SegyPy data structures
See also readSegy
(c) 2005, Thomas Mejer Hansen
"""
logger.debug("writeSegyStructure : Trying to write " + filename)
f = open(filename, 'wb')
# VERBOSE INF
revision = canonicalize_revision(header['SegyFormatRevisionNumber'])
dsf = header['DataSampleFormat']
try: # block added by A Squelch
data_descriptor = HEADER_DEF['DataSampleFormat']['descr'][revision][dsf]
except KeyError:
logging.critical(" An error has occurred interpreting a SEGY binary"
"header key")
logging.critical(" Please check the Endian setting for this "
"file: {0}".format(header["filename"]))
sys.exit()
logger.debug("writeSegyStructure : SEG-Y revision = " + str(revision))
logger.debug("writeSegyStructure : DataSampleFormat = " +
str(dsf) +
"(" + data_descriptor + ")")
# WRITE SEGY HEADER
for key in HEADER_DEF.keys():
pos = HEADER_DEF[key]["pos"]
format = HEADER_DEF[key]["type"]
value = header[key]
put_value(value, f, pos, format, endian)
# SEGY TRACES
ctype = HEADER_DEF['DataSampleFormat']['datatype'][revision][dsf]
bps = HEADER_DEF['DataSampleFormat']['bps'][revision][dsf]
sizeT = TRACE_HEADER_NUM_BYTES + header['ns'] * bps
for itrace in range(header['ntraces']):
index = REEL_HEADER_NUM_BYTES + itrace * sizeT
logger.debug('Writing Trace #' +
str(itrace + 1) +
'/' + str(header['ntraces']))
# WRITE SEGY TRACE HEADER
for key in TRACE_HEADER_DEF.keys():
pos = index + TRACE_HEADER_DEF[key]['pos']
format = TRACE_HEADER_DEF[key]['type']
value = trace_header[key][itrace]
logger.debug(str(pos) + " " +
str(format) +
" Writing " + key +
"=" + str(value))
put_value(value, f, pos, format, endian)
# Write Data
cformat = endian + ctype
for s in range(header['ns']):
strVal = struct.pack(cformat, data[s, itrace])
f.seek(index +
TRACE_HEADER_NUM_BYTES +
s * struct.calcsize(cformat))
f.write(strVal)
f.close()
def put_value(value, fileid, index, ctype='l', endian='>', number=1):
"""
putValue(data, index, ctype, endian, number)
"""
ctype = CTYPES[ctype]
cformat = endian + ctype*number
logger.debug('putValue : cformat : ' + cformat + ' ctype = ' + ctype)
str_val = struct.pack(cformat, value)
fileid.seek(index)
fileid.write(str_val)
return 1
def create_binary_reader(f, ctype='l', endian='>'):
"""Create a unary callable which reads a given binary data type from a file.
"""
ctype = CTYPES[ctype]
size = size_in_bytes(ctype)
cformat = endian + ctype
def reader(index):
f.seek(index, os.SEEK_SET)
data = f.read(size)
# TODO: Check the content of data before proceeding
value = struct.unpack(cformat, data)
return value[0]
return reader
def read_binary_value(f, index, ctype='l', endian='>', number=1):
"""
read_binary_value(data, index, ctype, endian, number)
"""
ctype = CTYPES[ctype]
size = size_in_bytes(ctype)
cformat = endian + ctype * number
logger.debug('read_binary_value : cformat : ' + cformat)
index_end = index + size * number
f.seek(index, os.SEEK_SET)
data = f.read(size * number)
if ctype == 'ibm':
# ASSUME IBM FLOAT DATA
value = range(number)
for i in arange(number):
index_ibm = i * 4
value[i] = ibm2ieee2(data[index_ibm: index_ibm + 4])
# this returns an array as opposed to a tuple
else:
# TODO: Check the content of data before proceeding
value = struct.unpack(cformat, data)
if ctype == 'B':
logger.warning('read_binary_value : '
'Inefficient use of 1 byte Integer...', 1)
logger.debug('read_binary_value : ' +
'start = ' + str(index) +
' size = ' + str(size) +
' number = ' + str(number) +
' value = ' + str(value) +
' cformat = ' + str(cformat))
if number == 1:
return value[0], index_end
else:
return value, index_end
def get_byte_per_sample(header):
revision = canonicalize_revision(header["SegyFormatRevisionNumber"])
dsf = header["DataSampleFormat"]
try: # block added by A Squelch
bps = HEADER_DEF["DataSampleFormat"]["bps"][revision][dsf]
except KeyError:
# TODO: This should not be a critical failure - should just convert
# exception
logging.critical(" An error has occurred interpreting a SEGY "
"binary header key")
logging.critical("Please check the Endian setting for "
"this file: {0}".format(header["filename"]))
sys.exit()
logger.debug("getBytePerSample : bps = " + str(bps))
return bps
def main():
s = compile_trace_header_format()
pass
#filename = 'data/stack_final_scaled50_int8.sgy'
#with open(filename, 'rb') as segy:
# data, header, trace_headers = read_segy(segy)
if __name__ == '__main__':
main()
-80
View File
@@ -1,80 +0,0 @@
#!/usr/bin/env python
#
# testsegy.py
#
import segypy
def test_read(filename):
# Read Segy File
with open(filename, 'rb') as f:
return segypy.read_segy(f, filename)
def test_write(filename_out, data, sh, sth):
sh['DataSampleFormat'] = 5
sh['SegyFormatRevisionNumber'] = 100
segypy.write_segy_structure(filename_out, data, sh, sth)
segypy.wiggle(data, sh, 2, .1, .1)
f_ieee = 'data_IEEE.segy'
f_ibm = 'data_IBM_REV1.segy'
d_ieee, sh, sth = segypy.read_segy(f_ieee)
d_ibm, sh, sth = segypy.read_segy(f_ibm)
return d_ieee, d_ibm, data
def test_render(d_ieee, d_ibm, data):
import pylab
# imshow(Data)
pylab.figure(1)
pylab.imshow(d_ieee)
pylab.title('ieee')
pylab.show()
pylab.figure(2)
pylab.imshow(d_ibm)
pylab.title('IBM')
pylab.show()
pylab.figure(3)
pylab.imshow(data)
pylab.title('TEST')
pylab.show()
def parse_args():
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('filename',
help='The SEGY input file')
parser.add_argument('--output', '-o',
dest='outfile',
default='',
help='The output file (optional).')
parser.add_argument('--render_test', '-r',
dest='render_test',
action='store_true',
help='Whether to test rendering (only applies if '
'output is produced.)')
return parser.parse_args()
if __name__ == '__main__':
args = parse_args()
read_results = test_read(args.filename)
if args.outfile:
write_results = test_write(args.outfile, *read_results)
if args.render_test:
test_render(*write_results)
+261
View File
@@ -0,0 +1,261 @@
from array import array
from collections import namedtuple
import itertools
import os
import struct
from catalog import CatalogBuilder
from datatypes import CTYPES, size_in_bytes
from reel_header_definition import HEADER_DEF
from ibm_float import ibm2ieee
from revisions import canonicalize_revision
from trace_header_definition import TRACE_HEADER_DEF
REEL_HEADER_NUM_BYTES = 3600
TRACE_HEADER_NUM_BYTES = 240
def extract_revision(reel_header):
"""Obtain the SEG Y revision from the reel header.
Args:
reel_header: A dictionary containing a reel header, such as obtained
from read_reel_header()
Returns:
One of the constants revisions.SEGY_REVISION_0 or
revisions.SEGY_REVISION_1
"""
raw_revision = reel_header['SegyFormatRevisionNumber']
return canonicalize_revision(raw_revision)
def bytes_per_sample(reel_header, revision):
"""Determine the number of bytes per sample from the reel header.
Args:
reel_header: A dictionary containing a reel header, such as obtained
from read_reel_header()
revision: One of the constants revisions.SEGY_REVISION_0 or
revisions.SEGY_REVISION_1
Returns:
An integer number of bytes per sample.
"""
dsf = reel_header['DataSampleFormat']
bps = HEADER_DEF["DataSampleFormat"]["bps"][revision][dsf]
return bps
def samples_per_trace(reel_header):
"""Determine the number of samples per trace from the reel header.
Note: There is no requirement for all traces to be of the same length,
so this value should be considered indicative only, and as such is
mostly useful in the absence of other information. The actual number
of samples for a specific trace should be retrieved from individual
trace headers.
Args:
reel_header: A dictionary containing a reel header, such as obtained
from read_reel_header()
Returns:
An integer number of samples per trace
"""
return reel_header['ns']
def trace_length_bytes(reel_header, bps):
"""Determine the trace length in bytes from the reel header.
Note: There is no requirement for all traces to be of the same length,
so this value should be considered indicative only, and as such is
mostly useful in the absence of other information. The actual number
of samples for a specific trace should be retrieved from individual
trace headers.
Args:
reel_header: A dictionary containing a reel header, such as obtained
from read_reel_header()
bps: The number of bytes per sample, such as obtained from a call to
bytes_per_sample()
"""
return samples_per_trace(reel_header) * bps + TRACE_HEADER_NUM_BYTES
def read_reel_header(fh, endian='>'):
"""Read the SEG Y reel header, also known as the binary header.
Args:
fh: A file-like-object open in binary mode positioned such that the
beginning of the reel header will be the next byte to be read.
endian: '>' for big-endian data (the standard and default), '<' for
little-endian (non-standard)
"""
reel_header = {}
for key in HEADER_DEF:
pos = HEADER_DEF[key]['pos']
ctype = HEADER_DEF[key]['type']
values = tuple(read_binary_values(fh, pos, ctype, 1, endian))
reel_header[key] = values[0]
return reel_header
def catalog_traces(fh, bps, endian='>'):
"""Determine the file offsets of each trace in the SEG Y file.
Args:
fh: A file-like-object open in binary mode.
bps: The number of bytes per sample, such as obtained by a call to
bytes_per_sample()
endian: '>' for big-endian data (the standard and default), '<' for
little-endian (non-standard)
Returns:
An immutable sequence containing byte offsets to the beginning of each trace.
"""
trace_header_format = compile_trace_header_format(endian)
pos_begin = REEL_HEADER_NUM_BYTES
trace_catalog_builder = CatalogBuilder()
line_catalog = CatalogBuilder()
cdp_catalog = CatalogBuilder()
for trace_number in itertools.count():
fh.seek(pos_begin)
data = fh.read(TRACE_HEADER_NUM_BYTES)
if len(data) < TRACE_HEADER_NUM_BYTES:
break
trace_header = TraceHeader._make(trace_header_format.unpack(data))
num_samples = trace_header.ns
samples_bytes = num_samples * bps
trace_catalog_builder.add(trace_number, pos_begin)
# Should we check the data actually exists?
line_catalog.add((trace_header.Inline3D, trace_header.Crossline3D), trace_number)
cdp_catalog.add(trace_header.cdp, trace_number)
pos_end = pos_begin + TRACE_HEADER_NUM_BYTES + samples_bytes
pos_begin = pos_end
return (trace_catalog_builder.create(),
cdp_catalog.create(),
line_catalog.create())
def read_binary_values(fh, pos, ctype='l', count=1, endian='>'):
"""Read a series of values from a binary file.
Args:
fh: A file-like-object open in binary mode.
pos: The file offset in bytes from the beginning from which the data
is to be read.
ctype: The SEG Y data type.
number: The number of items to be read.
Returns:
A sequence containing count items.
"""
fmt = CTYPES[ctype]
item_size = size_in_bytes(fmt)
block_size = item_size * count
fh.seek(pos, os.SEEK_SET)
buf = fh.read(block_size)
if len(buf) < block_size:
raise EOFError("{} bytes requested but only {} available".format(block_size, len(buf)))
values = unpack_ibm_floats(buf, count) if fmt == 'ibm' else unpack_values(buf, count, item_size, fmt)
assert len(values) == count
return values
def unpack_ibm_floats(data, count):
"""Unpack a series of binary-encoded big-endian single-precision IBM floats.
Args:
data: A sequence of bytes. (Python 2 - a str object, Python 3 - a bytes object)
count: The number of floats to be read.
Returns:
A sequence of floats.
"""
return array('f', (ibm2ieee(data[i: i+4]) for i in range(0, count * 4, 4)))
def unpack_values(buf, count, item_size, fmt, endian='>'):
"""Unpack a series items from a byte string.
Args:
data: A sequence of bytes. (Python 2 - a str object, Python 3 - a bytes object)
count: The number of floats to be read.
fmt: A format code (one of the values in the datatype.CTYPES dictionary)
Returns:
A sequence of objects with type corresponding to the format code.
"""
c_format = '{}{}{}'.format(endian, count, fmt)
return struct.unpack(c_format, buf)
# We could use array.fromfile() here. On the one hand it's likely to be faster and more compact,
# On the other, it only works on "real" files, not arbitrary file-like-objects and it would require us
# to handle endian byte swapping ourselves.
_TraceAttributeSpec = namedtuple('Record', ['name', 'pos', 'type'])
def compile_trace_header_format(endian='>'):
"""Compile a format string for use with the struct module from the trace header definition.
Args:
endian: '>' for big-endian data (the standard and default), '<' for
little-endian (non-standard)
Returns:
A string which can be used with the struct module for parsing trace headers.
"""
record_specs = sorted([_TraceAttributeSpec(name, TRACE_HEADER_DEF[name]['pos'], TRACE_HEADER_DEF[name]['type']) for name in TRACE_HEADER_DEF],
key=lambda r : r.pos)
fmt = [endian]
length = 0
for record_spec in record_specs:
shortfall = length - record_spec.pos
if shortfall:
fmt.append(str(shortfall) + 'x') # Ignore bytes
length += shortfall
ctype = CTYPES[record_spec.type]
fmt.append(ctype)
length += size_in_bytes(ctype)
assert length == TRACE_HEADER_NUM_BYTES
return struct.Struct(''.join(fmt))
def _compile_trace_header_record():
"""Build a TraceHeader namedtuple from the trace header definition"""
record_specs = sorted([_TraceAttributeSpec(name, TRACE_HEADER_DEF[name]['pos'], TRACE_HEADER_DEF[name]['type']) for name in TRACE_HEADER_DEF],
key=lambda r : r.pos)
return namedtuple('TraceHeader', (record_spec.name for record_spec in record_specs))
TraceHeader = _compile_trace_header_record()
+110
View File
@@ -0,0 +1,110 @@
import itertools
import os
def pairwise(iterable):
"""Pairwise iteration.
Args:
iterable: An iterable series.
Returns:
An iterator over 2-tuples.
"""
a, b = itertools.tee(iterable)
next(b, None)
return itertools.izip(a, b)
def contains_duplicates(sorted_iterable):
"""Determine in an iterable series contains duplicates.
Args:
sorted_iterable: Any iterable series which must be sorted in either
ascending or descending order.
Returns:
True if sorted_iterable contains duplicates, otherwise False.
"""
for a, b in pairwise(sorted_iterable):
if a == b:
return True
return False
def measure_stride(iterable):
"""Determine whether successive numeric items differ by a contant amount.
Args:
iterable: An iterable series of numeric values.
Returns:
The difference between successive values (e.g. item[1] - item[0]) if
that difference is the same between all successive pairs, otherwise
None.
"""
stride = None
for a, b in pairwise(iterable):
new_stride = b - a
if stride is None:
stride = new_stride
elif stride != new_stride:
return None
return stride
def minmax(iterable):
"""Return the minimum and maximum of an iterable series.
This function requires only a single pass over the data.
Args:
iterable: An iterable series for which to determine the minimum and
maximum values.
Returns:
A 2-tuple containing the minimum and maximum values.
"""
iterator = iter(iterable)
try:
first = next(iterator)
except StopIteration:
raise ValueError("minmax() arg is an empty iterable series")
minimum = first
maximum = first
for item in iterator:
minimum = min(minimum, item)
maximum = max(maximum, item)
return minimum, maximum
def file_length(fh):
"""Determine the length of a file-like object in bytes.
Args:
fh: A seekable file-like-object.
Returns:
An integer length in bytes.
"""
pos = fh.tell()
try:
fh.seek(0, os.SEEK_END)
return fh.tell()
finally:
fh.seek(pos, os.SEEK_SET)
def filename_from_handle(fh):
"""Determine the name of the file underlying a file-like object.
Args:
fh: A file-like object.
Returns:
A string containing the file name, or '<unknown>' if it could not
be determined.
"""
try:
return fh.name
except AttributeError:
return '<unknown>'