"""
Qt/matplotlib widget: made using matplotlib.backends.backend_qt4agg
"""
"""
qtgui/MGQTmatplotlib.py: CCP4MG Molecular Graphics Program
Copyright (C) 2011 University of York
Copyright (C) 2012 Science and Technology Facilities Council
This library is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
version 3, modified in accordance with the provisions of the
license to address the requirements of UK law.
You should have received a copy of the modified GNU Lesser General
Public License along with this library. If not, copies may be
downloaded from http://www.ccp4.ac.uk/ccp4license.php
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 Lesser General Public License for more details.
"""
import sys
import os
import math
import glob
import functools
import traceback
import copy
from PyQt4 import QtCore, QtGui
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.ticker import FuncFormatter, ScalarFormatter
from matplotlib.font_manager import FontProperties
import matplotlib.gridspec as gridspec
import matplotlib.transforms as mtransforms
import matplotlib
import numpy
from lxml import etree
from matplotlib.backends.backend_pdf import PdfPages
numpy.seterr(invalid='ignore')
import warnings
warnings.filterwarnings("ignore","'Legend' needs 'contains' method")
scaling_functions = { 'oneoversqrt' : lambda x,pos,format='%.1f': (format)%(math.pow(x,-0.5)) if x > 1e-8 else ' ' }
scaling_inverses = {scaling_functions['oneoversqrt'] : lambda x: 1/(x*x) if x*x > sys.float_info.min else sys.float_info.max }
scaling_numerical = {scaling_functions['oneoversqrt'] : lambda x,pos,format='%.1f': (format)%(math.pow(x,-0.5)) if x > sys.float_info.min else ("%e")%(sys.float_info.max) }
def getMatplotlibFontList():
db = QtGui.QFontDatabase()
warnings.filterwarnings("error","findfont: Font family")
items = []
for fname in db.families():
try:
fn = matplotlib.font_manager.findfont(str(fname.toUtf8()))
items.append(fname)
except:
pass
#print "Font",fname," not found"
fp = os.path.normpath(os.path.join(os.path.dirname(matplotlib.__file__),"mpl-data","fonts","ttf"))
for root, dirs, files in os.walk(fp):
for f in files:
id = db.addApplicationFont(os.path.join(root,f))
for family in db.applicationFontFamilies(id):
items.append(family)
# This is slow !?
#db.removeApplicationFont(id)
items = list(set(items))
items.sort(key=lambda x: str(x.toUtf8()).lower())
warnings.filterwarnings("always","findfont: Font family")
return items
def openFileToEtree(fileName=None,printout=True):
from lxml import etree
# Use this as etree.parse() seg faults on some Linux
parser = etree.XMLParser()
f = open(fileName)
s = f.read()
f.close()
tree = etree.fromstring(s, parser)
return tree
class CCP4Table:
def __str__(self):
string = ''
string = string + self.title +'\n'
string = string + str(self.graphs_list) +'\n'
string = string + str(self.headers) +'\n'
string = string + str(self.data_lines) +'\n'
return string
def __init__(self,table):
tname_start = table.find('$TABLE')+len('$TABLE')
tname_start = table[tname_start:].find(':')+tname_start+1
tname_end = table[tname_start:].find(':')
if table[tname_start:].find('\n') < tname_end:
tname_end= table[tname_start:].find('\n')
self.title = table[tname_start:tname_end+tname_start].strip()
rest = table[tname_end+tname_start:]
self.graphs_list = []
graphs_start = rest.find('$GRAPHS')+len('$GRAPHS')
graphs_end = rest[graphs_start:].find('$$')
graphs = rest[graphs_start:graphs_end+graphs_start].strip()
colCount = 0
currentHeader = ''
for g in graphs:
if g == ':':
colCount += 1
if colCount == 4:
s,name,n,cols = currentHeader.strip().split(':')
theRange = None
if n.startswith('N'):
theRange = ((None,None),(0,None))
if not n.startswith('XD') and not n.startswith('N') and not n.startswith('A') and n.find('x')>0 and n.find('|')>0:
try:
xRange,yRange = n.split('x')
xRange = xRange.split('|')
yRange = yRange.split('|')
theRange = (float(xRange[0]),float(xRange[1])),(float(yRange[0]),float(yRange[1]))
except:
pass
self.graphs_list.append((name.strip(), cols, theRange))
colCount = 0
currentHeader = ''
else:
currentHeader += g
rest2 = rest[graphs_end+graphs_start:]
headers_start = rest2.find('$$')+2
headers_end = rest2[headers_start:].find('$$')
self.headers = rest2[headers_start:headers_end+2].replace('\n',' ').split()
rest3 = rest2[headers_end+2:]
rest3 = rest3[rest3.find('$$')+2:]
data_start = rest3.find('$$')+2
rest3 = rest3[data_start:].lstrip()
data_end = rest3.find('$$')
data_start = 0
data_lines_str = rest3[data_start:data_end].strip().split('\n')
self.data_lines = []
for line_str in data_lines_str:
vals = []
vals_str = line_str.split()
for val_str in vals_str:
try:
vals.append(float(val_str))
except:
vals.append('NA')
self.data_lines.append(vals)
self.x_scaling = False
self.y_scaling = False
self.custom_x_label = False
# This is a bit iffy. We need to check if first column of data is one of these columns need this.
if len(self.headers)>0 and (self.headers[0] == 'M(4SSQ/LL)' or self.headers[0] == '1/d^2' or self.headers[1] == '1/d^2' or self.headers[0] == '1/resol^2' or self.headers[1] == '1/resol^2'):
self.custom_x_label = u'Resolution / \xc5'
self.x_scaling = scaling_functions["oneoversqrt"]
def toEtree(self):
t = etree.Element("CCP4Table")
t.attrib["title"] = self.title
theData = etree.Element("data")
theDataText = ''
for tdl in self.data_lines:
theDataText += ''.join([("%s "%n) for n in tdl[:]]).strip() + '\n'
theData.text = theDataText
t.append(theData)
theHeaders = etree.Element("headers",separator=' ')
theHeaders.text = ''.join([("%s "%n) for n in self.headers[:]]).strip() + '\n'
t.append(theHeaders)
for g in self.graphs_list:
p = etree.Element('plot')
theTitle = etree.Element("title")
theTitle.text = g[0]
p.append(theTitle)
t.append(p)
for s in g[1].split(',')[1:]:
plotline = etree.Element('plotline', xcol=g[1].split(',')[0], ycol=s)
p.append(plotline)
return t
class LogGraphMainWindow(QtGui.QMainWindow):
def __init__(self,parent=None):
QtGui.QMainWindow.__init__(self,parent)
self.loggraph = LogGraph()
self.setCentralWidget(self.loggraph)
menu = QtGui.QMenu("File",self)
menu.addAction(self.loggraph.fileOpen)
menu.addAction(self.loggraph.fileSave)
menu.addAction(self.loggraph.fileSaveStatus)
menu.addAction(self.loggraph.fileSaveAll)
menu.addSeparator()
exitAction = menu.addAction("Quit")
exitAction.setShortcut(QtGui.QKeySequence.Quit)
self.connect(exitAction,QtCore.SIGNAL("triggered(bool)"),self.close)
self.menuBar().addMenu(menu)
editMenu = QtGui.QMenu("Edit",self)
editMenu.addAction(self.loggraph.editLegendPos)
editMenu.addAction(self.loggraph.editPlotStyle)
editMenu.addAction(self.loggraph.prefAction)
self.menuBar().addMenu(editMenu)
self.setWindowTitle("Pimple")
toolBar = self.addToolBar('')
toolBar.addAction(self.loggraph.fileOpen)
toolBar.addAction(self.loggraph.fileSave)
toolBar.addAction(self.loggraph.fileSaveStatus)
toolBar.addSeparator()
toolBar.addAction(self.loggraph.editLegendPos)
toolBar.addAction(self.loggraph.editPlotStyle)
if self.loggraph.icons_missing:
toolBar.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
class LogGraph(QtGui.QWidget):
linestyles = ['-','--','-.',':','.']
linestyles_alias = ['Solid','Dashed','Dash-dot','Dotted','Blank']
markers = ['o','s','d','^','>','<','p','h','*']
styles = markers + [
r'$\lambda$',
r'$\bowtie$',
r'$\circlearrowleft$',
r'$\clubsuit$',
r'$\checkmark$']
markers_alias = ['Circle','Square','Diamond','Up arrow','Right arrow','Left arrow','Pentagon','Hexagon','Star','Lambda','Bow tie','Circle arrow left','Clubs','Tick']
colors = ['b', 'g', 'r', 'c', 'm', 'y', 'k']
colors_alias = ['Blue', 'Green', 'Red', 'Cyan', 'Magenta', 'Yellow', 'Black']
axis_styles_alias = ['Linear','Log','Symmetric Log']
axis_styles = ['linear','log','symlog']
currentDataChanged = QtCore.pyqtSignal(int)
currentTableChanged = QtCore.pyqtSignal(int)
def fctocolname(self,col):
if abs(col[0]-1)<1e-5 and abs(col[1])<1e-5 and abs(col[2])<1e-5:
return 'r'
if abs(col[1]-1)<1e-5 and abs(col[0])<1e-5 and abs(col[2])<1e-5:
return 'g'
if abs(col[2]-1)<1e-5 and abs(col[0])<1e-5 and abs(col[1])<1e-5:
return 'b'
if abs(col[0]-0.75)<1e-5 and abs(col[2]-0.75)<1e-5 and abs(col[1])<1e-5:
return 'm'
if abs(col[1]-0.75)<1e-5 and abs(col[2]-0.75)<1e-5 and abs(col[0])<1e-5:
return 'c'
if abs(col[0]-0.75)<1e-5 and abs(col[1]-0.75)<1e-5 and abs(col[2])<1e-5:
return 'y'
if abs(col[0])<1e-5 and abs(col[1])<1e-5 and abs(col[2])<1e-5:
return 'k'
return 'b'
def applyPlotStyle(self,tab,plot,otherWidget):
showLegend = otherWidget.showLegend.isChecked()
if hasattr(tab.currentWidget(),"showPdf"):
showPdf = tab.currentWidget().showPdf.isChecked()
hist = self.histograms[tab.currentIndex()]['patches']
colour = self.colors[tab.currentWidget().colourStyleCombo.currentIndex()]
for p in hist:
p.set_facecolor(colour)
if len(hist)>1:
if showPdf:
hist[0].show_pdf = True
else:
hist[0].show_pdf = False
doBestFit = showPdf
normed = tab.currentWidget().normed.isChecked()
if normed and not self.histograms[tab.currentIndex()]['normed']:
label = hist[0].get_label()
ccp4_uuid = hist[0].ccp4_uuid
plot.canvas.fig.get_axes()[0].patches = []
mu = self.histograms[tab.currentIndex()]['mu']
sigma = self.histograms[tab.currentIndex()]['sigma']
maxx = self.histograms[tab.currentIndex()]['maxx']
vals = self.histograms[tab.currentIndex()]['vals']
#n, bins, patches = plot.canvas.ax.hist(vals, int(maxx), normed=1, facecolor=hist[0].get_facecolor(), label=label)
n, bins, patches = plot.canvas.hist(vals, int(maxx), normed=1, facecolor=hist[0].get_facecolor(), label=label)
self.histograms[tab.currentIndex()] = {'normed':True,'vals':vals,'maxx':maxx,'patches':patches,'bins':bins,'mu':mu, 'sigma':sigma}
hist = self.histograms[tab.currentIndex()]['patches']
hist[0].ccp4_uuid = ccp4_uuid
plot.canvas.ax[0].set_ylim(0,1)
plot.canvas.draw()
if not normed and self.histograms[tab.currentIndex()]['normed']:
label = hist[0].get_label()
ccp4_uuid = hist[0].ccp4_uuid
plot.canvas.fig.get_axes()[0].patches = []
mu = self.histograms[tab.currentIndex()]['mu']
sigma = self.histograms[tab.currentIndex()]['sigma']
maxx = self.histograms[tab.currentIndex()]['maxx']
vals = self.histograms[tab.currentIndex()]['vals']
#n, bins, patches = plot.canvas.ax.hist(vals, int(maxx), normed=0, facecolor=hist[0].get_facecolor(), label=label)
n, bins, patches = plot.canvas.hist(vals, int(maxx), normed=1, facecolor=hist[0].get_facecolor(), label=label)
self.histograms[tab.currentIndex()] = {'normed':False,'vals':vals,'maxx':maxx,'patches':patches,'bins':bins,'mu':mu, 'sigma':sigma}
hist = self.histograms[tab.currentIndex()]['patches']
hist[0].ccp4_uuid = ccp4_uuid
plot.canvas.ax[0].set_ylim(0,1.1*numpy.max(n))
lines = plot.canvas.fig.get_axes()[0].get_lines()
lines = [l for l in lines if not hasattr(l,"ignore")]
#print lines
iline = 0
l = self.histograms[tab.currentIndex()]
if True:
if doBestFit:
bins = self.histograms[tab.currentIndex()]['bins']
mu = self.histograms[tab.currentIndex()]['mu']
sigma = self.histograms[tab.currentIndex()]['sigma']
bincenters = 0.5*(bins[1:]+bins[:-1])
y = matplotlib.mlab.normpdf( bincenters, mu, sigma)
haveBestFit = False
for l2 in lines:
if l2.get_label() == hist[0].ccp4_uuid+'_matplotlib_line_of_best_fit':
haveBestFit = True
l2.set_xdata(bincenters)
l2.set_ydata(y)
break
if not haveBestFit:
plot.canvas.plot(bincenters, y, 'r--', linewidth=1,label=hist[0].ccp4_uuid+'_matplotlib_line_of_best_fit')
else:
haveBestFit = False
for l2 in lines:
if l2.get_label() == hist[0].ccp4_uuid+'_matplotlib_line_of_best_fit':
haveBestFit = True
print "Need to get rid of", l2
l2.set_xdata([])
l2.set_ydata([])
break
elif hasattr(tab.currentWidget(),"lineStyleCombo"):
linestyle = self.linestyles[tab.currentWidget().lineStyleCombo.currentIndex()]
linesize = tab.currentWidget().lineSizeSpin.value()
if str(tab.currentWidget().markerStyleCombo.currentText()) == 'None':
marker = ''
else:
marker = self.styles[tab.currentWidget().markerStyleCombo.currentIndex()]
colour = self.colors[tab.currentWidget().colourStyleCombo.currentIndex()]
markersize = tab.currentWidget().sizeSpin.value()
markeredgewidth = tab.currentWidget().markeredgewidthSpin.value()
label = str(tab.currentWidget().titleEdit.text())
plot = self.graph.currentWidget().currentWidget()
doBestFit = tab.currentWidget().bestFitCombo.currentIndex()
thisInLegend = tab.currentWidget().showLegend.isChecked()
isVisible = tab.currentWidget().showVisible.isChecked()
excludeFromLegend = []
def apply_to_lines(lines):
iline = 0
for l in lines:
if not l.get_label().endswith('_matplotlib_line_of_best_fit'):
if tab.currentIndex()-len(self.histograms) == iline:
if doBestFit:
xvals = l.get_xdata()
v = l.get_ydata()
if doBestFit == 4:
from scipy import optimize
e = lambda v,x,y: sum(((v[1]*numpy.exp(v[0]*x))-y)**2)
v0=[0.3,2.]
vmin = optimize.fmin(e, v0, args=(xvals,v), maxiter=10000, maxfun=10000)
func = lambda x,v0,v1: v1*numpy.exp(v0*x)
vec_func = numpy.vectorize(func)
#print vmin
yfit = vec_func(xvals,vmin[0],vmin[1])
else:
m = numpy.polyfit(xvals,v,doBestFit)
#print m
yfit = numpy.polyval(m,xvals)
haveBestFit = False
for l2 in lines:
if hasattr(l,"ccp4_uuid") and l2.get_label() == l.ccp4_uuid+'_matplotlib_line_of_best_fit':
haveBestFit = True
l2.set_xdata(xvals)
l2.set_ydata(yfit)
break
if not haveBestFit and hasattr(l,"ccp4_uuid"):
plot.canvas.plot(xvals,yfit,'k',label=l.ccp4_uuid+'_matplotlib_line_of_best_fit')
else:
haveBestFit = False
for l2 in lines:
if hasattr(l,"ccp4_uuid") and l2.get_label() == l.ccp4_uuid+'_matplotlib_line_of_best_fit':
haveBestFit = True
#print "Need to get rid of", l2
l2.set_xdata([])
l2.set_ydata([])
break
l.set_label(label)
l.set_marker(marker)
l.set_markersize(markersize)
l.set_linewidth(linesize)
l.set_linestyle(linestyle)
l.set_color(colour)
if not thisInLegend:
l.hide_from_legend = True
else:
l.hide_from_legend = False
if isVisible:
l.set_visible(True)
else:
l.set_visible(False)
l.set_markeredgewidth(markeredgewidth)
break
iline = iline + 1
for axes in plot.canvas.fig.get_axes():
lines = axes.get_lines()
lines = [l for l in lines if not hasattr(l,"ignore")]
apply_to_lines(lines)
plot.canvas.ax[0].set_xscale(self.axis_styles[otherWidget.x_axis_style.currentIndex()])
plot.canvas.ax[0].set_yscale(self.axis_styles[otherWidget.y_axis_style.currentIndex()])
plot.canvas.ax[0].set_xlabel(unicode(otherWidget.x_axis_label.text()))
plot.canvas.ax[0].set_ylabel(unicode(otherWidget.y_axis_label.text()))
plot.canvas.ax[0].set_title(unicode(otherWidget.plot_title.text()))
plot.canvas.xlabel = unicode(otherWidget.x_axis_label.text())
plot.canvas.ylabel = unicode(otherWidget.y_axis_label.text())
plot.canvas.title = unicode(otherWidget.plot_title.text())
xminold = plot.canvas.ax[0].get_xlim()[0]
xmaxold = plot.canvas.ax[-1].get_xlim()[1]
yminold = plot.canvas.ax[-1].get_ylim()[0]
ymaxold = plot.canvas.ax[0].get_ylim()[1]
xminstr, xmaxstr = str(otherWidget.x_axis_range.text()).split(',')
xmin = float(xminstr)
xmax = float(xmaxstr)
if plot.canvas.x_scaling and scaling_inverses.has_key(plot.canvas.x_scaling):
xmin = scaling_inverses[plot.canvas.x_scaling](xmin)
xmax = scaling_inverses[plot.canvas.x_scaling](xmax)
if abs(xmin-xminold)>1e-7 or abs(xmax-xmaxold)>1e-7:
plot.canvas.ax[0].set_xlim(xmin,plot.canvas.ax[0].get_xlim()[1])
plot.canvas.ax[-1].set_xlim(plot.canvas.ax[-1].get_xlim()[0],xmax)
plot.canvas.custom_xlim = xmin,xmax
yminstr, ymaxstr = str(otherWidget.y_axis_range.text()).split(',')
ymin = float(yminstr)
ymax = float(ymaxstr)
if plot.canvas.y_scaling and scaling_inverses.has_key(plot.canvas.y_scaling):
ymin = scaling_inverses[plot.canvas.x_scaling](ymin)
ymax = scaling_inverses[plot.canvas.x_scaling](ymax)
if abs(ymin-yminold)>1e-7 or abs(ymax-ymaxold)>1e-7:
plot.canvas.ax[0].set_ylim(plot.canvas.ax[0].get_ylim()[0],ymax)
plot.canvas.ax[-1].set_ylim(ymin,plot.canvas.ax[-1].get_ylim()[1])
plot.canvas.custom_ylim = ymin,ymax
try:
xbreak = str(otherWidget.x_axis_break.text()).split(')')
if len(xbreak)>0:
new_xbreak = []
for br in xbreak:
theBr = br.strip().lstrip('('). split(',')
if len(theBr)==2:
lo = float(theBr[0].strip())
hi = float(theBr[1].strip())
if plot.canvas.x_scaling and scaling_inverses.has_key(plot.canvas.x_scaling):
lo = scaling_inverses[plot.canvas.x_scaling](lo)
hi = scaling_inverses[plot.canvas.x_scaling](hi)
new_xbreak.append((lo,hi))
new_xbreak = tuple(new_xbreak)
if len(new_xbreak) == 0:
new_xbreak = None
else:
new_xbreak = None
except:
new_xbreak = None
print "Badly formatted x-axis breaks declaration."
print "Should be of form: (xlow,xhigh), (xlow,xhigh), (xlow,xhigh), ..."
QtGui.QMessageBox.critical(self,"Bad x-axis break","Bad x-axis break declaration.
Should be of form: (xlow,xhigh), (xlow,xhigh), (xlow,xhigh), ...")
try:
ybreak = str(otherWidget.y_axis_break.text()).split(')')
if len(ybreak)>0:
new_ybreak = []
for br in ybreak:
theBr = br.strip().lstrip('('). split(',')
if len(theBr)==2:
lo = float(theBr[0].strip())
hi = float(theBr[1].strip())
if plot.canvas.y_scaling and scaling_inverses.has_key(plot.canvas.y_scaling):
lo = scaling_inverses[plot.canvas.y_scaling](lo)
hi = scaling_inverses[plot.canvas.y_scaling](hi)
new_ybreak.append((lo,hi))
new_ybreak = tuple(new_ybreak)
if len(new_ybreak) == 0:
new_ybreak = None
else:
new_ybreak = None
except:
new_ybreak = None
print "Badly formatted y-axis breaks declaration."
print "Should be of form: (ylow,yhigh), (ylow,yhigh), (ylow,yhigh), ..."
QtGui.QMessageBox.critical(self,"Bad y-axis break","Bad y-axis break declaration.
Should be of form: (ylow,yhigh), (ylow,yhigh), (ylow,yhigh), ...")
plot.canvas.xbreak = new_xbreak
plot.canvas.ybreak = new_ybreak
plot.canvas.set_breaks(plot.canvas.xbreak,plot.canvas.ybreak)
if plot.canvas.xbreak and abs(xmin-xminold)<1e-7 or abs(xmax-xmaxold)<1e-7:
plot.canvas.ax[0].set_xlim(xmin,xmax)
plot.canvas.ax[-1].set_xlim(xmin,xmax)
if plot.canvas.ybreak and abs(ymin-yminold)<1e-7 or abs(ymax-ymaxold)<1e-7:
plot.canvas.ax[0].set_ylim(ymin,ymax)
plot.canvas.ax[-1].set_ylim(ymin,ymax)
plot.canvas.fix_aspect_ratio = otherWidget.fixedAspectRatio.isChecked()
if showLegend:
plot.canvas.legend()
else:
if plot.canvas.ax[0].get_legend():
plot.canvas.ax[0].legend_.set_visible(False)
plot.canvas.plot()
plot.canvas.draw()
plot.canvas.resizeEvent(QtGui.QResizeEvent(QtCore.QSize(plot.canvas.width(),plot.canvas.height()),QtCore.QSize(plot.canvas.width(),plot.canvas.height())))
plot.canvas.resizeEvent(QtGui.QResizeEvent(QtCore.QSize(plot.canvas.width(),plot.canvas.height()),QtCore.QSize(plot.canvas.width(),plot.canvas.height())))
def editPreferences(self):
if not hasattr(LogGraph,"matplotlibFontList"):
LogGraph.matplotlibFontList = getMatplotlibFontList()
editWidget = QtGui.QDialog(self)
layout = QtGui.QGridLayout()
label = QtGui.QLabel(self.tr("Title font"))
titleFontSel = QtGui.QComboBox()
titleFontSel.addItems(LogGraph.matplotlibFontList)
titleFontSel.setEditable(True)
layout.addWidget(label,layout.rowCount(),0)
titleSize = QtGui.QSpinBox()
titleSize.setRange(8,100)
layout.addWidget(titleSize,layout.rowCount()-1,1)
layout.addWidget(titleFontSel,layout.rowCount()-1,2)
titleItalic = QtGui.QCheckBox(self.tr("Italic"))
layout.addWidget(titleItalic,layout.rowCount()-1,3)
titleBold = QtGui.QCheckBox(self.tr("Bold"))
layout.addWidget(titleBold,layout.rowCount()-1,4)
label = QtGui.QLabel(self.tr("Axes ticker font"))
axesFontSel = QtGui.QComboBox()
axesFontSel.addItems(LogGraph.matplotlibFontList)
axesFontSel.setEditable(True)
layout.addWidget(label,layout.rowCount(),0)
axesSize = QtGui.QSpinBox()
axesSize.setRange(8,100)
layout.addWidget(axesSize,layout.rowCount()-1,1)
layout.addWidget(axesFontSel,layout.rowCount()-1,2)
axesItalic = QtGui.QCheckBox(self.tr("Italic"))
layout.addWidget(axesItalic,layout.rowCount()-1,3)
axesBold = QtGui.QCheckBox(self.tr("Bold"))
layout.addWidget(axesBold,layout.rowCount()-1,4)
label = QtGui.QLabel(self.tr("Axes label font"))
axesLabelFontSel = QtGui.QComboBox()
axesLabelFontSel.addItems(LogGraph.matplotlibFontList)
axesLabelFontSel.setEditable(True)
layout.addWidget(label,layout.rowCount(),0)
axesLabelSize = QtGui.QSpinBox()
axesLabelSize.setRange(8,100)
layout.addWidget(axesLabelSize,layout.rowCount()-1,1)
layout.addWidget(axesLabelFontSel,layout.rowCount()-1,2)
axesLabelItalic = QtGui.QCheckBox(self.tr("Italic"))
layout.addWidget(axesLabelItalic,layout.rowCount()-1,3)
axesLabelBold = QtGui.QCheckBox(self.tr("Bold"))
layout.addWidget(axesLabelBold,layout.rowCount()-1,4)
label = QtGui.QLabel(self.tr("Legend font"))
legendFontSel = QtGui.QComboBox()
legendFontSel.addItems(LogGraph.matplotlibFontList)
legendFontSel.setEditable(True)
layout.addWidget(label,layout.rowCount(),0)
legendSize = QtGui.QSpinBox()
legendSize.setRange(8,100)
layout.addWidget(legendSize,layout.rowCount()-1,1)
layout.addWidget(legendFontSel,layout.rowCount()-1,2)
legendItalic = QtGui.QCheckBox(self.tr("Italic"))
layout.addWidget(legendItalic,layout.rowCount()-1,3)
legendBold = QtGui.QCheckBox(self.tr("Bold"))
layout.addWidget(legendBold,layout.rowCount()-1,4)
dialogButtons = QtGui.QDialogButtonBox()
applyButton = dialogButtons.addButton(QtGui.QDialogButtonBox.Apply)
closeButton = dialogButtons.addButton(QtGui.QDialogButtonBox.Close)
self.connect(closeButton,QtCore.SIGNAL("clicked(bool)"),editWidget.close)
layout.addWidget(dialogButtons,layout.rowCount(),0,1,layout.columnCount())
legendFontSelParams = {'family':legendFontSel,'italic':legendItalic,'weight':legendBold,'size':legendSize}
titleFontSelParams = {'family':titleFontSel,'italic':titleItalic,'weight':titleBold,'size':titleSize}
axesFontSelParams = {'family':axesFontSel,'italic':axesItalic,'weight':axesBold,'size':axesSize}
axesLabelFontSelParams = {'family':axesLabelFontSel,'italic':axesLabelItalic,'weight':axesLabelBold,'size':axesLabelSize}
for fn,selector in ((self.legendFontSel,legendFontSelParams),(self.titleFontSel,titleFontSelParams),(self.axesFontSel,axesFontSelParams),(self.axesLabelFontSel,axesLabelFontSelParams)):
isItalic = False
if fn and fn.has_key("slant") and fn['slant'] == "italic":
selector['italic'].setChecked(True)
else:
selector['italic'].setChecked(False)
isBold = False
if fn and fn.has_key("weight") and fn['weight'] == "bold":
selector['weight'].setChecked(True)
else:
selector['weight'].setChecked(False)
if fn and fn.has_key("family"):
selector['family'].setCurrentIndex(selector['family'].findText(QtCore.QString(unicode(fn['family'],"utf-8"))))
else:
selector['family'].setCurrentIndex(selector['family'].findText(QtCore.QString(unicode('Bitstream Vera Sans',"utf-8"))))
if fn and fn.has_key("family"):
selector['size'].setValue(fn['size'])
else:
selector['size'].setValue(10)
self.connect(applyButton,QtCore.SIGNAL("clicked(bool)"),functools.partial(self.applyPreferencesFromWidget,titleFontSelParams,axesFontSelParams,axesLabelFontSelParams,legendFontSelParams))
editWidget.setLayout(layout)
editWidget.exec_()
def widgetPrefsToPrefs(self,params_in):
params = {}
if params_in.has_key('family'):
params['family'] = str(params_in['family'].currentText().toUtf8())
if params_in.has_key('size'):
params['size'] = params_in['size'].value()
if params_in.has_key('weight') and params_in['weight'].isChecked():
params['weight'] = 'bold'
else:
params['weight'] = 'normal'
if params_in.has_key('italic') and params_in['italic'].isChecked():
params['slant'] = 'italic'
else:
params['slant'] = 'normal'
return params
def applyPreferencesFromWidget(self,titleFontSel_in,axesFontSel_in,axesLabelFontSel_in,legendFontSel_in):
titleFontSel = self.widgetPrefsToPrefs(titleFontSel_in)
axesFontSel = self.widgetPrefsToPrefs(axesFontSel_in)
axesLabelFontSel = self.widgetPrefsToPrefs(axesLabelFontSel_in)
legendFontSel = self.widgetPrefsToPrefs(legendFontSel_in)
self.applyPreferences(titleFontSel,axesFontSel,axesLabelFontSel,legendFontSel)
def fontsToEtree(self):
tree = etree.Element('Fonts')
tree.append(etree.Element('titleFont'))
tree.append(etree.Element('axesTickerFont'))
tree.append(etree.Element('axesLabelFont'))
tree.append(etree.Element('legendFont'))
for p2, sel in zip(['titleFont','axesTickerFont','axesLabelFont','legendFont'],[self.titleFontSel,self.axesFontSel,self.axesLabelFontSel,self.legendFontSel]):
for p in tree.xpath(p2):
for k in ["family","size","weight","slant"]:
if sel and sel.has_key(k):
if type(sel[k]) == int:
p.set(k,str(sel[k]))
else:
p.set(k,sel[k])
else:
if p.attrib.has_key(k):
p.attrib.pop(k)
return tree
def applyPreferences(self,titleFontSel=None,axesFontSel=None,axesLabelFontSel=None,legendFontSel=None):
self.titleFontSel = titleFontSel
self.axesFontSel = axesFontSel
self.axesLabelFontSel = axesLabelFontSel
self.legendFontSel = legendFontSel
currenti = self.graph.currentIndex()
if not self.graph.currentWidget():
return
currentj = self.graph.currentWidget().currentIndex()
for i in range(self.graph.count()):
self.graph.setCurrentIndex(i)
sw = self.graph.widget(i)
for j in range(sw.count()):
sw.setCurrentIndex(j)
aplot = sw.widget(j)
if not hasattr(aplot,"canvas"):
continue
aplot.canvas.applyPreferences(titleFontSel,axesFontSel,axesLabelFontSel,legendFontSel)
self.graph.setCurrentIndex(currenti)
self.graph.currentWidget().setCurrentIndex(currentj)
def editPlotPlotStyle(self):
plot = self.graph.currentWidget().currentWidget()
lines = plot.canvas.fig.get_axes()[0].get_lines()
lines = [l for l in lines if not hasattr(l,"ignore")]
editWidget = QtGui.QDialog(self)
layout = QtGui.QVBoxLayout()
tab = QtGui.QTabWidget()
for hist in self.histograms:
if len(hist)>1:
if not hasattr(hist['patches'][0],"ccp4_uuid"):
if sys.platform != 'win32':
import uuid
uuid._uuid_generate_time = None
uuid._uuid_generate_random = None
uuid_str = uuid.uuid4().get_hex()
else:
import msilib
uuid_str = msilib.gen_uuid().strip('{').strip('}').replace('-','')
hist['patches'][0].ccp4_uuid = uuid_str
widget = QtGui.QWidget()
widgetLayout = QtGui.QGridLayout()
widget.setLayout(widgetLayout)
label = QtGui.QLabel(self.tr("Colour"))
widget.colourStyleCombo = QtGui.QComboBox()
widget.colourStyleCombo.addItems(self.colors_alias)
widget.colourStyleCombo.setCurrentIndex(self.colors.index(self.fctocolname(hist['patches'][0].get_facecolor())))
widgetLayout.addWidget(label,widgetLayout.rowCount(),0)
widgetLayout.addWidget(widget.colourStyleCombo,widgetLayout.rowCount()-1,1)
widget.showPdf = QtGui.QCheckBox()
pdfLabel = QtGui.QLabel(self.tr("Show prob. distn. function"))
widgetLayout.addWidget(pdfLabel,widgetLayout.rowCount(),0)
widgetLayout.addWidget(widget.showPdf,widgetLayout.rowCount()-1,1)
if hasattr(hist['patches'][0],"show_pdf") and hist['patches'][0].show_pdf:
widget.showPdf.setChecked(True)
else:
widget.showPdf.setChecked(False)
widget.normed = QtGui.QCheckBox()
normLabel = QtGui.QLabel(self.tr("Normalized"))
widgetLayout.addWidget(normLabel,widgetLayout.rowCount(),0)
widgetLayout.addWidget(widget.normed,widgetLayout.rowCount()-1,1)
widget.normed.setChecked(hist['normed'])
"""
# Do not know how to do this for histograms.
widget.showLegend = QtGui.QCheckBox()
legendLabel = QtGui.QLabel(self.tr("Display in legend"))
widgetLayout.addWidget(legendLabel,widgetLayout.rowCount(),0)
widgetLayout.addWidget(widget.showLegend,widgetLayout.rowCount()-1,1)
print hasattr(hist[0],"hide_from_legend")
if hasattr(hist[0],"hide_from_legend") and hist[0].hide_from_legend:
widget.showLegend.setChecked(False)
else:
widget.showLegend.setChecked(True)
"""
widgetLayout.setRowStretch(widgetLayout.rowCount(),10)
tab.addTab(widget,hist['patches'][0].get_label())
for l in lines:
if l.get_label() is not None and not l.get_label().endswith('_matplotlib_line_of_best_fit'):
if not hasattr(l,"ccp4_uuid"):
if sys.platform != 'win32':
import uuid
uuid_str = uuid.uuid4().get_hex()
else:
import msilib
uuid_str = msilib.gen_uuid().strip('{').strip('}').replace('-','')
l.ccp4_uuid = uuid_str
widget = QtGui.QWidget()
widgetLayout = QtGui.QGridLayout()
widget.setLayout(widgetLayout)
label = QtGui.QLabel(self.tr("Line style"))
widget.lineStyleCombo = QtGui.QComboBox()
widget.lineStyleCombo.addItems(self.linestyles_alias)
widget.lineStyleCombo.setCurrentIndex(self.linestyles.index(l.get_linestyle()))
widgetLayout.addWidget(label,0,0)
widgetLayout.addWidget(widget.lineStyleCombo,0,1)
label = QtGui.QLabel(self.tr("Marker"))
widget.markerStyleCombo = QtGui.QComboBox()
widget.markerStyleCombo.addItems(self.markers_alias)
widget.markerStyleCombo.addItem('None')
marker = l.get_marker()
if marker and marker != 'None':
widget.markerStyleCombo.setCurrentIndex(self.styles.index(l.get_marker()))
else:
widget.markerStyleCombo.setCurrentIndex(widget.markerStyleCombo.count()-1)
widgetLayout.addWidget(label,widgetLayout.rowCount(),0)
widgetLayout.addWidget(widget.markerStyleCombo,widgetLayout.rowCount()-1,1)
label = QtGui.QLabel(self.tr("Colour"))
widget.colourStyleCombo = QtGui.QComboBox()
widget.colourStyleCombo.addItems(self.colors_alias)
if not l.get_color() in self.colors:
try:
c1 = matplotlib.colors.ColorConverter().to_rgb(l.get_color())
for cn in self.colors:
c2 = matplotlib.colors.ColorConverter().to_rgb(cn)
if c2 == c1:
idx = self.colors.index(cn)
break
else:
self.colors.append(l.get_color())
self.colors_alias.append(l.get_color().capitalize())
widget.colourStyleCombo.addItem(l.get_color())
idx = self.colors.index(l.get_color())
except:
exc_type, exc_value,exc_tb = sys.exc_info()[:3]
sys.stderr.write(str(exc_type)+'\n')
sys.stderr.write(str(exc_value)+'\n')
idx = 0
else:
idx = self.colors.index(l.get_color())
for c in self.colors:
mplc = matplotlib.colors.ColorConverter().to_rgb(c)
p = QtGui.QPixmap(20,12)
col = QtGui.QColor()
col.setRgbF(mplc[0],mplc[1],mplc[2])
p.fill(col)
widget.colourStyleCombo.setItemIcon(self.colors.index(c),QtGui.QIcon(p))
widget.colourStyleCombo.setCurrentIndex(idx)
widgetLayout.addWidget(label,widgetLayout.rowCount(),0)
widgetLayout.addWidget(widget.colourStyleCombo,widgetLayout.rowCount()-1,1)
label = QtGui.QLabel(self.tr("Line width"))
widget.lineSizeSpin = QtGui.QDoubleSpinBox()
widget.lineSizeSpin.setValue(float(l.get_linewidth()))
widgetLayout.addWidget(label,widgetLayout.rowCount(),0)
widgetLayout.addWidget(widget.lineSizeSpin,widgetLayout.rowCount()-1,1)
label = QtGui.QLabel(self.tr("Marker size"))
widget.sizeSpin = QtGui.QSpinBox()
widget.sizeSpin.setValue(l.get_markersize())
widgetLayout.addWidget(label,widgetLayout.rowCount(),0)
widgetLayout.addWidget(widget.sizeSpin,widgetLayout.rowCount()-1,1)
label = QtGui.QLabel(self.tr("Marker edge width"))
widget.markeredgewidthSpin = QtGui.QDoubleSpinBox()
widget.markeredgewidthSpin.setValue(l.get_markeredgewidth())
widgetLayout.addWidget(label,widgetLayout.rowCount(),0)
widgetLayout.addWidget(widget.markeredgewidthSpin,widgetLayout.rowCount()-1,1)
label = QtGui.QLabel(self.tr("Title"))
widget.titleEdit = QtGui.QLineEdit()
widget.titleEdit.setText(l.get_label())
widgetLayout.addWidget(label,widgetLayout.rowCount(),0)
widgetLayout.addWidget(widget.titleEdit,widgetLayout.rowCount()-1,1)
label = QtGui.QLabel(self.tr("Line of best fit"))
widget.bestFitCombo = QtGui.QComboBox()
fitItems = ['None','Linear','Quadratic','Cubic']
try:
from scipy import optimize
fitItems.append('Exponential')
except:
pass
widget.bestFitCombo.addItems(fitItems)
widgetLayout.addWidget(label,widgetLayout.rowCount(),0)
widgetLayout.addWidget(widget.bestFitCombo,widgetLayout.rowCount()-1,1)
widget.showVisible = QtGui.QCheckBox()
visibleLabel = QtGui.QLabel(self.tr("Visible on graph"))
widgetLayout.addWidget(visibleLabel,widgetLayout.rowCount(),0)
widgetLayout.addWidget(widget.showVisible,widgetLayout.rowCount()-1,1)
widget.showLegend = QtGui.QCheckBox()
legendLabel = QtGui.QLabel(self.tr("Display in legend"))
widgetLayout.addWidget(legendLabel,widgetLayout.rowCount(),0)
widgetLayout.addWidget(widget.showLegend,widgetLayout.rowCount()-1,1)
if hasattr(l,"hide_from_legend") and l.hide_from_legend:
widget.showLegend.setChecked(False)
else:
widget.showLegend.setChecked(True)
if hasattr(l,"get_visible") and l.get_visible():
widget.showVisible.setChecked(True)
else:
widget.showVisible.setChecked(False)
tab.addTab(widget,l.get_label())
layout.addWidget(tab)
otherWidget = QtGui.QWidget()
otherLayout = QtGui.QGridLayout()
otherWidget.setLayout(otherLayout)
showLegendLabel = QtGui.QLabel(self.tr("Show legend"))
otherWidget.showLegend = QtGui.QCheckBox()
otherWidget.x_axis_style = QtGui.QComboBox()
otherWidget.y_axis_style = QtGui.QComboBox()
otherWidget.x_axis_style.addItems(self.axis_styles_alias)
otherWidget.y_axis_style.addItems(self.axis_styles_alias)
xaxisLabel = QtGui.QLabel(self.tr("x-axis type"))
yaxisLabel = QtGui.QLabel(self.tr("y-axis type"))
otherLayout.addWidget(showLegendLabel,otherLayout.rowCount(),0)
otherLayout.addWidget(otherWidget.showLegend,otherLayout.rowCount()-1,1)
otherLayout.addWidget(xaxisLabel,otherLayout.rowCount(),0)
otherLayout.addWidget(otherWidget.x_axis_style,otherLayout.rowCount()-1,1)
otherLayout.addWidget(yaxisLabel,otherLayout.rowCount(),0)
otherLayout.addWidget(otherWidget.y_axis_style,otherLayout.rowCount()-1,1)
otherWidget.x_axis_style.setCurrentIndex(self.axis_styles.index(plot.canvas.ax[0].get_xscale()))
otherWidget.y_axis_style.setCurrentIndex(self.axis_styles.index(plot.canvas.ax[0].get_yscale()))
xaxisLabelLabel = QtGui.QLabel(self.tr("x-axis label"))
yaxisLabelLabel = QtGui.QLabel(self.tr("y-axis label"))
otherWidget.x_axis_label = QtGui.QLineEdit()
otherWidget.x_axis_label.setText(plot.canvas.xlabel)
otherWidget.y_axis_label = QtGui.QLineEdit()
otherWidget.y_axis_label.setText(plot.canvas.ylabel)
plotTitleLabel = QtGui.QLabel(self.tr("Plot title"))
otherWidget.plot_title = QtGui.QLineEdit()
otherWidget.plot_title.setText(plot.canvas.title)
xRangeLabel = QtGui.QLabel(self.tr("x-axis range"))
otherWidget.x_axis_range = QtGui.QLineEdit()
xmin = plot.canvas.ax[0].get_xlim()[0]
xmax = plot.canvas.ax[-1].get_xlim()[1]
if plot.canvas.x_scaling and scaling_numerical.has_key(plot.canvas.x_scaling):
otherWidget.x_axis_range.setText("%s, %s" % (scaling_numerical[plot.canvas.x_scaling](xmin,0,"%.5f"),scaling_numerical[plot.canvas.x_scaling](xmax,0,"%.5f")))
else:
otherWidget.x_axis_range.setText("%.3f, %.3f" % (xmin,xmax))
yRangeLabel = QtGui.QLabel(self.tr("y-axis range"))
otherWidget.y_axis_range = QtGui.QLineEdit()
ymax = plot.canvas.ax[0].get_ylim()[1]
ymin = plot.canvas.ax[-1].get_ylim()[0]
if plot.canvas.y_scaling and scaling_numerical.has_key(plot.canvas.y_scaling):
otherWidget.y_axis_range.setText("%s, %s" % (scaling_numerical[plot.canvas.y_scaling](ymin,0,"%.5f"),scaling_numerical[plot.canvas.y_scaling](ymax,0,"%.5f")))
else:
otherWidget.y_axis_range.setText("%.3f, %.3f" % (ymin,ymax))
xBreakLabel = QtGui.QLabel(self.tr("x-axis breaks"))
otherWidget.x_axis_break = QtGui.QLineEdit()
xBreakText = ''
if plot.canvas.xbreak:
for b in plot.canvas.xbreak:
if plot.canvas.x_scaling and scaling_numerical.has_key(plot.canvas.x_scaling):
xBreakText += ("(%s, %s) " % (scaling_numerical[plot.canvas.x_scaling](b[0],0,"%.5f"),scaling_numerical[plot.canvas.x_scaling](b[1],0,"%.5f")))
else:
xBreakText += ("(%.3f, %.3f) " % (b[0],b[1]))
otherWidget.x_axis_break.setText(xBreakText)
yBreakLabel = QtGui.QLabel(self.tr("y-axis breaks"))
otherWidget.y_axis_break = QtGui.QLineEdit()
yBreakText = ''
if plot.canvas.ybreak:
for b in plot.canvas.ybreak:
if plot.canvas.y_scaling and scaling_numerical.has_key(plot.canvas.y_scaling):
yBreakText += ("(%s, %s) " % (scaling_numerical[plot.canvas.y_scaling](b[0],0,"%.5f"),scaling_numerical[plot.canvas.y_scaling](b[1],0,"%.5f")))
else:
yBreakText += ("(%.3f, %.3f) " % (b[0],b[1]))
otherWidget.y_axis_break.setText(yBreakText)
otherLayout.addWidget(xaxisLabelLabel,otherLayout.rowCount(),0)
otherLayout.addWidget(otherWidget.x_axis_label,otherLayout.rowCount()-1,1)
otherLayout.addWidget(yaxisLabelLabel,otherLayout.rowCount(),0)
otherLayout.addWidget(otherWidget.y_axis_label,otherLayout.rowCount()-1,1)
otherLayout.addWidget(plotTitleLabel,otherLayout.rowCount(),0)
otherLayout.addWidget(otherWidget.plot_title,otherLayout.rowCount()-1,1)
otherLayout.addWidget(xRangeLabel,otherLayout.rowCount(),0)
otherLayout.addWidget(otherWidget.x_axis_range,otherLayout.rowCount()-1,1)
otherLayout.addWidget(yRangeLabel,otherLayout.rowCount(),0)
otherLayout.addWidget(otherWidget.y_axis_range,otherLayout.rowCount()-1,1)
otherLayout.addWidget(xBreakLabel,otherLayout.rowCount(),0)
otherLayout.addWidget(otherWidget.x_axis_break,otherLayout.rowCount()-1,1)
otherLayout.addWidget(yBreakLabel,otherLayout.rowCount(),0)
otherLayout.addWidget(otherWidget.y_axis_break,otherLayout.rowCount()-1,1)
fixedAspectRatioLabel = QtGui.QLabel(self.tr("1:1 aspect"))
otherWidget.fixedAspectRatio = QtGui.QCheckBox()
if plot.canvas.fix_aspect_ratio:
otherWidget.fixedAspectRatio.setChecked(True)
else:
otherWidget.fixedAspectRatio.setChecked(False)
otherLayout.addWidget(fixedAspectRatioLabel,otherLayout.rowCount(),0)
otherLayout.addWidget(otherWidget.fixedAspectRatio,otherLayout.rowCount()-1,1)
if plot.canvas.ax[0].get_legend():
otherWidget.showLegend.setChecked(True)
else:
otherWidget.showLegend.setChecked(False)
layout.addWidget(otherWidget)
dialogButtons = QtGui.QDialogButtonBox()
applyButton = dialogButtons.addButton(QtGui.QDialogButtonBox.Apply)
closeButton = dialogButtons.addButton(QtGui.QDialogButtonBox.Close)
self.connect(closeButton,QtCore.SIGNAL("clicked(bool)"),editWidget.close)
layout.addWidget(dialogButtons)
editWidget.setLayout(layout)
self.connect(applyButton,QtCore.SIGNAL("clicked(bool)"),functools.partial(self.applyPlotStyle,tab,plot,otherWidget))
editWidget.exec_()
def editLegendPosition(self):
plot = self.graph.currentWidget().currentWidget()
plot.canvas.movingLegend = True
plot.canvas.setFocus(QtCore.Qt.OtherFocusReason)
def loadFile(self,filename='',hist=False,xsd=None,select=None):
oldCount = self.table_combo.count()
if filename.endswith('.log') or filename.endswith('.txt'):
f = open(filename)
b = f.read()
f.close()
splits = b[b.find("$TABLE"):].split("$TABLE")
newsplits = []
gs = []
#self.table_combo.blockSignals(True)
self.data_combo.blockSignals(True)
for ns in splits[1:]:
if select is None or ns in select:
ns = "$TABLE"+ns
newsplits.append(ns)
table = CCP4Table(ns)
gs.append(self.addCCP4Table(table))
#print self.table_combo.count(), oldCount
if self.table_combo.count()>0:
self.table_combo.setCurrentIndex(oldCount)
self.data_combo.setCurrentIndex(0)
self.graph.setCurrentIndex(oldCount)
self.graph.currentWidget().setCurrentIndex(0)
self.setCurrentData(0)
self.table_combo.blockSignals(False)
self.data_combo.blockSignals(False)
return gs
elif filename.endswith('.xml'):
self.data_combo.blockSignals(True)
graphs = self.addXMLCCP4TableFile(filename,xsd=xsd)
if self.table_combo.count()>0:
self.table_combo.setCurrentIndex(oldCount)
self.data_combo.setCurrentIndex(0)
self.graph.setCurrentIndex(oldCount)
self.graph.currentWidget().setCurrentIndex(0)
self.setCurrentData(0)
self.table_combo.blockSignals(False)
self.data_combo.blockSignals(False)
return graphs
elif filename.endswith('.html'):
graphs = self.addCCP4ReportFile(filename,select=select)
if self.table_combo.count()>0:
self.table_combo.setCurrentIndex(oldCount)
self.data_combo.setCurrentIndex(0)
self.graph.setCurrentIndex(oldCount)
self.graph.currentWidget().setCurrentIndex(0)
self.setCurrentData(0)
return graphs
elif filename.endswith('.surf'):
try:
ret = self.addSurfaceFile(filename)
if self.table_combo.count()>0:
self.table_combo.setCurrentIndex(oldCount)
self.data_combo.setCurrentIndex(0)
self.graph.setCurrentIndex(oldCount)
self.graph.currentWidget().setCurrentIndex(0)
return [ret]
except:
exc_type, exc_value,exc_tb = sys.exc_info()[:3]
sys.stderr.write(str(exc_type)+'\n')
sys.stderr.write(str(exc_value)+'\n')
traceback.print_tb(exc_tb)
QtGui.QMessageBox.critical(self,"File open failed","Failed to open file "+filename+ \
'\n'+str(exc_type)+'\n'+str(exc_value)+'\n')
elif filename.endswith('.agr') or filename.endswith('.xmgr'):
try:
ret = self.addGraceFile(filename)
if self.table_combo.count()>0:
self.table_combo.setCurrentIndex(oldCount)
self.data_combo.setCurrentIndex(0)
self.graph.setCurrentIndex(oldCount)
self.graph.currentWidget().setCurrentIndex(0)
return [ret]
except:
exc_type, exc_value,exc_tb = sys.exc_info()[:3]
sys.stderr.write(str(exc_type)+'\n')
sys.stderr.write(str(exc_value)+'\n')
traceback.print_tb(exc_tb)
QtGui.QMessageBox.critical(self,"File open failed","Failed to open file "+filename+\
'\n'+str(exc_type)+'\n'+str(exc_value)+'\n' )
else:
try:
ret = self.addPlainFile(filename,hist=hist)
if self.table_combo.count()>0:
self.table_combo.setCurrentIndex(oldCount)
self.data_combo.setCurrentIndex(0)
self.graph.setCurrentIndex(oldCount)
self.graph.currentWidget().setCurrentIndex(0)
return [ret]
except:
exc_type, exc_value,exc_tb = sys.exc_info()[:3]
sys.stderr.write(str(exc_type)+'\n')
sys.stderr.write(str(exc_value)+'\n')
traceback.print_tb(exc_tb)
QtGui.QMessageBox.critical(self,"File open failed","Failed to open file "+filename+\
'\n'+str(exc_type)+'\n'+str(exc_value)+'\n' )
self.statusFormat = None
def loadFileDialog(self):
filter_list = []
filter_list.append(self.tr("CCP4 log files (*.log *.html)"))
filter_list.append(self.tr("CCP4 XML log files (*.xml)"))
filter_list.append(self.tr("XMGR/Grace files (*.xmgr *.agr)"))
filter_list.append(self.tr("3D Surface (*.surf)"))
filter_list.append(self.tr("Any file (*.*)"))
loadFileDialog = QtGui.QFileDialog()
loadFileDialog.setOption(QtGui.QFileDialog.DontUseNativeDialog)
loadFileDialog.setFileMode(QtGui.QFileDialog.ExistingFile)
loadFileDialog.setAcceptMode(QtGui.QFileDialog.AcceptOpen)
if loadFileDialog.exec_():
for f in loadFileDialog.selectedFiles():
self.loadFile(str(f))
def statusAsXML(self):
status_xml = ""
header ="""\n"""
status_xml += header
NSMAP = {'xsi':"http://www.w3.org/2001/XMLSchema-instance"}
NS = NSMAP['xsi']
location_attribute = '{%s}noNamespaceSchemaLocation' % NS
tree = etree.Element("CCP4ApplicationOutput",nsmap = NSMAP,attrib={location_attribute: 'http://www.ysbl.york.ac.uk/~mcnicholas/schema/CCP4ApplicationOutput.xsd'})
tree.append(self.fontsToEtree())
for surf in self.surface_etrees:
tree.append(surf)
for i in range(self.table_combo.count()):
cw = self.graph.widget(i)
if self.table_etrees.has_key(cw):
t = str(self.table_combo.itemText(i).toUtf8())
tableTree = etree.Element('CCP4Table',title=t)
tree.append(tableTree)
for data in self.table_etrees[cw].xpath('data'):
tableTree.append(copy.deepcopy(data))
for eltype in ["headers"]:
for el in self.table_etrees[cw].xpath(eltype):
tableTree.append(copy.deepcopy(el))
for j in range(cw.count()):
cw2 = cw.widget(j)
if hasattr(cw2,"canvas"):
#print "Have a canvas, already drawn",j
el = self.table_etrees[cw].xpath('plot')[j]
if hasattr(cw2.canvas,"x_scaling") and cw2.canvas.x_scaling is scaling_functions['oneoversqrt']:
el.append(etree.Element('xscale'))
el.xpath("xscale")[0].text = 'oneoversqrt'
if hasattr(cw2.canvas,"y_scaling") and cw2.canvas.y_scaling is scaling_functions['oneoversqrt']:
el.append(etree.Element('yscale'))
el.xpath("yscale")[0].text = 'oneoversqrt'
if cw2.canvas.custom_xlim:
if not len(el.xpath("xrange")) > 0:
el.append(etree.Element('xrange'))
el.xpath("xrange")[0].set("min",str(cw2.canvas.custom_xlim[0]))
el.xpath("xrange")[0].set("max",str(cw2.canvas.custom_xlim[1]))
if cw2.canvas.custom_ylim:
for yrangeel in el.xpath("yrange"):
if not yrangeel.attrib.has_key("rightaxis"):
theEl = yrangeel
break
if yrangeel.attrib['rightaxis'] != "true" and yrangeel.attrib['rightaxis'] != "1":
theEl = yrangeel
break
else:
el.append(etree.Element('yrange'))
theEl = el.xpath("yrange")[-1]
if len(el.xpath("yrange"))==0:
el.append(etree.Element('yrange'))
theEl = el.xpath("yrange")[-1]
theEl.set("min",str(cw2.canvas.custom_ylim[0]))
theEl.set("max",str(cw2.canvas.custom_ylim[1]))
if cw2.canvas.title:
if not len(el.xpath("title")) > 0:
el.append(etree.Element('title'))
el.xpath("title")[0].text = cw2.canvas.title
if cw2.canvas.xlabel:
if not len(el.xpath("xlabel")) > 0:
el.append(etree.Element('xlabel'))
el.xpath("xlabel")[0].text = cw2.canvas.xlabel
if cw2.canvas.ylabel:
if not len(el.xpath("ylabel")) > 0:
el.append(etree.Element('ylabel'))
el.xpath("ylabel")[0].text = cw2.canvas.ylabel
if cw2.canvas.xbreak:
if not len(el.xpath("xbreaks")) > 0:
el.append(etree.Element('xbreaks'))
for node in el.xpath("xbreaks") :
for n in node:
node.remove(n)
for br in cw2.canvas.xbreak:
xmlbr = etree.Element('break')
xmlbr.set("min",str(br[0]))
xmlbr.set("max",str(br[1]))
for node in el.xpath("xbreaks") :
node.append(xmlbr)
if cw2.canvas.ybreak:
if not len(el.xpath("ybreaks")) > 0:
el.append(etree.Element('ybreaks'))
for node in el.xpath("ybreaks") :
for n in node:
node.remove(n)
for br in cw2.canvas.ybreak:
xmlbr = etree.Element('break')
xmlbr.set("min",str(br[0]))
xmlbr.set("max",str(br[1]))
for node in el.xpath("ybreaks") :
node.append(xmlbr)
if hasattr(cw2.canvas,"custom_legend_position"):
if not len(el.xpath("legendposition")) > 0:
el.append(etree.Element('legendposition'))
for node in el.xpath("legendposition") :
node.set("x",str(cw2.canvas.custom_legend_position[0]))
node.set("y",str(cw2.canvas.custom_legend_position[1]))
if cw2.canvas.ax[0].get_legend() and not cw2.canvas.ax[0].legend_.get_visible():
if not len(el.xpath("showlegend")) > 0:
el.append(etree.Element('showlegend'))
for node in el.xpath("showlegend") :
node.text = "false"
if hasattr(cw2.canvas,"fix_aspect_ratio") and cw2.canvas.fix_aspect_ratio:
print "should be saving with fixed aspect ratio"
if not len(el.xpath("fixaspectratio")) > 0:
el.append(etree.Element('fixaspectratio'))
for node in el.xpath("fixaspectratio") :
node.text = "true"
#print 'plotline length',len(el.xpath("plotline"))
for plotline in el.xpath("plotline"):
# Just do the simple lines. Histograms will be more complex.
if len(self.elementToPlotMap[plotline])==1:
if len(plotline.xpath("label")) == 0:
plotline.append(etree.Element('label'))
for node in plotline.xpath("label") :
node.text = self.elementToPlotMap[plotline][0].get_label()
if len(plotline.xpath("symbol")) == 0:
plotline.append(etree.Element('symbol'))
for node in plotline.xpath("symbol") :
node.text = self.elementToPlotMap[plotline][0].get_marker()
if len(plotline.xpath("symbolsize")) == 0:
plotline.append(etree.Element('symbolsize'))
for node in plotline.xpath("symbolsize") :
node.text = str(int(self.elementToPlotMap[plotline][0].get_markersize()))
if len(plotline.xpath("markeredgewidth")) == 0:
plotline.append(etree.Element('markeredgewidth'))
for node in plotline.xpath("markeredgewidth") :
node.text = str(int(self.elementToPlotMap[plotline][0].get_markeredgewidth()))
if len(plotline.xpath("colour")) == 0:
plotline.append(etree.Element('colour'))
for node in plotline.xpath("colour") :
node.text = self.elementToPlotMap[plotline][0].get_color()
if len(plotline.xpath("linestyle")) == 0:
plotline.append(etree.Element('linestyle'))
for node in plotline.xpath("linestyle") :
node.text = self.elementToPlotMap[plotline][0].get_linestyle()
if len(plotline.xpath("linesize")) == 0:
plotline.append(etree.Element('linesize'))
for node in plotline.xpath("linesize") :
node.text = str(int(self.elementToPlotMap[plotline][0].get_linewidth()))
if not self.elementToPlotMap[plotline][0].get_visible():
if len(plotline.xpath("visible")) == 0:
plotline.append(etree.Element('visible'))
for node in plotline.xpath("visible") :
node.text = "false"
if hasattr(self.elementToPlotMap[plotline][0],"hide_from_legend") and self.elementToPlotMap[plotline][0].hide_from_legend:
if len(plotline.xpath("showinlegend")) == 0:
plotline.append(etree.Element('showinlegend'))
for node in plotline.xpath("showinlegend") :
node.text = "false"
tableTree.append(copy.deepcopy(el))
else:
el = self.table_etrees[cw].xpath('plot')[j]
if hasattr(cw2,"_do_the_plot_"):
if hasattr(cw2._do_the_plot_,"args"):
if len(cw2._do_the_plot_.args)>0:
if hasattr(cw2._do_the_plot_.args[0],"x_scaling"):
if cw2._do_the_plot_.args[0].x_scaling is scaling_functions['oneoversqrt']:
if len(el.xpath("xscale"))==0:
el.append(etree.Element('xscale'))
el.xpath("xscale")[0].text = 'oneoversqrt'
if hasattr(cw2._do_the_plot_.args[0],"y_scaling"):
if cw2._do_the_plot_.args[0].y_scaling is scaling_functions['oneoversqrt']:
if len(el.xpath("yscale"))==0:
el.append(etree.Element('yscale'))
el.xpath("yscale")[0].text = 'oneoversqrt'
tableTree.append(copy.deepcopy(el))
status_xml += etree.tostring(tree,encoding='utf-8', pretty_print=True)
return status_xml
def saveFileDialog(self,saveAll=False,saveStatus=False):
"""
if saveStatus:
print "Saving status"
status = self.statusAsXML()
#print status; sys.stdout.flush()
return
"""
filter_list = []
if not saveAll:
filter_list.append(self.tr("Postscript (*.ps)"))
#filter_list.append(self.tr("Encapsulated Postscript (*.eps)"))
filter_list.append(self.tr("Portable Document Format (*.pdf)"))
if not saveAll:
filter_list.append(self.tr("PNG files (*.png)"))
if saveStatus:
filter_list = [self.tr("XML files (*.xml)")]
formats_py = []
if not saveAll and not saveStatus:
formats = QtGui.QImageWriter.supportedImageFormats()
for format in formats:
if str(format) != 'png':
filter_list.append(self.tr(str(format).upper()+" files (*."+str(format)+")"))
formats_py.append(str(format))
formats_py = tuple(formats_py)
saveFileDialog = QtGui.QFileDialog()
saveFileDialog.setOption(QtGui.QFileDialog.DontUseNativeDialog)
saveFileDialog.setFileMode(QtGui.QFileDialog.AnyFile)
saveFileDialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
if saveAll:
saveFileDialog.setWindowTitle('Save all figures')
elif saveStatus:
saveFileDialog.setWindowTitle('Save status')
else:
saveFileDialog.setWindowTitle('Save figure')
saveFileDialog.setNameFilters(filter_list)
if saveFileDialog.exec_():
filename = str(saveFileDialog.selectedFiles()[0])
if not filename.endswith('.xml') and not filename.endswith('.XML') and not filename.endswith('.pdf') and not filename.endswith('.PDF') and not filename.endswith('.png') and not filename.endswith('.PNG') and not filename.endswith('.ps') and not filename.endswith('.PS') and not filename.endswith(formats_py):
selectedFilter = str(saveFileDialog.selectedNameFilter())
splitFilters = selectedFilter[selectedFilter.find('(')+1:selectedFilter.find(')')].strip().split(' ')
if len(splitFilters) == 1 and splitFilters[0].startswith('*.'):
filename = filename + splitFilters[0][1:]
else:
filename = filename + 'png'
dpi = 100
if saveStatus:
print "Saving status"
status = self.statusAsXML()
f = open(filename,"w")
f.write(status)
f.close()
return
if saveAll:
pp = PdfPages(filename)
currenti = self.graph.currentIndex()
currentj = self.graph.currentWidget().currentIndex()
for i in range(self.graph.count()):
self.graph.setCurrentIndex(i)
cw = self.graph.widget(i)
for j in range(cw.count()):
cw.setCurrentIndex(j)
plot = cw.widget(j)
if hasattr(plot,"canvas"):
plot.canvas.draw()
plot.canvas.fig.savefig(pp, format='pdf')
elif hasattr(plot,"_do_the_plot_"):
newPlot = plot._do_the_plot_()
newPlot.show()
newPlot.canvas.draw()
newPlot.canvas.fig.savefig(pp, format='pdf')
pp.close()
self.graph.setCurrentIndex(currenti)
self.graph.currentWidget().setCurrentIndex(currentj)
return
plot = self.graph.currentWidget().currentWidget()
if not filename.endswith('.pdf') and not filename.endswith('.PDF') and not filename.endswith('.png') and not filename.endswith('.PNG') and not filename.endswith('.ps') and not filename.endswith('.PS'):
if filename.endswith(formats_py):
import tempfile
f = tempfile.NamedTemporaryFile(suffix=".png",prefix="ccp4mg"+str(os.getpid()))
fn = f.name
f.close()
plot.canvas.fig.savefig(fn,dpi=dpi)
im = QtGui.QImage(fn)
#print "Save ", filename
im.save(filename)
else:
print "Save ", filename
if filename.endswith('.pdf') or filename.endswith('.PDF'):
pp = PdfPages(filename)
plot.canvas.fig.savefig(pp, format='pdf')
pp.close()
else:
plot.canvas.fig.savefig(filename,dpi=dpi)
def updateStatusFormat(self):
import math
def logBase(num):
try:
l = math.log10(num)
except:
# Probably trying for log(0)
l = 0.0
if l<0:
return int(l)-1
else:
return int(l)
def format(minX,maxX):
if maxX>3 or minX<-6:
#Use scientific notation
xF = '%.3E'
elif minX < 0:
if maxX<0:
xF = '%'+str(abs(minX))+'.'+str(abs(minX))+'f'
else:
xF = '%'+str(abs(minX)+abs(maxX))+'.'+str(abs(minX))+'f'
else:
xf = '%'+str(abs(maxX))+'.0f'
return xF
try:
plot = self.graph.currentWidget().currentWidget()
#The range of axes
xr = math.fabs(plot.canvas.ax[-1].get_xlim()[1]-plot.canvas.ax[0].get_xlim()[0])
yr = math.fabs(plot.canvas.ax[-1].get_ylim()[1]-plot.canvas.ax[0].get_ylim()[0])
#The max abs value of axes
xx = max(math.fabs(plot.canvas.ax[-1].get_xlim()[1]),math.fabs(plot.canvas.ax[0].get_xlim()[0]))
yy = max(math.fabs(plot.canvas.ax[-1].get_ylim()[1]),math.fabs(plot.canvas.ax[0].get_ylim()[0]))
#print 'updateStatusFormat',xx,yy,xr,yr
maxX = logBase(xx)
minX = logBase(xr) - 3
xF = format(minX,maxX)
maxY = logBase(yy)
minY = logBase(yr) - 3
yF = format(minY,maxY)
#print 'updateStatusFormat',minX,maxX,xF,minY,maxY,yF
self.statusFormat = [ xF, yF ]
except:
self.statusFormat = [ '%12.6f', '%12.6f' ]
def updateStatusWithPickXandY(self,x_scaling,y_scaling,pos):
plot = self.graph.currentWidget().currentWidget()
if plot.canvas.movingLegend == True:
self.statusBar.showMessage(self.tr("Moving legend, press escape to cancel"))
return
if pos and type(pos)==dict and pos.has_key('x') and pos.has_key('y') and pos.has_key('label'):
name = pos['label']
if x_scaling:
x = "x = " + x_scaling(pos['x'],None,format=self.statusFormat[0])
else:
x = "x = "+self.statusFormat[0] % (pos['x'])
if y_scaling:
y = "y = " + y_scaling(pos['y'],None,format=self.statusFormat[1])
else:
y = "y = "+self.statusFormat[1] % (pos['y'])
text = name + " " + x + ", " + y
self.statusBar.showMessage(text)
def updateStatusWithXandY(self,x_scaling,y_scaling,pos):
if self.statusFormat is None: self.updateStatusFormat()
plot = self.graph.currentWidget().currentWidget()
if plot.canvas.movingLegend == True:
self.statusBar.showMessage(self.tr("Moving legend, press escape to cancel"))
return
if pos and type(pos)==tuple and len(pos)==2:
if x_scaling:
x = "x = " + x_scaling(pos[0],None,format=self.statusFormat[0])
else:
x = "x = "+self.statusFormat[0] % (pos[0])
if y_scaling:
y = "y = " + y_scaling(pos[1],None,format=self.statusFormat[1])
else:
y = "y = "+self.statusFormat[1] % (pos[1])
text = x + ", " + y
self.statusBar.showMessage(text)
def setCurrentData(self,idx):
#print 'setCurrentData', idx
#traceback.print_stack()
if idx < 0: return
#print self.table_combo.currentIndex(), idx, self.graph.currentIndex(), self.graph.count()
if not self.graph.currentWidget():
#print "returning"
return
if self.graph.currentWidget().widget(idx) and hasattr(self.graph.currentWidget().widget(idx),"_do_the_plot_"):
#print self.graph.currentWidget().widget(idx)
newWidget = self.graph.currentWidget().widget(idx)._do_the_plot_()
#print newWidget
oldWidget = self.graph.currentWidget().widget(idx)
self.graph.currentWidget().removeWidget(oldWidget)
oldWidget.close()
self.graph.currentWidget().insertWidget(idx,newWidget)
self.graph.currentWidget().setCurrentIndex(idx)
#print self.graph.currentWidget().currentWidget()
if sys.platform == "darwin":
# This is a hack to get around a(n almost certainly Qt) bug on OS X.
# The first widget on each stack seems not to get mouse focus unless
# the winfow has been resized. This does just that.
self.resize(self.width()+1,self.height())
self.repaint()
self.resize(self.width()-1,self.height())
self.repaint()
self.graph.currentWidget().currentWidget().canvas.resizeEvent(QtGui.QResizeEvent(QtCore.QSize(self.graph.currentWidget().currentWidget().canvas.width(),self.graph.currentWidget().currentWidget().canvas.height()),QtCore.QSize(self.graph.currentWidget().currentWidget().canvas.width(),self.graph.currentWidget().currentWidget().canvas.height())))
self.graph.currentWidget().currentWidget().canvas.resizeEvent(QtGui.QResizeEvent(QtCore.QSize(self.graph.currentWidget().currentWidget().canvas.width(),self.graph.currentWidget().currentWidget().canvas.height()),QtCore.QSize(self.graph.currentWidget().currentWidget().canvas.width(),self.graph.currentWidget().currentWidget().canvas.height())))
self.statusFormat=None
self.currentDataChanged.emit(idx)
def setCurrentTable(self,idx):
#print 'setCurrentTable',self.graph_lists
self.data_combo.clear()
for g in self.graph_lists[idx]:
#print "Adding", g[0]
self.data_combo.addItem(g[0])
self.comboItemsChanged()
self.data_combo.setCurrentIndex(0)
self.graph.setCurrentIndex(idx)
self.setCurrentData(0)
self.currentTableChanged.emit(idx)
def addSurfaceFromEtree(self,tree=None,graph_uuid=None):
title = tree.attrib.get('title','')
columns = int(tree.attrib.get('columns',''))
rows = int(tree.attrib.get('rows',''))
Z = []
Zi = []
theText = tree.text.split()
while theText:
while len(Zi) maxd:
maxd = float(v)
if float(v)< mind:
mind = float(v)
levels = []
diff = float(maxd-mind)
ncont = 50
step = diff/ncont
for i in range(ncont):
levels.append(mind+i*step)
graph = QtGui.QStackedWidget()
if graph_uuid != None:
graph.setObjectName(graph_uuid)
self.graph.addWidget(graph)
graph_lists = []
graph_lists.append((dataname,''))
plot = QtMatplotlibWidget(title=dataname)
plot.setDefaultSymbolSize(self.defaultSymbolSize)
self.connect(plot.canvas,QtCore.SIGNAL("MouseMoveEvent"),functools.partial(self.updateStatusWithXandY,None,None))
graph.addWidget(plot)
from pylab import cm
plot.canvas.ax[0].contour(Z,80,cmap=cm.bone,linewidths=1,origin='lower')
CS = plot.canvas.ax[0].contourf(Z,80,linestyles='dotted',origin='lower')
plot.canvas.fig.colorbar(CS)
plot.canvas._type = 'surface'
plot.canvas.ax[0].set_title(dataname)
self.graph_lists.append(graph_lists)
self.table_combo.addItem(str(dataname))
self.comboItemsChanged()
self.table_combo.setCurrentIndex(self.table_combo.count()-1)
return graph
def addGraceFile(self,filename,graph_uuid=None):
f = open(filename)
lines = f.readlines()
f.close()
ig = 0
iset = 1
vals = []
xvals = []
graph_lists = []
graph = QtGui.QStackedWidget()
if graph_uuid != None:
graph.setObjectName(graph_uuid)
self.graph.addWidget(graph)
t = etree.Element("CCP4Table")
theDataEl = etree.Element("data")
self.table_etrees[graph] = t
inGraph = False
graph_lists.append((filename+' '+str(iset),''))
p = etree.Element('plot')
theTitle = etree.Element("title")
theTitle.text = filename+' '+str(iset)
p.append(theTitle)
t.append(p)
plot = QtMatplotlibWidget(title=filename+' '+str(iset))
plot.setDefaultSymbolSize(self.defaultSymbolSize)
self.connect(plot.canvas,QtCore.SIGNAL("MouseMoveEvent"),functools.partial(self.updateStatusWithXandY,None,None))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointMoveEvent"),functools.partial(self.updateStatusWithPickXandY,None,None))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointClickEvent"),functools.partial(graph.emit,QtCore.SIGNAL("DetectPointClickEvent")))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointMoveEvent"),functools.partial(graph.emit,QtCore.SIGNAL("DetectPointMoveEvent")))
self.connect(plot.canvas,QtCore.SIGNAL("RegionSelected"),functools.partial(graph.emit,QtCore.SIGNAL("RegionSelected")))
graph.addWidget(plot)
currentLineStyle = None
currentColour = None
currentMarker = None
currentLegendString = None
currentMarkerScaling = 1
haveLegend = False
xRange = [None,None]
yRange = [None,None]
for l in lines:
if l.startswith('@') and len(l.split()) == 4 and l.split()[2] == 'type':
inGraph = True
elif l.startswith('&'):
inGraph = False
label = filename+' '+str(ig)
if currentLegendString:
label = currentLegendString
markersize = int(self.defaultSymbolSize*currentMarkerScaling)
if len(vals)>0:
if len(xvals)==len(vals):
if type(vals[0]) == list:
for j in range(len(vals[0])):
v = []
for i in range(len(xvals)):
v.append(vals[i][j])
if currentColour:
color = currentColour
else:
color = self.colors[ig % len(self.colors)]
if currentLineStyle:
style = currentLineStyle
if currentMarker:
thePlot = plot.canvas.plot(xvals,v,label=label,picker=markersize, marker=currentMarker, linestyle=style, color=color, markersize=markersize)
else:
thePlot = plot.canvas.plot(xvals,v,label=label,picker=markersize, linestyle=style, color=color, markersize=markersize)
else:
style = self.styles[ig % len(self.styles)]
thePlot = plot.canvas.plot(xvals,v,label=label,picker=markersize, marker=style, color=color, markersize=markersize)
for line in thePlot:
if not currentLegendString: line.hide_from_legend = True
ig = ig + 1
else:
if currentColour:
color = currentColour
else:
color = self.colors[ig % len(self.colors)]
if currentLineStyle:
style = currentLineStyle
if currentMarker:
thePlot = plot.canvas.plot(xvals,vals,label=label,picker=markersize, marker=currentMarker, linestyle=style, color=color, markersize=markersize)
else:
thePlot = plot.canvas.plot(xvals,vals,label=label,picker=markersize, linestyle=style, color=color, markersize=markersize)
else:
style = self.styles[ig % len(self.styles)]
thePlot = plot.canvas.plot(xvals,vals,label=label,picker=markersize, marker=style, color=color, markersize=markersize)
for line in thePlot:
if not currentLegendString: line.hide_from_legend = True
ig = ig + 1
else:
if currentColour:
color = currentColour
else:
color = self.colors[ig % len(self.colors)]
if currentLineStyle:
style = currentLineStyle
if currentMarker:
thePlot = plot.canvas.plot(vals,label=label,picker=markersize, marker=currentMarker, linestyle=style, color=color, markersize=markersize)
else:
thePlot = plot.canvas.plot(vals,label=label,picker=markersize, linestyle=style, color=color, markersize=markersize)
else:
style = self.styles[ig % len(self.styles)]
thePlot = plot.canvas.plot(vals,label=label,picker=markersize, marker=style, color=color, markersize=markersize)
for line in thePlot:
if not currentLegendString: line.hide_from_legend = True
ig = ig + 1
#print "adding plotline",label,ig,p
plotline = etree.Element('plotline',xcol=str(2*(ig-1)),ycol=str(2*(ig-1)+1))
p.append(plotline)
self.elementToPlotMap[plotline] = thePlot
vals = []
xvals = []
currentLineStyle = None
currentColour = None
currentMarker = None
currentLegendString = None
currentMarkerScaling = 1
elif inGraph and l.startswith('@'):
if len(l.split()) == 4 and l.split()[2] == 'linestyle':
lineStyle = l.split()[3]
if int(lineStyle) == 0:
currentLineStyle = '.'
currentMarker = 'o'
print "."
if int(lineStyle) == 1:
currentLineStyle = '-'
elif len(l.split()) == 5 and l.split()[2] == 'symbol' and l.split()[3] == 'size':
currentMarkerScaling = 1+float(l.split()[4])
elif len(l.split()) > 4 and l.split()[1] == 'legend' and l.split()[2] == 'string':
currentLegendString = l[l.find('"'):].strip().strip('\'"')
haveLegend = True
elif len(l.split()) == 4 and l.split()[2] == 'color':
currentColour = self.colors[int(l.split()[3])-1]
else:
print "IGNORE",l
elif inGraph:
thisVal = l.strip().split()
if len(thisVal) == 1:
vals.append(float(thisVal[0]))
elif len(thisVal) == 2:
xvals.append(float(thisVal[0]))
vals.append(float(thisVal[1]))
elif len(thisVal) > 2:
xvals.append(float(thisVal[0]))
tvals = []
for v in thisVal[1:]:
tvals.append(float(v))
vals.append(tvals)
elif l.startswith('@'):
if len(l.split()) > 2 and l.split()[1] == 'title':
title = l[l.find('title')+len('title'):].strip().strip('\'"')
plot.canvas.ax[0].set_title(title)
plot.canvas.title = title
elif len(l.split()) > 3 and l.split()[1] == 'world':
if l.split()[2] == 'xmin':
try:
xRange[0] = float(l.split()[3])
except:
xRange[0] = None
if l.split()[2] == 'xmax':
try:
xRange[1] = float(l.split()[3])
except:
xRange[1] = None
if l.split()[2] == 'ymin':
try:
yRange[0] = float(l.split()[3])
except:
yRange[0] = None
if l.split()[2] == 'ymax':
try:
yRange[1] = float(l.split()[3])
except:
yRange[1] = None
else:
print "IGNORE",l
if xRange[0] and xRange[1] and yRange[0] and yRange[1]:
plot.canvas.ax[0].set_xlim(xRange[0],xRange[1])
plot.canvas.custom_xlim = xRange[0],xRange[1]
plot.canvas.ax[0].set_ylim(yRange[0],yRange[1])
plot.canvas.custom_ylim = yRange[0],yRange[1]
if abs((xRange[1]-xRange[0])-(yRange[1]-yRange[0]))<1e-5:
plot.canvas.fix_aspect_ratio = True
plot.canvas.resizeEvent(QtGui.QResizeEvent(QtCore.QSize(plot.canvas.width(),plot.canvas.height()),QtCore.QSize(plot.canvas.width(),plot.canvas.height())))
plot.canvas.resizeEvent(QtGui.QResizeEvent(QtCore.QSize(plot.canvas.width(),plot.canvas.height()),QtCore.QSize(plot.canvas.width(),plot.canvas.height())))
#print p.xpath('plotline')
theData = []
maxXData, maxYData = 0,0
for plotline in p.xpath('plotline'):
maxXData, maxYData = len(self.elementToPlotMap[plotline][0].get_xdata()) , len(self.elementToPlotMap[plotline][0].get_ydata())
theDataStr = ''
for i,plotline in zip(range(len(p.xpath('plotline'))),p.xpath('plotline')):
theData.append(self.elementToPlotMap[plotline][0].get_xdata())
theData.append(self.elementToPlotMap[plotline][0].get_ydata())
#print theData
theData2 = map(None, *theData)
theDataText = ''
for row in theData2:
theRow = ''
for c in row:
if c !=None:
theRow += "%.6f " %c
else:
theRow += "%6s " % "-"
theDataText += theRow + '\n'
theDataEl.text = theDataText
t.append(theDataEl)
if haveLegend: plot.canvas.legend()
self.graph_lists.append(graph_lists)
self.table_combo.addItem(str(filename))
self.comboItemsChanged()
self.table_combo.setCurrentIndex(self.table_combo.count()-1)
return graph
def addPlainFile(self,filename,graph_uuid=None,hist=False):
f = open(filename)
lines = f.readlines()
f.close()
return self.addPlainData(lines,filename,graph_uuid,hist=hist)
def addPlainData(self,lines,dataname,graph_uuid=None,hist=False):
ig = 0
iset = 1
vals = []
xvals = []
graph_lists = []
graph = QtGui.QStackedWidget()
if graph_uuid != None:
graph.setObjectName(graph_uuid)
self.graph.addWidget(graph)
for l in lines:
thisVal = l.strip().split()
if len(thisVal) == 1:
vals.append(float(thisVal[0]))
elif len(thisVal) == 2:
xvals.append(float(thisVal[0]))
vals.append(float(thisVal[1]))
elif len(thisVal) > 2:
xvals.append(float(thisVal[0]))
tvals = []
for v in thisVal[1:]:
tvals.append(float(v))
vals.append(tvals)
elif len(thisVal) == 0:
if len(vals)>0:
graph_lists.append((dataname,''))
plot = QtMatplotlibWidget(title=dataname)
plot.setDefaultSymbolSize(self.defaultSymbolSize)
self.connect(plot.canvas,QtCore.SIGNAL("MouseMoveEvent"),functools.partial(self.updateStatusWithXandY,None,None))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointMoveEvent"),functools.partial(self.updateStatusWithPickXandY,None,None))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointClickEvent"),functools.partial(graph.emit,QtCore.SIGNAL("DetectPointClickEvent")))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointMoveEvent"),functools.partial(graph.emit,QtCore.SIGNAL("DetectPointMoveEvent")))
self.connect(plot.canvas,QtCore.SIGNAL("RegionSelected"),functools.partial(graph.emit,QtCore.SIGNAL("RegionSelected")))
graph.addWidget(plot)
if len(xvals)==len(vals):
if type(vals[0]) == list:
for j in range(len(vals[0])):
v = []
for i in range(len(xvals)):
v.append(vals[i][j])
color = self.colors[ig % len(self.colors)]
style = self.styles[ig % len(self.styles)]
plot.canvas.plot(xvals,v,label=dataname+' '+str(ig),picker=self.defaultSymbolSize, marker=style, color=color, markersize=self.defaultSymbolSize)
ig = ig + 1
else:
color = self.colors[ig % len(self.colors)]
style = self.styles[ig % len(self.styles)]
plot.canvas.plot(xvals,vals,label=dataname+' '+str(ig),picker=self.defaultSymbolSize, marker=style, color=color, markersize=self.defaultSymbolSize)
ig = ig + 1
else:
if hist:
color = self.colors[ig % len(self.colors)]
mu, sigma = 0,1
if len(vals)>0:
mu = numpy.mean(vals)
sigma = numpy.std(vals)
maxx = numpy.max(vals)
#n, bins, patches = plot.canvas.ax.hist(vals, int(maxx), normed=0, facecolor=color, label=dataname+' '+str(ig))
if(ig)>0:
n, bins, patches = plot.canvas.hist(vals, int(maxx), normed=0, facecolor=color, label=dataname+' '+str(ig+1))
else:
n, bins, patches = plot.canvas.hist(vals, int(maxx), normed=0, facecolor=color, label=dataname)
if len(patches)>0:
# Maybe need a Histogram class ?
self.histograms.append({'normed':False,'vals':vals,'maxx':maxx,'patches':patches,'bins':bins,'mu':mu, 'sigma':sigma})
else:
color = self.colors[ig % len(self.colors)]
style = self.styles[ig % len(self.styles)]
plot.canvas.plot(vals,label=dataname+' '+str(ig),picker=self.defaultSymbolSize, marker=style, color=color, markersize=self.defaultSymbolSize)
ig = ig + 1
vals = []
xvals = []
iset = iset + 1
ig = 0
if len(vals)>0:
if iset>0:
graph_lists.append((dataname+' '+str(iset+1),''))
else:
graph_lists.append((dataname,''))
plot = QtMatplotlibWidget(title=dataname+' '+str(iset))
plot.setDefaultSymbolSize(self.defaultSymbolSize)
self.connect(plot.canvas,QtCore.SIGNAL("MouseMoveEvent"),functools.partial(self.updateStatusWithXandY,None,None))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointMoveEvent"),functools.partial(self.updateStatusWithPickXandY,None,None))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointClickEvent"),functools.partial(graph.emit,QtCore.SIGNAL("DetectPointClickEvent")))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointMoveEvent"),functools.partial(graph.emit,QtCore.SIGNAL("DetectPointMoveEvent")))
self.connect(plot.canvas,QtCore.SIGNAL("RegionSelected"),functools.partial(graph.emit,QtCore.SIGNAL("RegionSelected")))
graph.addWidget(plot)
if len(xvals)==len(vals):
if type(vals[0]) == list:
for j in range(len(vals[0])):
v = []
for i in range(len(xvals)):
v.append(vals[i][j])
color = self.colors[ig % len(self.colors)]
style = self.styles[ig % len(self.styles)]
plot.canvas.plot(xvals,v,label=dataname+' '+str(ig),picker=self.defaultSymbolSize, marker=style, color=color, markersize=self.defaultSymbolSize)
ig = ig + 1
else:
color = self.colors[ig % len(self.colors)]
style = self.styles[ig % len(self.styles)]
plot.canvas.plot(xvals,vals,label=dataname+' '+str(ig),picker=self.defaultSymbolSize, marker=style, color=color, markersize=self.defaultSymbolSize)
else:
if hist:
color = self.colors[ig % len(self.colors)]
mu, sigma = 0,1
if len(vals)>0:
mu = numpy.mean(vals)
sigma = numpy.std(vals)
maxx = numpy.max(vals)
if(ig)>0:
n, bins, patches = plot.canvas.hist(vals, int(maxx), normed=0, facecolor=color, label=dataname+' '+str(ig+1))
else:
n, bins, patches = plot.canvas.hist(vals, int(maxx), normed=0, facecolor=color, label=dataname)
if len(patches)>0:
# Maybe need a Histogram class ?
self.histograms.append({'normed':False,'vals':vals,'maxx':maxx,'patches':patches,'bins':bins,'mu':mu, 'sigma':sigma})
else:
color = self.colors[ig % len(self.colors)]
style = self.styles[ig % len(self.styles)]
plot.canvas.plot(vals,label=dataname+' '+str(ig),picker=self.defaultSymbolSize, marker=style, color=color, markersize=self.defaultSymbolSize)
self.graph_lists.append(graph_lists)
self.table_combo.addItem(str(dataname))
self.comboItemsChanged()
self.table_combo.setCurrentIndex(self.table_combo.count()-1)
return graph
def addCCP4ReportFile(self,fname,select=None):
#print 'CCP4Table.addCCP4ReportFile',fname
from lxml import etree
try:
doc = openFileToEtree(fname)
except:
exc_type, exc_value,exc_tb = sys.exc_info()[:3]
sys.stderr.write(str(exc_type)+'\n')
sys.stderr.write(str(exc_value)+'\n')
traceback.print_tb(exc_tb)
QtGui.QMessageBox.warning(self,"Report HTML parse error","File "+fname+" does not seem to be valid HTML")
return []
graphList = []
#print 'CCP4Table.addCCP4ReportFile doc',etree.tostring(doc,pretty_print=True)
for tag in ('ccp4_data','{http://www.ccp4.ac.uk/ccp4ns}ccp4_data'):
for tableEle in doc.iter(tag = tag):
#print 'CCP4Table.addCCP4ReportFile found ccp4_data',tableEle.tag
if select is None or tableEle.get('id',None) in select:
try:
graph = self.addTableFromEtree(tableEle)
graphList.append(graph)
except:
print 'ERROR loading table',tableEle.tag
# This section deals with data coming from external XML files.
for tableEle in doc.iter(tag = "div"):
dataData = tableEle.attrib.get('data-data','')
# We allow for the bizarre situation where the string ends with .xml but is actually a div id.
if len(dataData.strip())>0 and dataData.endswith(".xml") and len(doc.findall(".//*[@id='"+dataData+"']"))==0:
fnameXML = os.path.join(os.path.dirname(fname),dataData)
try:
docXML = openFileToEtree(fnameXML)
tables = docXML.xpath('/CCP4ApplicationOutput/CCP4Table')
for t in tables:
#print CCP4Table.addCCP4ReportFile XML table',etree.tostring(doc,pretty_print=True)
graph = self.addTableFromEtree(t)
graphList.append(graph)
except:
print 'POSSIBLE ERROR loading table file',fnameXML,"."
print "This may not be a table file, in which case there is no problem."
return graphList
def addXMLCCP4TableFile(self,fname,graph_uuid=None,xsd=None):
try:
doc = openFileToEtree(fname)
except:
exc_type, exc_value,exc_tb = sys.exc_info()[:3]
sys.stderr.write(str(exc_type)+'\n')
sys.stderr.write(str(exc_value)+'\n')
traceback.print_tb(exc_tb)
QtGui.QMessageBox.warning(self,"XML parse error","File "+fname+" does not seem to be valid XML")
return []
if xsd:
xmlschema_doc = None
try:
xmlschema_doc = openFileToEtree(xsd)
except:
exc_type, exc_value,exc_tb = sys.exc_info()[:3]
sys.stderr.write(str(exc_type)+'\n')
sys.stderr.write(str(exc_value)+'\n')
traceback.print_tb(exc_tb)
QtGui.QMessageBox.warning(self,"XML validation error","File "+xsd+ " is not a valid schema")
if xmlschema_doc is not None:
try:
xmlschema = etree.XMLSchema(xmlschema_doc)
xmlschema.assertValid(doc)
print "Validated successfully against",xsd
except:
exc_type, exc_value,exc_tb = sys.exc_info()[:3]
sys.stderr.write(str(exc_type)+'\n')
sys.stderr.write(str(exc_value)+'\n')
traceback.print_tb(exc_tb)
QtGui.QMessageBox.warning(self,"XML validation error","File "+fname+ " does not conform to schema\n\n"+str(exc_type)+'\n\n'+str(exc_value))
graphs = []
surfaces = doc.xpath('/CCP4ApplicationOutput/CCP4Surface')
for surf in surfaces:
graph = self.addSurfaceFromEtree(surf)
graphs.append(graph)
self.surface_etrees.append(copy.deepcopy(surf))
tables = doc.xpath('/CCP4ApplicationOutput/CCP4Table')
for t in tables:
try:
graph = self.addTableFromEtree(t)
graphs.append(graph)
except:
exc_type, exc_value,exc_tb = sys.exc_info()[:3]
sys.stderr.write(str(exc_type)+'\n')
sys.stderr.write(str(exc_value)+'\n')
print 'ERROR loading table',t.tag
fonts = doc.xpath('/CCP4ApplicationOutput/Fonts')
def elementToDict(element):
theFont = {}
if len(element)>0:
titleFontElement = element[-1]
family = titleFontElement.attrib.get('family','')
if family:
theFont['family'] = family
size = titleFontElement.attrib.get('size',0)
if size:
theFont['size'] = int(size)
weight = titleFontElement.attrib.get('weight')
if weight:
theFont['weight'] = weight
slant = titleFontElement.attrib.get('slant')
if slant:
theFont['slant'] = slant
return theFont
titleFont = None
axesFont = None
axesLabelFont = None
legendFont = None
for font in fonts:
titleFonts = font.xpath('titleFont')
titleFont = elementToDict(titleFonts)
axesFonts = font.xpath('axesTickerFont')
axesFont = elementToDict(axesFonts)
axesLabelFonts = font.xpath('axesLabelFont')
axesLabelFont = elementToDict(axesLabelFonts)
legendFonts = font.xpath('legendFont')
legendFont = elementToDict(legendFonts)
if titleFont or axesFont or axesLabelFont or legendFont:
self.applyPreferences(titleFontSel=titleFont,axesFontSel=axesFont,axesLabelFontSel=axesLabelFont,legendFontSel=legendFont)
return graphs
def analyzeDistributionOfPoints(self,xdata,ydata,halfx,halfy):
nTopLeft = 0
nTopRight = 0
nBottomLeft = 0
nBottomRight = 0
if len(xdata) != len(ydata):
return
for i in range(len(xdata)):
if xdata[i] > halfx:
if ydata[i]> halfy:
nTopRight += 1
else:
nBottomRight += 1
else:
if ydata[i]> halfy:
nTopLeft += 1
else:
nBottomLeft += 1
return nTopLeft, nTopRight, nBottomLeft, nBottomRight
def getDataArray(self,t,theId):
for data in t.xpath('data'):
if data.attrib.get('id',None) == theId:
a = data.text.strip().split()
a2 = []
for i in a:
j = i.replace("NA","Nan")
if j == "*" or j=="-":
j = "NaN"
a2.append(j)
array1 = numpy.array(a2,dtype=float)
array2 = numpy.array_split(array1,len(array1)/len(t.xpath('headers')[0].text.strip().split()))
array = numpy.array(array2)
return array
def addTableFromEtreeAndSetVisible(self,table):
oldCount = self.table_combo.count()
self.data_combo.blockSignals(True)
graphs = []
graph = self.addTableFromEtree(table)
graphs.append(graph)
self.table_combo.setCurrentIndex(oldCount)
self.data_combo.setCurrentIndex(0)
self.graph.setCurrentIndex(oldCount)
self.graph.currentWidget().setCurrentIndex(0)
self.setCurrentData(0)
self.table_combo.blockSignals(False)
self.data_combo.blockSignals(False)
return graphs
def addTableFromDataIslandDivs(self,tree=None):
print "addTableFromEtree"; sys.stdout.flush()
print "addTableFromEtree",tree; sys.stdout.flush()
print etree.tostring(t,pretty_print=True)
def addTableFromEtree(self,tree=None):
t = tree
ttitle = t.attrib.get('title','').strip()
data = t.xpath('data')[0]
a = data.text.strip().split()
a2 = []
for i in a:
j = i.replace("NA","Nan")
if j == "*" or j=="-":
j = "NaN"
a2.append(j)
array1 = numpy.array(a2,dtype=float)
array2 = numpy.array_split(array1,len(array1)/len(t.xpath('headers')[0].text.strip().split()))
theFirstArray = numpy.array(array2)
graph_lists = []
ydata = []
headers = []
for i,p in zip(range(len(t.xpath('plot'))),t.xpath('plot')):
if len(p.xpath("title")) > 0:
ptitle = p.xpath("title")[0].text.strip()
else:
ptitle = 'Plot %d' % (i+1)
graph_lists.append((ptitle,""))
self.graph_lists.append(graph_lists)
self.table_combo.addItem(ttitle)
self.comboItemsChanged()
graph = QtGui.QStackedWidget()
self.graph.addWidget(graph)
self.table_etrees[graph] = t
for p in t.xpath('plot'):
def add_plot(p,t):
if len(p.xpath("title")) > 0:
ptitle = p.xpath("title")[0].text.strip()
else:
ptitle = ''
plot = QtMatplotlibWidget(title=ptitle)
plot.setDefaultSymbolSize(self.defaultSymbolSize)
x_scaling = None
y_scaling = None
for obj in p.xpath('polygon|circle|line'):
if obj.tag == 'polygon':
poly = obj
array1 = numpy.array(poly.text.strip().split(),dtype=float)
array2 = numpy.hsplit(array1,len(array1)/2)
polygon = matplotlib.patches.Polygon(array2)
polygon.set_linewidth(float(poly.attrib.get('linesize','1')))
polygon.set_facecolor(poly.attrib.get('fillcolour','none'))
polygon.set_edgecolor(poly.attrib.get('linecolour','black'))
polygon.set_linestyle(poly.attrib.get('linestyle','solid'))
plot.canvas.ax[0].add_patch(polygon)
elif obj.tag == 'circle':
circ = obj
circle = matplotlib.patches.Circle((float(circ.attrib['xpos']),float(circ.attrib['ypos'])),float(circ.attrib['radius']))
circle.set_linewidth(float(circ.attrib.get('linesize','1')))
circle.set_facecolor(circ.attrib.get('fillcolour','none'))
circle.set_edgecolor(circ.attrib.get('linecolour','black'))
circle.set_linestyle(circ.attrib.get('linestyle','solid'))
plot.canvas.ax[0].add_patch(circle)
elif obj.tag == 'line':
l = obj
x1 = l.attrib['x1']
x2 = l.attrib['x2']
y1 = l.attrib['y1']
y2 = l.attrib['y2']
line = plot.canvas.ax[0].add_line(matplotlib.lines.Line2D([x1,x2],[y1,y2]))
line.set_linewidth(float(l.attrib.get('linesize','1')))
line.set_linestyle(l.attrib.get('linestyle','solid'))
line.set_color(l.attrib.get('linecolour','black'))
considerFixedAspect = False
if len(p.xpath("xrange")) > 0:
try:
try:
xmin = float(p.xpath("xrange")[0].attrib['min'])
except:
xmin = None
try:
xmax = float(p.xpath("xrange")[0].attrib['max'])
except:
xmax = None
plot.canvas.ax[0].set_xlim(xmin,xmax)
plot.canvas.custom_xlim = xmin,xmax
except:
pass
if len(p.xpath("yrange")) > 0:
try:
iax = 0
for yrange in p.xpath("yrange"):
try:
ymin = float(yrange.attrib['min'])
except:
ymin = None
try:
ymax = float(yrange.attrib['max'])
except:
ymax = None
try:
if yrange.attrib['rightaxis'] == "true" or yrange.attrib['rightaxis'] == '1':
rightaxis = True
else:
rightaxis = False
except:
rightaxis = False
if not rightaxis:
plot.canvas.ax[iax].set_ylim(ymin,ymax)
plot.canvas.custom_ylim = ymin,ymax
else:
plot.canvas.rax.append(plot.canvas.ax[0].twinx())
plot.canvas.rax[-1].set_ylim(ymin,ymax)
plot.canvas.custom_rylim = ymin,ymax
try:
rhcol = yrange.attrib['colour']
plot.canvas.rax[-1].spines['right'].set_color(rhcol)
plot.canvas.ax[-1].spines['right'].set_color(rhcol)
for tl in plot.canvas.rax[-1].get_yticklabels():
tl.set_color(rhcol)
except:
pass
except:
pass
if plot.canvas.custom_ylim and len (plot.canvas.custom_ylim)==2 and (plot.canvas.custom_ylim[0] is not None) and (plot.canvas.custom_ylim[1] is not None) and plot.canvas.custom_xlim and len (plot.canvas.custom_xlim)==2 and (plot.canvas.custom_xlim[0] is not None) and (plot.canvas.custom_xlim[1] is not None):
considerFixedAspect = True
try:
if considerFixedAspect and plot.canvas.ax[iax].get_xlim()[0] is not None and plot.canvas.ax[iax].get_xlim()[1] is not None and plot.canvas.ax[iax].get_ylim()[0] is not None and plot.canvas.ax[iax].get_ylim()[1] is not None:
if abs((plot.canvas.ax[iax].get_xlim()[1]-plot.canvas.ax[iax].get_xlim()[0])-(plot.canvas.ax[iax].get_ylim()[1]-plot.canvas.ax[iax].get_ylim()[0]))<1e-5:
plot.canvas.fix_aspect_ratio = True
plot.canvas.resizeEvent(QtGui.QResizeEvent(QtCore.QSize(plot.canvas.width(),plot.canvas.height()),QtCore.QSize(plot.canvas.width(),plot.canvas.height())))
plot.canvas.resizeEvent(QtGui.QResizeEvent(QtCore.QSize(plot.canvas.width(),plot.canvas.height()),QtCore.QSize(plot.canvas.width(),plot.canvas.height())))
except:
pass
if len(p.xpath("legendposition")) > 0:
try:
xlegpos = float(p.xpath("legendposition")[0].attrib['x'])
ylegpos = float(p.xpath("legendposition")[0].attrib['y'])
plot.canvas.initial_legend_position = [xlegpos,ylegpos]
except:
pass
if len(p.xpath('xscale')) > 0 :
x_scaling = scaling_functions[p.xpath("xscale")[0].text.strip()]
plot.canvas.x_scaling = x_scaling
if len(p.xpath('yscale')) > 0 :
y_scaling = scaling_functions[p.xpath("yscale")[0].text.strip()]
plot.canvas.y_scaling = y_scaling
if y_scaling:
plot.canvas.ax[0].yaxis.set_major_formatter(FuncFormatter(y_scaling))
if x_scaling:
plot.canvas.ax[0].xaxis.set_major_formatter(FuncFormatter(x_scaling))
if len(p.xpath('xlabel')) > 0 :
theText = plot.canvas.ax[0].set_xlabel(p.xpath("xlabel")[0].text.strip())
plot.canvas.xlabel = p.xpath("xlabel")[0].text.strip()
if len(p.xpath('ylabel')) > 0 :
theText = plot.canvas.ax[0].set_ylabel(p.xpath("ylabel")[0].text.strip())
plot.canvas.ylabel = p.xpath("ylabel")[0].text.strip()
if len(p.xpath('rylabel')) > 0 :
theText = plot.canvas.rax[0].set_ylabel(p.xpath("rylabel")[0].text.strip())
plot.canvas.rylabel = p.xpath("rylabel")[0].text.strip()
try:
theText.set_color(rhcol)
except:
pass
if len(p.xpath('xbreaks')) > 0 :
xbreaks = p.xpath('xbreaks')[0]
breaks = []
for ibr in range(len(xbreaks.xpath('break'))):
theBreak = xbreaks.xpath('break')[ibr]
breaks.append((float(theBreak.attrib['min']), float(theBreak.attrib['max'])),)
breaks = tuple(breaks)
plot.canvas.set_breaks(breaks,None)
elif len(p.xpath('ybreaks')) > 0 :
ybreaks = p.xpath('ybreaks')[0]
breaks = []
for ibr in range(len(ybreaks.xpath('break'))):
theBreak = ybreaks.xpath('break')[ibr]
breaks.append((float(theBreak.attrib['min']), float(theBreak.attrib['max'])),)
breaks = tuple(breaks)
plot.canvas.set_breaks(None,breaks)
self.connect(plot.canvas,QtCore.SIGNAL("MouseMoveEvent"),functools.partial(self.updateStatusWithXandY,x_scaling,y_scaling))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointMoveEvent"),functools.partial(self.updateStatusWithPickXandY,x_scaling,y_scaling))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointClickEvent"),functools.partial(graph.emit,QtCore.SIGNAL("DetectPointClickEvent")))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointMoveEvent"),functools.partial(graph.emit,QtCore.SIGNAL("DetectPointMoveEvent")))
self.connect(plot.canvas,QtCore.SIGNAL("RegionSelected"),functools.partial(graph.emit,QtCore.SIGNAL("RegionSelected")))
ig = 0
theseColours = None; theColour = None
theseSymbols = None; theSymbol = None
theseSymbolSizes = None; theSymbolSize = None
theseLineSizes = None; theLineSize = None
theseLineStyles = None; theLineStyle = None
for i in range(len(p.xpath('histogram'))):
histo = p.xpath('histogram')[i]
vals = []
col = int(histo.attrib['col'])
array = theFirstArray
vals = array[:,int(col)-1]
head = t.xpath('headers')[0].text.strip().split()[int(col)-1]
if len(histo.xpath('colour'))>0:
color = histo.xpath('colour')[0].text.strip()
else:
color = self.colors[ig % len(self.colors)]
if len(vals)>0:
mu = numpy.mean(vals)
sigma = numpy.std(vals)
maxx = numpy.max(vals)
#n, bins, patches = plot.canvas.ax.hist(vals, int(maxx), normed=0, facecolor=color, label=dataname+' '+str(ig))
#print mu, sigma, maxx, len(vals)
if maxx < 0.0:
maxx = -maxx
if abs(maxx) < 1.0:
maxx = 1.0
if len(histo.xpath('nbins'))>0:
maxx = histo.xpath('nbins')[0].text.strip()
n, bins, patches = plot.canvas.hist(vals, int(maxx), normed=0, facecolor=color, label=head)
#sys.exit()
if len(patches)>0:
# Maybe need a Histogram class ?
self.histograms.append({'normed':False,'vals':vals,'maxx':maxx,'patches':patches,'bins':bins,'mu':mu, 'sigma':sigma})
for i in range(len(p.xpath('plotline'))):
plotline = p.xpath('plotline')[i]
ycol = int(plotline.attrib['ycol'])
array = theFirstArray
if not plotline.attrib.get('dataid',None) is None:
array = self.getDataArray(t,plotline.attrib['dataid'])
if array is None:
array = theFirstArray
ydat2 = array[:,int(ycol)-1]
head = t.xpath('headers')[0].text.strip().split()[int(ycol)-1]
vals = []
if len(plotline.xpath('colour'))>0:
color = plotline.xpath('colour')[0].text.strip()
else:
color = self.colors[ig % len(self.colors)]
if len(plotline.xpath('symbol'))>0:
style = plotline.xpath('symbol')[0].text.strip()
else:
style = self.styles[ig % len(self.styles)]
if len(plotline.xpath('symbolsize'))>0:
markersize = float(plotline.xpath('symbolsize')[0].text.strip())
else:
markersize = self.defaultSymbolSize
if len(plotline.xpath('linestyle'))>0:
linestyle = plotline.xpath('linestyle')[0].text.strip()
else:
linestyle = '-'
if len(plotline.xpath('linesize'))>0:
linewidth = int(plotline.xpath('linesize')[0].text.strip())
else:
linewidth = 1
if not color in self.colors:
try:
c1 = matplotlib.colors.ColorConverter().to_rgb(color)
for cn in self.colors:
c2 = matplotlib.colors.ColorConverter().to_rgb(cn)
if c2 == c1:
break
else:
self.colors.append(color)
self.colors_alias.append(color.capitalize())
except:
color = 'blue'
exc_type, exc_value,exc_tb = sys.exc_info()[:3]
sys.stderr.write(str(exc_type)+'\n')
sys.stderr.write(str(exc_value)+'\n')
idx = 0
xcol = int(plotline.attrib['xcol'])-1
xdata = array[:,xcol]
if len(p.xpath('xintegral'))>0:
if p.xpath('xintegral')[0].text == "true" or p.xpath('xintegral')[0].text == '1':
plot.canvas.xintegral=True
if len(p.xpath('yintegral'))>0:
if p.xpath('yintegral')[0].text == "true" or p.xpath('yintegral')[0].text == '1':
plot.canvas.yintegral=True
visible=True
if len(plotline.xpath('visible'))>0:
if plotline.xpath('visible')[0].text == "false" or plotline.xpath('visible')[0].text == '0':
visible=False
rightaxis = False
try:
if plotline.attrib['rightaxis'] == "true" or yrange.attrib['rightaxis'] == '1':
rightaxis = True
if len(plot.canvas.rax)==0:
plot.canvas.rax.append(plot.canvas.ax[0].twinx())
plot.canvas.rax[-1].set_ylim(None,None)
plot.canvas.custom_rylim = None,None
except:
pass
thePlot = plot.canvas.plot(xdata,ydat2,label=head,picker=self.defaultSymbolSize, marker=style, color=color, markersize=markersize,linestyle=linestyle,linewidth=linewidth,visible=visible,rightaxis=rightaxis)
self.elementToPlotMap[plotline] = thePlot
if len(plotline.xpath('showinlegend'))>0 and len(thePlot)>0:
if plotline.xpath('showinlegend')[0].text == "false" or plotline.xpath('showinlegend')[0].text == '0':
thePlot[0].hide_from_legend = True
if len(plotline.xpath('label'))>0 and len(thePlot)>0:
thePlot[0].set_label(plotline.xpath('label')[0].text)
if len(plotline.xpath('markeredgewidth'))>0 and len(thePlot)>0:
thePlot[0].set_markeredgewidth(float(plotline.xpath('markeredgewidth')[0].text))
ig = ig+1
if len(p.xpath("legendposition")) == 0:
halfx = (plot.canvas.ax[0].get_xlim()[0]+plot.canvas.ax[0].get_xlim()[1])/2.
halfy = (plot.canvas.ax[0].get_ylim()[0]+plot.canvas.ax[0].get_ylim()[1])/2.
nTopLeft = nTopRight = nBottomLeft = nBottomRight = 0
for i in range(len(p.xpath('plotline'))):
plotline = p.xpath('plotline')[i]
ycol = int(plotline.attrib['ycol'])
ydat2 = array[:,int(ycol)-1]
xcol = int(plotline.attrib['xcol'])-1
xdata = array[:,xcol]
nTopLeft_i, nTopRight_i, nBottomLeft_i, nBottomRight_i = self.analyzeDistributionOfPoints(xdata, ydat2, halfx, halfy)
nTopLeft += nTopLeft_i
nBottomLeft += nBottomLeft_i
nTopRight += nTopRight_i
nBottomRight += nBottomRight_i
legend_pos_idx = (nTopLeft, nTopRight, nBottomLeft, nBottomRight).index(min(nTopLeft, nTopRight, nBottomLeft, nBottomRight))
if legend_pos_idx == 0:
plot.canvas.initial_legend_position = [0.15,0.75]
elif legend_pos_idx == 1:
plot.canvas.initial_legend_position = [0.75,0.75]
elif legend_pos_idx == 2:
plot.canvas.initial_legend_position = [0.15,0.15]
elif legend_pos_idx == 3:
plot.canvas.initial_legend_position = [0.75,0.15]
plot.canvas.legend()
try:
plot.canvas.applyPreferences(self.titleFontSel,self.axesFontSel,self.axesLabelFontSel,self.legendFontSel,redraw=False)
except:
sys.stderr.write("Failed to apply font preferences\n")
exc_type, exc_value,exc_tb = sys.exc_info()[:3]
sys.stderr.write(str(exc_type)+'\n')
sys.stderr.write(str(exc_value)+'\n')
if len(p.xpath('fixaspectratio'))>0:
fixaspectratio = p.xpath('fixaspectratio')[0].text.strip()
if fixaspectratio =='1' or fixaspectratio =='true':
plot.canvas.fix_aspect_ratio = True
if len(p.xpath('showlegend'))>0:
showlegend = p.xpath('showlegend')[0].text.strip()
if showlegend =='0' or showlegend =='false':
plot.canvas.ax[0].legend_.set_visible(False)
return plot
#plot = add_plot(p,t)
#graph.addWidget(plot)
nullWidget = QtGui.QWidget()
nullWidget._do_the_plot_ = functools.partial(add_plot,p,t)
graph.addWidget(nullWidget)
#self.table_combo.setCurrentIndex(self.table_combo.count()-1)
self.statusFormat = None
return graph
def addCCP4Table(self,table,graph_uuid=None):
self.graph_lists.append(table.graphs_list)
self.table_combo.addItem(table.title)
self.comboItemsChanged()
graph = QtGui.QStackedWidget()
if graph_uuid != None:
graph.setObjectName(graph_uuid)
self.graph.addWidget(graph)
t = etree.Element("CCP4Table")
theData = etree.Element("data")
theDataText = ''
for tdl in table.data_lines:
theDataText += ''.join([("%s "%n) for n in tdl[:]]).strip() + '\n'
theData.text = theDataText
t.append(theData)
self.table_etrees[graph] = t
theHeaders = etree.Element("headers",separator=' ')
theHeaders.text = ''.join([("%s "%n) for n in table.headers[:]]).strip() + '\n'
t.append(theHeaders)
for g in table.graphs_list:
p = etree.Element('plot')
theTitle = etree.Element("title")
theTitle.text = g[0]
p.append(theTitle)
t.append(p)
for s in g[1].split(',')[1:]:
plotline = etree.Element('plotline', xcol=g[1].split(',')[0], ycol=s)
p.append(plotline)
def add_plot(table,graph,g,t,p):
plot = QtMatplotlibWidget(title=g[0])
plot.setDefaultSymbolSize(self.defaultSymbolSize)
self.connect(plot.canvas,QtCore.SIGNAL("MouseMoveEvent"),functools.partial(self.updateStatusWithXandY,table.x_scaling,table.y_scaling))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointMoveEvent"),functools.partial(self.updateStatusWithPickXandY,table.x_scaling,table.y_scaling))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointClickEvent"),functools.partial(graph.emit,QtCore.SIGNAL("DetectPointClickEvent")))
self.connect(plot.canvas,QtCore.SIGNAL("DetectPointMoveEvent"),functools.partial(graph.emit,QtCore.SIGNAL("DetectPointMoveEvent")))
self.connect(plot.canvas,QtCore.SIGNAL("RegionSelected"),functools.partial(graph.emit,QtCore.SIGNAL("RegionSelected")))
for s in g[1].split(',')[0:1]:
xvals = []
col = int(s)-1
if table.custom_x_label:
plot.canvas.ax[0].set_xlabel(table.custom_x_label)
plot.canvas.xlabel = table.custom_x_label
else:
plot.canvas.ax[0].set_xlabel(table.headers[col])
plot.canvas.xlabel = table.headers[col]
for l in table.data_lines:
try:
v = l[col]
xvals.append(v)
except:
print "Error",l,col
ig = 0
theRange = None
if len(g)>2:
theRange = g[2]
theXVals = []
theYVals = []
for s in g[1].split(',')[1:]:
plotline = p.xpath('plotline')[ig]
vals = []
col = int(s)-1
myxvals = []
for l,il in zip(table.data_lines,range(len(table.data_lines))):
try:
f = float(l[col])
vals.append(l[col])
myxvals.append(xvals[il])
except:
pass
color = self.colors[ig % len(self.colors)]
style = self.styles[ig % len(self.styles)]
try:
thePlot = plot.canvas.plot(myxvals,vals,label=table.headers[col],picker=self.defaultSymbolSize, marker=style, color=color, markersize=self.defaultSymbolSize)
theXVals.append(myxvals)
theYVals.append(vals)
self.elementToPlotMap[plotline] = thePlot
try:
if theRange and len(theRange)==2 and theRange[0] and theRange[1] and len(theRange[0])==2 and len(theRange[1])==2:
xmin,xmax = theRange[0]
ymin,ymax = theRange[1]
plot.canvas.ax[0].set_xlim(xmin,xmax)
plot.canvas.ax[0].set_ylim(ymin,ymax)
plot.canvas.custom_xlim = xmin,xmax
plot.canvas.custom_ylim = ymin,ymax
except:
pass
except:
print "Badly formatted line",l,vals, len(myxvals), len(vals)
ig = ig+1
if table.y_scaling:
plot.canvas.ax[0].yaxis.set_major_formatter(FuncFormatter(table.y_scaling))
plot.canvas.y_scaling = table.y_scaling
if table.x_scaling:
plot.canvas.ax[0].xaxis.set_major_formatter(FuncFormatter(table.x_scaling))
plot.canvas.x_scaling = table.x_scaling
halfx = (plot.canvas.ax[0].get_xlim()[0]+plot.canvas.ax[0].get_xlim()[1])/2.
halfy = (plot.canvas.ax[0].get_ylim()[0]+plot.canvas.ax[0].get_ylim()[1])/2.
nTopLeft = nTopRight = nBottomLeft = nBottomRight = 0
for i in range(len(theXVals)):
nTopLeft_i, nTopRight_i, nBottomLeft_i, nBottomRight_i = self.analyzeDistributionOfPoints(theXVals[i], theYVals[i], halfx, halfy)
nTopLeft += nTopLeft_i
nBottomLeft += nBottomLeft_i
nTopRight += nTopRight_i
nBottomRight += nBottomRight_i
legend_pos_idx = (nTopLeft, nTopRight, nBottomLeft, nBottomRight).index(min(nTopLeft, nTopRight, nBottomLeft, nBottomRight))
if legend_pos_idx == 0:
plot.canvas.initial_legend_position = [0.15,0.75]
elif legend_pos_idx == 1:
plot.canvas.initial_legend_position = [0.75,0.75]
elif legend_pos_idx == 2:
plot.canvas.initial_legend_position = [0.15,0.15]
elif legend_pos_idx == 3:
plot.canvas.initial_legend_position = [0.75,0.15]
plot.canvas.legend()
try:
plot.canvas.applyPreferences(self.titleFontSel,self.axesFontSel,self.axesLabelFontSel,self.legendFontSel,redraw=False)
except:
sys.stderr.write("Failed to apply font preferences\n")
exc_type, exc_value,exc_tb = sys.exc_info()[:3]
sys.stderr.write(str(exc_type)+'\n')
sys.stderr.write(str(exc_value)+'\n')
return plot
#graph.addWidget(add_plot(table,graph,g))
nullWidget = QtGui.QWidget()
nullWidget._do_the_plot_ = functools.partial(add_plot,table,graph,g,t,p)
graph.addWidget(nullWidget)
#self.table_combo.setCurrentIndex(self.table_combo.count()-1)
return graph
def sizeHint(self):
return QtCore.QSize(800,600)
def comboItemsChanged(self):
if self.table_combo.count()>1 or self.data_combo.count()>1:
self.table_combo.show()
self.data_combo.show()
else:
self.table_combo.hide()
self.data_combo.hide()
def __init__(self,parent=None):
QtGui.QWidget.__init__(self,parent)
#print 'Loggraph parent',self.parent()
self.titleFontSel,self.axesFontSel,self.axesLabelFontSel,self.legendFontSel = None,None,None,None
layout = QtGui.QHBoxLayout()
mainLayout = QtGui.QVBoxLayout()
self.setLayout(layout)
layout.addLayout(mainLayout)
self.graph = QtGui.QStackedWidget()
nullGraph = QtMatplotlibWidget()
#self.graph.addWidget(nullGraph)
self.table_combo = QtGui.QComboBox()
self.data_combo = QtGui.QComboBox()
self.table_combo.hide()
self.data_combo.hide()
comboLayout = QtGui.QHBoxLayout()
comboLayout.addWidget(self.table_combo)
comboLayout.addWidget(self.data_combo)
mainLayout.addWidget(self.graph)
mainLayout.addLayout(comboLayout)
self.graph_lists = []
self.histograms = []
self.table_etrees = {}
self.surface_etrees = []
self.elementToPlotMap = {}
line = QtGui.QHBoxLayout()
line.setContentsMargins(0,0,0,0)
line.setSpacing(0)
layout.setContentsMargins(0,0,0,0)
layout.setSpacing(0)
comboLayout.setContentsMargins(0,0,0,0)
comboLayout.setSpacing(0)
mainLayout.setContentsMargins(0,0,0,0)
mainLayout.setSpacing(0)
self.statusBar=QtGui.QStatusBar()
self.statusBar.setSizeGripEnabled(False)
self.statusFormat = None
# Add spacing to statusBar line to get nicer layout if add a widget in ccp4i2
line.addWidget(self.statusBar)
line.addSpacing(10)
mainLayout.addLayout(line)
self.connect(self.table_combo, QtCore.SIGNAL("currentIndexChanged(int)"),self.setCurrentTable);
self.connect(self.data_combo, QtCore.SIGNAL("currentIndexChanged(int)"),self.setCurrentData);
self.setWindowTitle("Pimple")
self.fileOpen = QtGui.QAction("Open..",self)
self.fileSave = QtGui.QAction("Save figure..",self)
self.fileSaveStatus = QtGui.QAction("Save status..",self)
self.fileSaveAll = QtGui.QAction("Save all figures..",self)
self.prefAction = QtGui.QAction("Preferences..",self)
self.editLegendPos = QtGui.QAction("Edit legend position",self)
self.editPlotStyle = QtGui.QAction("Edit plot style",self)
haveEditIcon = True
try:
icon = QtGui.QIcon()
if getattr(sys, 'frozen', None):
basedir = sys._MEIPASS
fbase = os.path.normpath(os.path.join(basedir,"qticons","actions","edit"))
else:
fbase = os.path.normpath(os.path.join(os.path.dirname(__file__),"..","qticons","actions","edit"))
pngs = glob.glob(os.path.join(fbase,"*.png"))
if len(pngs)==0:
haveEditIcon = False
for png in pngs:
icon.addFile(unicode(png,'utf-8'))
self.editPlotStyle.setIcon(icon)
except:
haveEditIcon = False
print "Failed to set edit icon"
self.icons_missing = False
self.fileOpen.setShortcut(QtGui.QKeySequence.Open)
self.fileSaveStatus.setShortcut(QtGui.QKeySequence.Save)
self.connect(self.fileSave,QtCore.SIGNAL("triggered(bool)"),self.saveFileDialog)
self.connect(self.fileSaveAll,QtCore.SIGNAL("triggered(bool)"),functools.partial(self.saveFileDialog,True,False))
self.connect(self.fileSaveStatus,QtCore.SIGNAL("triggered(bool)"),functools.partial(self.saveFileDialog,False,True))
self.connect(self.fileOpen,QtCore.SIGNAL("triggered(bool)"),self.loadFileDialog)
self.connect(self.editLegendPos,QtCore.SIGNAL("triggered(bool)"),self.editLegendPosition)
self.connect(self.editPlotStyle,QtCore.SIGNAL("triggered(bool)"),self.editPlotPlotStyle)
self.connect(self.prefAction,QtCore.SIGNAL("triggered(bool)"),self.editPreferences)
if getattr(sys, 'frozen', None):
basedir = sys._MEIPASS
icondir = os.path.abspath(os.path.join(basedir,'qticons','loggraph'))
else:
icondir = os.path.abspath(os.path.join(os.path.dirname(__file__),'..','qticons','loggraph'))
if os.path.exists(icondir):
self.fileOpen.setIcon(QtGui.QIcon(os.path.join(icondir,"fileopen.svg")))
self.fileSave.setIcon(QtGui.QIcon(os.path.join(icondir,"save_picture.svg")))
self.prefAction.setIcon(QtGui.QIcon(os.path.join(icondir,"preferences.svg")))
self.editLegendPos.setIcon(QtGui.QIcon(os.path.join(icondir,"moving.svg")))
self.fileSaveStatus.setIcon(QtGui.QIcon(os.path.join(icondir,"save_status.svg")))
self.actionBar = QtGui.QWidget()
actionLayout = QtGui.QVBoxLayout()
openButton = QtGui.QToolButton()
openButton.setDefaultAction(self.fileOpen)
if not os.path.exists(os.path.join(icondir,"fileopen.svg")):
openButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
self.icons_missing = True
actionLayout.addWidget(openButton)
saveStatusButton = QtGui.QToolButton()
saveStatusButton.setDefaultAction(self.fileSaveStatus)
if not os.path.exists(os.path.join(icondir,"save_status.svg")):
saveStatusButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
self.icons_missing = True
saveButton = QtGui.QToolButton()
saveButton.setDefaultAction(self.fileSave)
if not os.path.exists(os.path.join(icondir,"save_picture.svg")):
saveButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
self.icons_missing = True
actionLayout.addWidget(saveButton)
editLegendButton = QtGui.QToolButton()
editLegendButton.setDefaultAction(self.editLegendPos)
if not os.path.exists(os.path.join(icondir,"moving.svg")):
editLegendButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
self.icons_missing = True
actionLayout.addWidget(editLegendButton)
editPlotStyle = QtGui.QToolButton()
editPlotStyle.setDefaultAction(self.editPlotStyle)
if not haveEditIcon:
editPlotStyle.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
self.icons_missing = True
actionLayout.addWidget(editPlotStyle)
self.actionBar.setLayout(actionLayout)
actionLayout.addStretch(2)
layout.addWidget(self.actionBar)
actionLayout.setContentsMargins(3,3,3,3)
self.actionBar.hide()
self.defaultSymbolSize = 5
def showActionBar(self):
self.actionBar.show()
def setDefaultSymbolSize(self,size=5):
self.defaultSymbolSize = size
class QtMatplotlibWidget(QtGui.QWidget):
def __init__(self,parent=None,figsize = (800, 600), dpi=100,facecolor = '#FFFFFF',title='',x_axis_label='',y_axis_label=''):
QtGui.QWidget.__init__(self,parent)
fig = Figure(figsize=figsize,dpi=dpi,facecolor=facecolor)
self.canvas = QtMatplotlibCanvas(fig,title=title,x_axis_label=x_axis_label,y_axis_label=y_axis_label)
layout = QtGui.QVBoxLayout()
layout.addWidget(self.canvas)
self.setLayout(layout)
self.setCursor(QtCore.Qt.CrossCursor)
layout.setContentsMargins(0,0,0,0)
self.defaultSymbolSize = 5
def addPoint(self,point):
self.canvas.addPoint(point)
def setDefaultSymbolSize(self,size=5):
self.defaultSymbolSize = size
self.canvas.setDefaultSymbolSize(size)
class QtMatplotlibCanvas(FigureCanvas):
def setDefaultSymbolSize(self,size=5):
self.defaultSymbolSize = size
def applyPreferences(self,titleFontSel=None,axesFontSel=None,axesLabelFontSel=None,legendFontSel=None,redraw=True):
try:
params = legendFontSel
if params:
if params.has_key('family'):
family = params['family']
else:
family = "Bitstream Vera Sans"
if params.has_key('size'):
size = params['size']
else:
size = 8
newFont = FontProperties(family=family,size=size)
self.legend_font = newFont
else:
newFont = FontProperties(family="Bitstream Vera Sans",size=8)
self.legend_font = newFont
except:
print "error 1"
pass
#print 'applyPreferences titleFontSel',titleFontSel
try:
params = titleFontSel
if params:
if params.has_key('family'):
family = params['family']
else:
family = "Bitstream Vera Sans"
if params.has_key('size'):
size = params['size']
else:
size = 8
newFont = FontProperties(family=family,size=size)
self.title_font = newFont
else:
newFont = FontProperties(family="Bitstream Vera Sans",size=8)
self.title_font = newFont
except:
print "error 2"
pass
try:
params = axesFontSel
if params:
if params.has_key('family'):
family = params['family']
else:
family = "Bitstream Vera Sans"
if params.has_key('size'):
size = params['size']
else:
size = 8
newFont = FontProperties(family=family,size=size)
self.axes_font = newFont
else:
newFont = FontProperties(family="Bitstream Vera Sans",size=8)
self.axes_font = newFont
except:
print "error 3"
pass
try:
params = axesLabelFontSel
if params:
if params.has_key('family'):
family = params['family']
else:
family = "Bitstream Vera Sans"
if params.has_key('size'):
size = params['size']
else:
size = 8
newFont = FontProperties(family=family,size=size)
self.label_font = newFont
else:
newFont = FontProperties(family="Bitstream Vera Sans",size=8)
self.label_font = newFont
except:
print "error 4"
pass
for fn,params in ((self.legend_font,legendFontSel),(self.title_font,titleFontSel),(self.axes_font,axesFontSel),(self.label_font,axesLabelFontSel)):
if params:
if params.has_key('weight') and params['weight']=='bold':
fn.set_weight('bold')
else:
fn.set_weight('normal')
if params.has_key('slant') and params['slant']=='italic':
fn.set_slant('italic')
else:
fn.set_slant('normal')
self.legend()
if self.xbreak:
nbreaks = len(self.xbreak)+1
theTitle = self.ax[int(nbreaks/2.)].set_title(self.title)
theXLabel = self.ax[int(nbreaks/2.)].set_xlabel(self.xlabel)
theYLabel = self.ax[0].set_ylabel(self.ylabel)
if len(self.rax):
theRYLabel = self.rax[-1].set_ylabel(self.rylabel)
theRYLabel.set_fontproperties(self.label_font)
elif self.ybreak:
nbreaks = len(self.ybreak)+1
theTitle = self.ax[0].set_title(self.title)
theXLabel = self.ax[-1].set_xlabel(self.xlabel)
theYLabel = self.ax[int(nbreaks/2.)].set_ylabel(self.ylabel)
else:
theTitle = self.ax[0].set_title(self.title)
theXLabel = self.ax[0].set_xlabel(self.xlabel)
theYLabel = self.ax[0].set_ylabel(self.ylabel)
theTitle.set_fontproperties(self.title_font)
theXLabel.set_fontproperties(self.label_font)
theYLabel.set_fontproperties(self.label_font)
self.set_tick_labels_font()
if not redraw:
return
self.resizeEvent(QtGui.QResizeEvent(QtCore.QSize(self.width(),self.height()),QtCore.QSize(self.width(),self.height())))
self.resizeEvent(QtGui.QResizeEvent(QtCore.QSize(self.width(),self.height()),QtCore.QSize(self.width(),self.height())))
self.draw()
def legend(self,loc=None,bbox_to_anchor=None):
xratio = 1.0
if hasattr(self,"old_xbreak"):
if (self.old_xbreak and not self.xbreak) or (not self.old_xbreak and self.xbreak) or (self.old_xbreak and self.xbreak and len(self.old_xbreak) != len(self.xbreak)):
if self.xbreak:
nax = len(self.xbreak) + 1
else:
nax = 1
if self.old_xbreak:
naxold = len(self.old_xbreak) + 1
else:
naxold = 1
xratio = float(nax)/float(naxold)
haveLegend = False
handles,labels = self.ax[0].get_legend_handles_labels()
if len(self.rax)>0:
rhandles,rlabels = self.rax[0].get_legend_handles_labels()
handles.extend(rhandles)
labels.extend(rlabels)
leg_handles = []
leg_labels = []
for handle, label in zip(handles,labels):
if not label.endswith('_matplotlib_line_of_best_fit'):
if (hasattr(handle,"hide_from_legend") and handle.hide_from_legend == True) or not handle.get_visible():
pass
else:
leg_handles.append(handle)
leg_labels.append(label)
haveLegend = True
if not haveLegend:
if self.ax[0].get_legend():
self.ax[0].legend_.set_visible(False)
else:
if loc != None and bbox_to_anchor != None:
if self.xbreak:
self.custom_legend_position = bbox_to_anchor[0]/(xratio*1.3*(len(self.xbreak)+1)),bbox_to_anchor[1]
self.ax[0].legend(leg_handles,leg_labels,fancybox=True, shadow=True, loc = loc, bbox_to_anchor = bbox_to_anchor, prop=self.legend_font)
elif self.ax[0].get_legend():
if(hasattr,self.ax[0].get_legend().get_bbox_to_anchor().get_points(),"item") and callable(self.ax[0].get_legend().get_bbox_to_anchor().get_points().item):
points = self.ax[0].get_legend().get_bbox_to_anchor().get_points().item(0), self.ax[0].get_legend().get_bbox_to_anchor().get_points().item(1)
else:
points = self.ax[0].get_legend().get_bbox_to_anchor().get_points()[1]
loc = self.ax[0].get_legend().parent.transAxes.inverted().transform_point((xratio*points[0],points[1]))
fm = QtGui.QFontMetrics(QtGui.QFont(self.legend_font.get_family()[0],self.legend_font.get_size()))
maxp = 0
for lab in leg_labels:
maxp = max(maxp,fm.width(lab))
leg_h = fm.height()*len(leg_labels)
if sys.platform == "darwin":
#No idea why I have to do this hack.
leg_h *= 2
maxp *= 2
if loc[0] + float(maxp)/self.parent().width() > 0.8:
loc[0] -= float(maxp)/self.parent().width()
#print "Adjusting x pos"
if loc[1] + float(leg_h)/self.parent().height()>0.8:
if sys.platform == "darwin":
loc[1] -= float(leg_h)/self.parent().height()
else:
loc[1] -= 1.5*float(leg_h)/self.parent().height()
#print "Adjusting y pos"
self.custom_legend_position = loc[0],loc[1]
if self.xbreak:
self.custom_legend_position = loc[0]/(xratio*1.3*(len(self.xbreak)+1)),loc[1]
self.ax[0].legend(leg_handles,leg_labels,fancybox=True, shadow=True, prop=self.legend_font, loc ='lower left', bbox_to_anchor =loc)
else:
self.ax[0].legend(leg_handles,leg_labels,fancybox=True, shadow=True, prop=self.legend_font, loc ='lower left', bbox_to_anchor =self.initial_legend_position)
if self.xbreak:
loc = (xratio*1.0*(len(self.xbreak)+1)*self.initial_legend_position[0],self.initial_legend_position[1])
self.ax[0].legend(leg_handles,leg_labels,fancybox=True, shadow=True, prop=self.legend_font, loc = 'lower left', bbox_to_anchor =loc)
self.old_xbreak = self.xbreak
self.old_ybreak = self.ybreak
def keyPressEvent(self,e):
if e.key() == QtCore.Qt.Key_Escape:
self.movingLegend = False
self.repaint()
def mousePressEvent(self,e):
self.mouseDownPos = QtCore.QPoint(e.pos())
FigureCanvas.mousePressEvent(self,e)
def mouseReleaseEvent(self, e):
self.mouseUpPos = QtCore.QPoint(e.pos())
FigureCanvas.mouseReleaseEvent(self,e)
self.repaint()
if not hasattr(self,"mouseDownPos"):
return
if self.mouseDownPos.x() != self.mouseUpPos.x():
# FIXME, this needs to cope with broken axes! Hard.
xlim = self.ax[0].get_xlim()
figWidth = self.width()*(float(self.right)-self.left)
xp = (float(self.mouseDownPos.x())-float(self.left)*self.width())/figWidth
x1 = xp*(xlim[1]-xlim[0])+xlim[0]
xp = (float(self.mouseUpPos.x())-float(self.left)*self.width())/figWidth
x2 = xp*(xlim[1]-xlim[0])+xlim[0]
self.emit(QtCore.SIGNAL("RegionSelected"),{'plotwidget':self.parent(), 'x1':x1,'x2':x2})
def mouseMoveEvent(self,e):
if e.buttons() & QtCore.Qt.LeftButton:
self.mouseUpPos = QtCore.QPoint(e.pos())
FigureCanvas.mouseMoveEvent(self,e)
self.repaint()
def resizeEvent(self,e):
if self._type == 'surface':
return FigureCanvas.resizeEvent(self,e)
if self.width() == 0:
self.left = 0.3
self.right = 1
else:
if self.ylabel or self.xlabel:
labelFontscale = math.pow(float(QtGui.QFontMetrics(QtGui.QFont(QtCore.QString(unicode(self.label_font.get_family()[0],"utf-8")),self.label_font.get_size())).height())/self.defaultTextHeight,0.6)
if self.ylabel:
self.left = 0.3 / self.width()*200.*labelFontscale
else:
self.left = 0.2 / self.width()*200.
self.right = 1 - 0.1 / self.width()*200.
if hasattr(self,"rylabel") and self.rylabel:
self.right -= 0.1 / self.width()*200.*labelFontscale
if self.height() == 0:
self.top = 0.95
self.bottom = 0.1
else:
if self.title:
fontscale = math.pow(float(QtGui.QFontMetrics(QtGui.QFont(QtCore.QString(unicode(self.title_font.get_family()[0],"utf-8")),self.title_font.get_size())).height())/self.defaultTextHeight,0.6)
self.top = 1 - 0.15 / self.height()*200.*fontscale
else:
self.top = 1 - 0.05 / self.height()*200.
if self.xlabel:
self.bottom = 0.2 / self.height()*200.*labelFontscale
else:
self.bottom = 0.1 / self.height()*200.
axesFontscale = math.pow(float(QtGui.QFontMetrics(QtGui.QFont(QtCore.QString(unicode(self.axes_font.get_family()[0],"utf-8")),self.axes_font.get_size())).height())/self.defaultTextHeight,0.6)-1.
self.left += 0.3 / self.width()*200.*axesFontscale
self.bottom += 0.3 / self.width()*200.*axesFontscale
if len(self.rax)>0:
self.right -= 50*(self.axes_font.get_size()/self.defaultTextHeight)/self.width()
if self.fix_aspect_ratio and self.width()>0 and self.height()>0:
if self.width()>self.height():
diff = (1-self.right+self.left)/2*self.height()/self.width()
ratio = (float(self.width())/self.height()-1)/2/(float(self.width())/self.height())
self.left = ratio
self.right = 1-ratio
self.left += (1-self.top+self.bottom)/2*self.height()/self.width()
self.right -= (1-self.top+self.bottom)/2*self.height()/self.width()
if self.ylabel:
self.left += diff
self.bottom += diff
else:
ratio = (float(self.height())/self.width()-1)/2/(float(self.height())/self.width())
self.bottom = ratio
self.top = 1-ratio
self.bottom += (1-self.right+self.left)/2*self.width()/self.height()
self.top -= (1-self.right+self.left)/2*self.width()/self.height()
if self.left >= self.right:
self.left = self.right - 0.001
if self.bottom >= self.top:
self.bottom = self.top - 0.001
self.fig.subplots_adjust(self.left, self.bottom, self.right, self.top)
if self.xbreak:
nbreaks = len(self.xbreak)+1
self.gs[0].update(left=self.left, right=(self.left+self.right)/float(nbreaks)-0.5*self.breaksize, top=self.top, bottom=self.bottom, wspace=0.0)
for i in range(1,len(self.gs)):
self.gs[i].update(left=i*(self.left+self.right)/float(nbreaks)+0.5*self.breaksize, right=min(self.right,(i+1)*(self.left+self.right)/float(nbreaks)-0.5*self.breaksize), top=self.top, bottom=self.bottom, wspace=0.0)
elif self.ybreak:
nbreaks = len(self.ybreak)+1
bottom = (nbreaks-1)*(self.top+self.bottom)/float(nbreaks)+0.5*self.breaksize
if bottom >= self.top:
bottom = self.top - 0.001
self.gs[0].update(left=self.left, right=self.right, top=self.top, bottom=bottom, wspace=0.0)
for i in range(1,len(self.gs)):
bottom = max(self.bottom,(i-1)*(self.top+self.bottom)/float(nbreaks)+0.5*self.breaksize)
top = i*(self.top+self.bottom)/float(nbreaks)-0.5*self.breaksize
if bottom >=top:
bottom = top - 0.001
self.gs[nbreaks-i].update(left=self.left, right=self.right, top=top, bottom=bottom, wspace=0.0)
else:
self.gs[0].update(left=self.left, right=self.right, top=self.top, bottom=self.bottom, wspace=0.0)
FigureCanvas.resizeEvent(self,e)
def paintEvent(self,e):
FigureCanvas.paintEvent(self,e)
painter = QtGui.QPainter(self);
painter.setPen(QtCore.Qt.blue);
pos = self.mapFromGlobal(self.cursor().pos())
if hasattr(self,"mouseDownPos") and hasattr(self,"mouseUpPos"):
if self.mouseDownPos.x() != self.mouseUpPos.x():
if self.mouseDownPos.x() < self.mouseUpPos.x():
painter.fillRect(self.mouseDownPos.x(),(1-self.top)*self.height(),self.mouseUpPos.x()-self.mouseDownPos.x(),(1-self.bottom)*self.height()-(1-self.top)*self.height(),QtGui.QBrush(QtGui.QColor(128,128,255,60),QtCore.Qt.SolidPattern))
else:
painter.fillRect(self.mouseUpPos.x(),(1-self.top)*self.height(),self.mouseDownPos.x()-self.mouseUpPos.x(),(1-self.bottom)*self.height()-(1-self.top)*self.height(),QtGui.QBrush(QtGui.QColor(128,128,255,60),QtCore.Qt.SolidPattern))
painter.drawLine(self.mouseDownPos.x(),(1-self.top)*self.height(),self.mouseDownPos.x(),(1-self.bottom)*self.height())
painter.drawLine(self.mouseUpPos.x(),(1-self.top)*self.height(),self.mouseUpPos.x(),(1-self.bottom)*self.height())
if self.movingLegend == True:
if self.ax[0].get_legend():
bbox = self.ax[0].get_legend().get_window_extent()
bbox2 = bbox.transformed(self.ax[0].get_legend().axes.transAxes.inverted())
painter.drawLine(pos.x(),pos.y(),pos.x()+bbox.width,pos.y())
painter.drawLine(pos.x(),pos.y()-bbox.height,pos.x()+bbox.width,pos.y()-bbox.height)
painter.drawLine(pos.x(),pos.y(),pos.x(),pos.y()-bbox.height)
painter.drawLine(pos.x()+bbox.width,pos.y(),pos.x()+bbox.width,pos.y()-bbox.height)
else:
self.movingLegend = False
else:
if pos.x() > self.left*self.width() and pos.x() < self.right*self.width() and pos.y() > (1-self.top)*self.height() and pos.y() < (1-self.bottom)*self.height():
painter.drawLine(pos.x(),(1-self.top)*self.height(),pos.x(),(1-self.bottom)*self.height())
painter.drawLine(self.left*self.width(),pos.y(),self.right*self.width(),pos.y())
if self._painted == False:
self._painted = True
self.resizeEvent(QtGui.QResizeEvent(QtCore.QSize(self.width(),self.height()),QtCore.QSize(self.width(),self.height())))
self.legend()
def autoscale_based_on(self,ax):
lines = ax.get_lines()
ax.dataLim = mtransforms.Bbox([(1,1),(0,0)])
for line in lines:
if not hasattr(line,"ignore"):
xy = numpy.vstack(line.get_data()).T
ax.dataLim.update_from_data_xy(xy, ignore=False)
ax.autoscale_view()
def plot(self,*args,**kwargs):
axis = self.ax
if kwargs.has_key("rightaxis"):
rightaxis = kwargs.pop("rightaxis")
if rightaxis:
axis = self.rax
self.remove_break_lines_x()
axis[0].set_autoscale_on(True)
if kwargs or args:
thePlot = axis[0].plot(*args,**kwargs)
else:
thePlot = None
if self.xbreak or self.ybreak:
axis[0].set_autoscale_on(False)
self.show_break_lines()
self.autoscale_based_on(axis[0])
axis[0].set_autoscale_on(False)
if self.custom_xlim: axis[0].set_xlim(self.custom_xlim)
if self.custom_rylim and axis is self.rax:
axis[0].set_ylim(self.custom_rylim)
if self.custom_ylim and axis is not self.rax:
axis[0].set_ylim(self.custom_ylim)
for l in axis[0].get_lines():
if not hasattr(l,"ignore"):
if not hasattr(l,"ccp4_uuid"):
if sys.platform != 'win32':
import uuid
uuid_str = uuid.uuid4().get_hex()
else:
import msilib
uuid_str = msilib.gen_uuid().strip('{').strip('}').replace('-','')
l.ccp4_uuid = uuid_str
for theAxis in axis[1:]:
for l2t in theAxis.get_lines():
if hasattr(l2t,"ccp4_uuid") and l2t.ccp4_uuid == l.ccp4_uuid:
haveThis = True
break
else:
l2 = matplotlib.lines.Line2D(l.get_xdata(),l.get_ydata(),linewidth=l.get_linewidth(),linestyle=l.get_linestyle(),
color=l.get_color(),markersize=l.get_markersize(),marker=l.get_marker(),label=l.get_label(),picker=l.get_picker()
)
if not l.get_visible():
l2.set_visible(0)
theAxis.add_line(l2)
l2.ccp4_uuid = l.ccp4_uuid
theXLim = axis[0].get_xlim()
theYLim = axis[0].get_ylim()
theXRange = theXLim[1]-theXLim[0]
theYRange = theYLim[1]-theYLim[0]
for ax in axis:
ax.set_xlim(theXLim[0],theXLim[1])
ax.set_ylim(theYLim[0],theYLim[1])
if self.xbreak:
axis[0].set_xlim(theXLim[0],self.xbreak[0][0])
nbreaks = len(self.xbreak)
for i in range(nbreaks-1):
axis[i+1].set_xlim(self.xbreak[i][1],self.xbreak[i+1][0])
axis[i+1].set_ylim(theYLim[0],theYLim[1])
fmt = ScalarFormatter()
fmt.set_useOffset(0)
axis[i+1].xaxis.set_major_formatter(fmt)
axis[-1].set_xlim(self.xbreak[-1][1],theXLim[1])
axis[-1].set_ylim(theYLim[0],theYLim[1])
elif self.ybreak:
axis[-1].set_ylim(theYLim[0],self.ybreak[0][0])
nbreaks = len(self.ybreak)
for i in range(nbreaks-1):
axis[nbreaks-i-1].set_ylim(self.ybreak[i][1],self.ybreak[i+1][0])
axis[nbreaks-i-1].set_xlim(theXLim[0],theXLim[1])
axis[0].set_ylim(self.ybreak[-1][1],theXLim[1])
axis[0].set_xlim(theXLim[0],theXLim[1])
xticks = 5
if self.xbreak:
xticks -= len(self.xbreak)-1
yticks = 5
if self.ybreak:
yticks -= len(self.ybreak)-1
if self.xintegral: xticks += 1
if self.yintegral: yticks += 1
xticks = max(xticks,1)
yticks = max(yticks,1)
for ax in axis:
ax.xaxis.set_major_locator(matplotlib.ticker.MaxNLocator(xticks,integer=self.xintegral))
ax.xaxis.get_major_locator().refresh()
ax.yaxis.set_major_locator(matplotlib.ticker.MaxNLocator(yticks,integer=self.yintegral))
ax.yaxis.get_major_locator().refresh()
for ax in axis:
if self.x_scaling: ax.xaxis.set_major_formatter(FuncFormatter(self.x_scaling))
if self.y_scaling: ax.yaxis.set_major_formatter(FuncFormatter(self.y_scaling))
if self.xbreak and self.custom_xlim:
xmin,xmax = axis[0].get_xlim()
axis[0].set_xlim(self.custom_xlim[0],xmax)
xmin,xmax = axis[-1].get_xlim()
axis[-1].set_xlim(xmin,self.custom_xlim[1])
elif self.ybreak and self.custom_ylim:
ymin,ymax = axis[0].get_ylim()
axis[0].set_ylim(ymin,self.custom_ylim[1])
ymin,ymax = axis[-1].get_ylim()
axis[-1].set_ylim(self.custom_ylim[0],ymax)
"""
See q.log for why this might be useful.
if not self.custom_xlim:
self.ax[-1].set_xlim(self.ax[-1].get_xlim()[0],self.ax[0].get_lines()[0].get_xdata()[-1])
"""
return thePlot
def remove_break_lines_x(self):
for diag in self.diags:
for l in diag:
l.remove()
self.diags = []
def show_break_lines(self):
d = 0.015
self.remove_break_lines_x()
if self.xbreak:
kwargs = dict(transform=self.ax[0].transAxes, color='k', clip_on=False)
self.diags.append(self.ax[0].plot((1-d,1+d),(-d,d),**kwargs))
self.diags[-1][0].ignore = True
self.diags.append(self.ax[0].plot((1-d,1+d),(1-d,1+d),**kwargs))
self.diags[-1][0].ignore = True
kwargs = dict(transform=self.ax[-1].transAxes, color='k', clip_on=False)
self.diags.append(self.ax[-1].plot((-d,+d),(-d,d),**kwargs))
self.diags[-1][0].ignore = True
self.diags.append(self.ax[-1].plot((-d,+d),(1-d,1+d),**kwargs))
self.diags[-1][0].ignore = True
for ax in self.ax[1:-1]:
kwargs = dict(transform=ax.transAxes, color='k', clip_on=False)
self.diags.append(ax.plot((1-d,1+d),(-d,d),**kwargs))
self.diags[-1][0].ignore = True
self.diags.append(ax.plot((1-d,1+d),(1-d,1+d),**kwargs))
self.diags[-1][0].ignore = True
self.diags.append(ax.plot((-d,+d),(-d,d),**kwargs))
self.diags[-1][0].ignore = True
self.diags.append(ax.plot((-d,+d),(1-d,1+d),**kwargs))
self.diags[-1][0].ignore = True
elif self.ybreak:
kwargs = dict(transform=self.ax[0].transAxes, color='k', clip_on=False)
self.diags.append(self.ax[0].plot((1-d,1+d),(-d,d),**kwargs))
self.diags[-1][0].ignore = True
self.diags.append(self.ax[0].plot((-d,d),(-d,d),**kwargs))
self.diags[-1][0].ignore = True
kwargs = dict(transform=self.ax[-1].transAxes, color='k', clip_on=False)
self.diags.append(self.ax[-1].plot((1-d,1+d),(1-d,1+d),**kwargs))
self.diags[-1][0].ignore = True
self.diags.append(self.ax[-1].plot((-d,d),(1-d,1+d),**kwargs))
self.diags[-1][0].ignore = True
for ax in self.ax[1:-1]:
kwargs = dict(transform=ax.transAxes, color='k', clip_on=False)
self.diags.append(ax.plot((1-d,1+d),(1-d,1+d),**kwargs))
self.diags[-1][0].ignore = True
self.diags.append(ax.plot((1-d,1+d),(-d,d),**kwargs))
self.diags[-1][0].ignore = True
self.diags.append(ax.plot((-d,d),(1-d,1+d),**kwargs))
self.diags[-1][0].ignore = True
self.diags.append(ax.plot((-d,d),(-d,d),**kwargs))
self.diags[-1][0].ignore = True
def hist(self,*args,**kwargs):
return self.ax[0].hist(*args,**kwargs)
def set_breaks(self,xbreak,ybreak):
self.xbreak = xbreak
self.ybreak = ybreak
self.breaksize = 0.02
for ax in self.ax[1:]:
self.fig.delaxes(ax)
self.ax = [self.ax[0]]
self.gs = [self.gs[0]]
self.gs[0].update(left=self.left, right=self.right, top=self.top, bottom=self.bottom, wspace=0.0)
self.ax[0].spines['right'].set_visible(True)
self.ax[0].spines['bottom'].set_visible(True)
self.ax[0].tick_params(labelright='off')
self.ax[0].tick_params(labelbottom='on')
if len(self.rax)>0:
rcoltick = self.rax[-1].get_yticklabels()[0].get_color()
ryrange = self.rax[-1].get_ylim()
self.rax[-1].set_ylabel('')
for i in range(len(self.rax)):
self.rax[i].spines['left'].set_visible(False)
self.rax[i].spines['right'].set_visible(False)
self.rax[i].tick_params(labelleft='off',left='off')
self.rax[i].tick_params(labelright='off',right='off')
for i in range(len(self.ax)):
self.ax[i].spines['left'].set_visible(False)
self.ax[i].spines['right'].set_visible(False)
self.ax[i].tick_params(labelleft='off',left='off')
self.ax[i].tick_params(labelright='off',right='off')
if self.xbreak:
nbreaks = len(self.xbreak)+1
self.gs[0].update(left=self.left, right=(self.left+self.right)/float(nbreaks)-0.5*self.breaksize, top=self.top, bottom=self.bottom, wspace=0.0)
for i in range(1,nbreaks):
self.gs.append(gridspec.GridSpec(1,1))
self.gs[i].update(left=i*(self.left+self.right)/float(nbreaks)+0.5*self.breaksize, right=min(self.right,(i+1)*(self.left+self.right)/float(nbreaks)-0.5*self.breaksize), top=self.top, bottom=self.bottom, wspace=0.0)
self.ax.append(self.fig.add_subplot(self.gs[i][:]))
self.ax[i].spines['left'].set_visible(False)
self.ax[i].spines['right'].set_visible(False)
self.ax[i].tick_params(labelleft='off',left='off')
self.ax[i].tick_params(labelright='off',right='off')
if len(self.rax)>0:
#self.rax.append(self.fig.add_subplot(self.gs[i][:]))
self.rax.append(self.ax[-1].twinx())
self.rax[i].spines['left'].set_visible(False)
self.rax[i].spines['right'].set_visible(False)
self.rax[i].tick_params(labelleft='off',left='off')
self.rax[i].tick_params(labelright='off',right='off')
self.ax[0].set_title('')
self.ax[0].set_xlabel('')
theText = self.ax[int(nbreaks/2.)].set_title(self.title)
theText.set_fontproperties(self.title_font)
if nbreaks%2==0:
theText.set_position((0,1))
theText = self.ax[int(nbreaks/2.)].set_xlabel(self.xlabel)
theText.set_fontproperties(self.label_font)
if nbreaks%2==0:
theText.set_position((0,1))
self.ax[0].yaxis.tick_left()
self.ax[-1].yaxis.tick_right()
self.ax[0].spines['left'].set_visible(True)
self.ax[0].spines['right'].set_visible(False)
self.ax[-1].spines['right'].set_visible(True)
self.ax[-1].tick_params(labelright='off')
# It must be a matplotlib bug that this is necessary.
for i in range(1,len(self.ax)-1):
self.ax[i].tick_params(labelright='off',right='off')
self.ax[i].tick_params(labelleft='off',left='off')
if len(self.rax)>0:
self.rax[-1].yaxis.tick_right()
self.rax[0].spines['left'].set_visible(False)
self.rax[0].spines['right'].set_visible(False)
self.rax[0].spines['bottom'].set_visible(False)
self.rax[-1].spines['right'].set_visible(True)
self.rax[-1].tick_params(labelright='on')
self.rax[0].tick_params(labelright='off')
self.rax[-1].tick_params(labelleft='off')
self.rax[-1].tick_params(right='on')
self.rax[0].tick_params(right='off')
self.rax[-1].tick_params(left='off')
self.rax[0].tick_params(labelbottom='off')
self.rax[-1].tick_params(labelbottom='off')
self.rax[-1].spines['right'].set_color(rcoltick)
self.ax[-1].spines['right'].set_color(rcoltick)
for tl in self.rax[-1].get_yticklabels():
tl.set_color(rcoltick)
self.rax[0].set_ylabel('')
if hasattr(self,"rylabel") and len(self.rylabel)>0:
theText = self.rax[-1].set_ylabel(self.rylabel,color=rcoltick)
#theText.set_fontproperties(self.label_font)
#print self.label_font
self.rax[-1].set_ylim(ryrange)
elif self.ybreak:
nbreaks = len(self.ybreak)+1
title = self.ax[0].get_title()
theText = self.ax[0].set_title(title)
self.gs[0].update(left=self.left, right=self.right, top=self.top, bottom=(nbreaks-1)*(self.top+self.bottom)/float(nbreaks)+0.5*self.breaksize, wspace=0.0)
for i in range(1,nbreaks):
self.gs.append(gridspec.GridSpec(1,1))
self.ax.append(self.fig.add_subplot(self.gs[i][:]))
for i in range(1,nbreaks):
self.gs[nbreaks-i].update(left=self.left, right=self.right, top=i*(self.top+self.bottom)/float(nbreaks)-0.5*self.breaksize, bottom=max(self.bottom,(i-1)*(self.top+self.bottom)/float(nbreaks)+0.5*self.breaksize), wspace=0.0)
self.ax[nbreaks-i].spines['top'].set_visible(False)
self.ax[nbreaks-i].spines['bottom'].set_visible(False)
self.ax[nbreaks-i].tick_params(labeltop='off',top='off')
self.ax[nbreaks-i].tick_params(labelbottom='off',bottom='off')
self.ax[0].set_ylabel('')
theText = self.ax[int(nbreaks/2.)].set_ylabel(self.ylabel)
theText.set_fontproperties(self.label_font)
if nbreaks%2==0:
theText.set_position((0,1))
theText = self.ax[-1].set_xlabel(self.xlabel)
self.ax[0].set_xlabel('')
theText.set_fontproperties(self.label_font)
self.ax[0].xaxis.tick_top()
self.ax[-1].xaxis.tick_bottom()
self.ax[0].spines['top'].set_visible(True)
self.ax[0].spines['bottom'].set_visible(False)
self.ax[-1].spines['bottom'].set_visible(True)
self.ax[0].tick_params(labeltop='off')
else:
theText = self.ax[0].set_xlabel(self.xlabel)
theText.set_fontproperties(self.label_font)
self.ax[0].yaxis.tick_left()
self.ax[-1].yaxis.tick_right()
self.ax[0].spines['left'].set_visible(True)
self.ax[-1].spines['right'].set_visible(True)
self.ax[0].tick_params(labelleft='on',left='on')
self.ax[-1].tick_params(labelright='off',right='on')
if len(self.rax)>0:
self.rax[-1].yaxis.tick_right()
self.rax[0].spines['left'].set_visible(False)
self.rax[0].spines['right'].set_visible(False)
self.rax[0].spines['bottom'].set_visible(False)
self.rax[-1].spines['right'].set_visible(True)
self.rax[-1].tick_params(labelright='on')
self.rax[0].tick_params(labelright='off')
self.rax[-1].tick_params(labelleft='off')
self.rax[-1].tick_params(right='on')
self.rax[0].tick_params(right='off')
self.rax[-1].tick_params(left='off')
self.rax[0].tick_params(labelbottom='off')
self.rax[-1].tick_params(labelbottom='off')
self.rax[-1].spines['right'].set_color(rcoltick)
self.ax[-1].spines['right'].set_color(rcoltick)
for tl in self.rax[-1].get_yticklabels():
tl.set_color(rcoltick)
self.rax[0].set_ylabel('')
if hasattr(self,"rylabel") and len(self.rylabel)>0:
theText = self.rax[-1].set_ylabel(self.rylabel,color=rcoltick)
#theText.set_fontproperties(self.label_font)
#print self.label_font
self.rax[-1].set_ylim(ryrange)
# Try to make sure first plot is the top one.
self.ax[0].set_zorder(1000)
if len(self.rax)>0:
self.rax[0].set_zorder(1001)
"""
for ax in self.rax:
ax.set_zorder(1001)
"""
self.fig.subplots_adjust(self.left, self.bottom, self.right, self.top)
self.set_tick_labels_font()
def set_tick_labels_font(self):
labels_x = []
labels_y = []
for ax in self.ax:
labels_x.extend(ax.get_xticklabels())
labels_y.extend(ax.get_yticklabels())
for ax in self.rax:
labels_x.extend(ax.get_xticklabels())
labels_y.extend(ax.get_yticklabels())
for xlabel in labels_x:
xlabel.set_fontproperties(self.axes_font)
for ylabel in labels_y:
ylabel.set_fontproperties(self.axes_font)
def __init__(self,fig=Figure(figsize = (800, 600), dpi=300, facecolor = '#FFFFFF'),title='',x_axis_label='',y_axis_label='',parent=None):
self.fig = fig
FigureCanvas.__init__(self,fig)
self.setFocusPolicy(QtCore.Qt.StrongFocus)
self._type = 'xy'
self.diags = []
self.xbreak = None
self.ybreak = None
self.x_scaling = None
self.y_scaling = None
self.custom_xlim = None
self.custom_ylim = None
self.custom_rylim = None
self.fix_aspect_ratio = False
self.initial_legend_position = [0.75,0.75]
self.gs = [gridspec.GridSpec(1,1)]
self.ax = [self.fig.add_subplot(self.gs[0][:])]
self.rax = []
self.defaultTextHeight = QtGui.QFontMetrics(QtGui.QFont("Bitstream Vera Sans",10)).height()
self.top = 0.95
self.left = 0.1
self.bottom=0.1
self.right=0.97
self.xintegral = False
self.yintegral = False
#font = FontProperties(family="sans-serif",style="normal",weight="normal",size="10")
font = FontProperties(family="Bitstream Vera Sans",size=10)
self.title_font = font.copy()
#self.title_font.set_weight('bold')
self.label_font = font.copy()
#self.label_font.set_weight('bold')
self.axes_font = font.copy()
#self.axes_font.set_weight('bold')
self.legend_font = font.copy()
#self.legend_font.set_weight('bold')
self.title = title
self.xlabel = x_axis_label
self.ylabel = y_axis_label
theText = self.ax[0].set_title(self.title,fontproperties=self.title_font)
self.ax[0].set_ylabel(y_axis_label,fontproperties=self.label_font)
self.ax[0].set_xlabel(x_axis_label,fontproperties=self.label_font)
self.ax[0].hold(True)
self.setMouseTracking(True)
self.mpl_connect('button_press_event', self.onClick)
self.mpl_connect('motion_notify_event', self.onMove)
self.mpl_connect('pick_event',self.onpick)
self.movingLegend = False
self.fig.subplots_adjust(self.left, self.bottom, self.right, self.top)
self.set_tick_labels_font()
self.defaultSymbolSize = 5
self._painted = False
def onpick(self,e):
try:
if hasattr(e,"mouseevent"):
mouseevent = e.mouseevent
elif hasattr(e,"lastevent"):
mouseevent = e.lastevent
dumX = float(mouseevent.xdata)
dumY = float(mouseevent.ydata)
if len(self.rax)>0:
yfrac = (self.rax[0].get_ylim()[0]-mouseevent.ydata)/(self.rax[0].get_ylim()[0]-self.rax[0].get_ylim()[1])
ydatal = self.ax[0].get_ylim()[0] - yfrac*(self.ax[0].get_ylim()[0]-self.ax[0].get_ylim()[1])
self.emit(QtCore.SIGNAL("MouseMoveEvent"),(mouseevent.xdata,ydatal))
else:
self.emit(QtCore.SIGNAL("MouseMoveEvent"),(mouseevent.xdata,mouseevent.ydata))
if len(self.rax)>0:
hl = self.fig.hitlist(mouseevent)
xlim = self.ax[0].get_xlim()
ylim = self.ax[0].get_ylim()
xtol = self.defaultSymbolSize*abs(xlim[1]-xlim[0])/self.width()
ytol = self.defaultSymbolSize*abs(ylim[1]-ylim[0])/self.height()
#print xtol, ytol
for hit in hl:
if type(hit)==matplotlib.lines.Line2D:
xdata = hit.get_xdata()
ydata = hit.get_ydata()
x_idx = (numpy.abs(xdata-mouseevent.xdata)).argmin()
#print mouseevent.xdata-xdata[x_idx], xtol
if abs(mouseevent.xdata-xdata[x_idx])0:
yfrac = (self.rax[0].get_ylim()[0]-e.ydata)/(self.rax[0].get_ylim()[0]-self.rax[0].get_ylim()[1])
ydatal = self.ax[0].get_ylim()[0] - yfrac*(self.ax[0].get_ylim()[0]-self.ax[0].get_ylim()[1])
self.emit(QtCore.SIGNAL("MouseMoveEvent"),(e.xdata,ydatal))
else:
self.emit(QtCore.SIGNAL("MouseMoveEvent"),(e.xdata,e.ydata))
if len(self.rax)>0:
hl = self.fig.hitlist(e)
xlim = self.ax[0].get_xlim()
ylim = self.ax[0].get_ylim()
xtol = self.defaultSymbolSize*abs(xlim[1]-xlim[0])/self.width()
ytol = self.defaultSymbolSize*abs(ylim[1]-ylim[0])/self.height()
#print xtol, ytol
for hit in hl:
if type(hit)==matplotlib.lines.Line2D:
xdata = hit.get_xdata()
ydata = hit.get_ydata()
x_idx = (numpy.abs(xdata-e.xdata)).argmin()
if abs(e.xdata-xdata[x_idx])\n"""
status_xml += header
NSMAP = {'xsi':"http://www.w3.org/2001/XMLSchema-instance"}
NS = NSMAP['xsi']
location_attribute = '{%s}noNamespaceSchemaLocation' % NS
bigtree = etree.Element("CCP4ApplicationOutput",nsmap = NSMAP,attrib={location_attribute: 'http://www.ysbl.york.ac.uk/~mcnicholas/schema/CCP4ApplicationOutput.xsd'})
for ns in splits[1:]:
ns = "$TABLE"+ns
newsplits.append(ns)
table = CCP4Table(ns)
tree = table.toEtree()
bigtree.append(tree)
status_xml += etree.tostring(bigtree,encoding='utf-8', pretty_print=True)
return status_xml
def CCP4LogFileNameToXML(f):
if f.endswith('.log') or f.endswith('.txt'):
fo = open(f)
b = fo.read()
fo.close()
return CCP4LogToXML(b)
else:
return CCP4LogToXML("")
def CCP4LogFileNameToEtree(f):
if f.endswith('.log') or f.endswith('.txt'):
fo = open(f)
b = fo.read()
fo.close()
return CCP4LogToEtree(b)
else:
return CCP4LogToEtree("")
if __name__ == "__main__":
if "-quit" in sys.argv:
sys.exit()
import sip
sip.setdestroyonexit( False )
app = QtGui.QApplication(sys.argv)
if getattr(sys, 'frozen', None):
basedir = sys._MEIPASS
app.addLibraryPath(os.path.join(basedir,"qt4_plugins"))
else:
#app.addLibraryPath(os.path.join(os.environ['CCP4MG'],"QtPlugins"))
app.addLibraryPath(os.path.join(os.path.dirname(__file__),'..',"QtPlugins"))
"""
t = 0
timer = QtCore.QTimer()
win = QtMatplotlibWidget()
def addRandomPoint():
import random
global t, timer, win
t = t + 1
v = random.randint(1,20)
print t*timer.interval()/1000., v
win.addPoint((t,v))
"""
def regionTest(vals,**kwargs):
print "Region VALS",vals,kwargs
def clickTest(vals,**kwargs):
print "Click VALS",vals,kwargs
xsd = None
hist = False
nomainwin = False
testla = False
select = []
import getopt
try:
opts, args = getopt.getopt(sys.argv[1:], "hnx:s:g:", ["hist", "nomainwin","testla", "xsd=", "select=","graph="])
except getopt.GetoptError, err:
# print help information and exit:
print str(err) # will print something like "option -a not recognized"
sys.exit(2)
theGraph = None
for o, a in opts:
if o in ("-h", "--hist"):
hist = True
elif o in ("-n", "--testla"):
testla = True
elif o in ("-n", "--nomainwin"):
nomainwin = True
elif o in ("-x", "--xsd"):
xsd = a
elif o in ("-s", "--select"):
items = a.strip('[').strip(']').split(',')
for item in items: select.append(item.strip("'").strip('"'))
elif o in ("-g", "--graph"):
items = a.strip('[').strip(']').split(',')
theGraph = items
else:
assert False, "unhandled option: "+o
if len(select)==0: select = None
if theGraph is not None and len(theGraph)!=2: theGraph = None
if nomainwin:
win = LogGraph()
win.layout().setContentsMargins(0,0,0,0)
win.showActionBar()
win.show()
win.raise_()
if len(sys.argv)>1:
for f in args:
graphs = win.loadFile(f,hist=hist,xsd=xsd)
if len(graphs)>0:
graph = graphs[0]
if graph:
graph.connect(graph,QtCore.SIGNAL("DetectPointClickEvent"),clickTest)
graph.connect(graph,QtCore.SIGNAL("RegionSelected"),regionTest)
elif testla:
owin = QtGui.QWidget()
layout = QtGui.QVBoxLayout()
owin.setLayout(layout)
win = LogGraph()
layout.addWidget(win)
owin.show()
owin.raise_()
if len(sys.argv)>1:
for f in args:
graphs = win.loadFile(f,hist=hist,xsd=xsd)
if len(graphs)>0:
graph = graphs[0]
if graph:
graph.connect(graph,QtCore.SIGNAL("DetectPointClickEvent"),clickTest)
graph.connect(graph,QtCore.SIGNAL("RegionSelected"),regionTest)
selectorWidget = QtGui.QWidget()
selectorLayout = QtGui.QVBoxLayout()
selectorWidget.setLayout(selectorLayout)
layout.addWidget(selectorWidget)
def drawLineSelector():
import sip
child = selectorWidget.layout().takeAt(0)
while child:
if child:
if hasattr(child,"widget") and child.widget() is not None:
sip.delete(child.widget())
sip.delete(child)
child = selectorWidget.layout().takeAt(0)
if win.graph and win.graph.currentWidget() and win.graph.currentWidget().currentWidget():
currentGraph = win.graph.currentWidget().currentWidget()
if hasattr(currentGraph,"canvas") and currentGraph.canvas:
if hasattr(currentGraph.canvas,"fig") and currentGraph.canvas.fig:
if len(currentGraph.canvas.fig.get_axes())>0:
lines = currentGraph.canvas.fig.get_axes()[0].get_lines()
lines = [l for l in lines if not hasattr(l,"ignore")]
for l in lines:
cb = QtGui.QCheckBox(l.get_label())
if l.get_visible():
cb.setChecked(True)
selectorWidget.layout().addWidget(cb)
cb.stateChanged.connect(l.set_visible)
cb.stateChanged.connect(currentGraph.canvas.draw)
win.currentTableChanged.connect(drawLineSelector)
win.currentDataChanged.connect(drawLineSelector)
drawLineSelector()
else:
win = LogGraphMainWindow()
win.layout().setContentsMargins(0,0,0,0)
win.show()
win.raise_()
if len(sys.argv)>1:
for f in args:
graphs = win.loggraph.loadFile(f,hist=hist,xsd=xsd,select=select)
if graphs is not None and len(graphs)>0:
graph = graphs[0]
if graph:
graph.connect(graph,QtCore.SIGNAL("DetectPointClickEvent"),clickTest)
graph.connect(graph,QtCore.SIGNAL("RegionSelected"),regionTest)
if theGraph is not None:
try:
win.loggraph.table_combo.setCurrentIndex(int(theGraph[0]))
win.loggraph.data_combo.setCurrentIndex(int(theGraph[1]))
except:
print "Failed to set graph",theGraph
sys.exit(app.exec_())