Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

Content

Table of Contents

Parsing of input parameters

Parsing "on knees"

Code Block
import sys
import os

def get_input_parameters() :
    nargs = len(sys.argv)
    print 'sys.argv[0]: ', sys.argv[0]
    print 'nargs: ', nargs
    # Then do something with arguments...

Use OptionParser

Code Block
from optparse import OptionParser

def input_option_parser() :

    def_fname = 'spec-xppi0412-r0060-20120507-125420.198726277.txt'
    def_cols = 100

    parser = OptionParser(description='Process optional input parameters.', usage = "usage: %prog [options]")
    parser.add_option('-f', '--fname', dest='fname', default=def_fname, action='store', type='string', help='input file name')
    parser.add_option('-c', '--cols', dest='cols', default=def_cols, action='store', type='int', help='number of columns in the image array')
    parser.add_option('-v', dest='verbose', action='store_true',  help='set flag to print more details',  default=True)
    parser.add_option('-q', dest='verbose', action='store_false', help='set flag to print less details')
    (opts, args) = parser.parse_args()

    print 'opts:',opts
    print 'args:',args

    return (opts, args)

Manipulation with directories and files

Access to files in the derectory

Code Block
def getListOfFilesInDir(dirname) :
    return os.listdir(dirname)

def printListOfFilesInDir(dirname) :
    print 'List of files in the dir.', dirname
    for name in os.listdir(dirname) :
        print name
    print '\n'

Parsing the pathname

Code Block
        root, ext = os.path.splitext(path) # i.e. path='root-part.tail-part'
        basename  = os.path.basename(path)
        dirname   = os.path.dirname(path)
        lexist    = os.path.lexists(path)
        isfile    = os.path.isfile(path)
        isdir     = os.path.isdir(path)
        head, tail= os.path.split(path)    # i.e. path='head-part/tail-part'
...

http://docs.python.org/library/os.path.html

Joint path and name

Code Block
        path_name = os.path.join(path,fname)

Useful string parsing options

http://docs.python.org/library/string.html

Code Block
    string.rsplit(str, sep, maxsplit)
    string.capitalize(word)
    string.lower(s)
    start = string.find(symbolic_string, pattern)
    pattern_length = len(pattern)

http://docs.python.org/library/parser.html?

Or use more shorter methods for str object:
http://docs.python.org/library/stdtypes.html, for example:

Code Block
    par_str = line[pos_eq+1:].strip(' ').rstrip('\n')

Replace the part of the string

Code Block
 my_string.replace("abcde","cde")

Python - useful references

Built-in functions

http://docs.python.org/library/functions.html

setattr - gives dynamic variables in python

http://docs.python.org/library/functions.html#setattr

String formatting

Code Block
s = 'some text %s  %s' % (msg.ljust(30), str(val).rjust(30)

PyQt4

PyQt4 class references

All classes
Selected:

Open/close/move other GUI window

Try to close window if its object exists, othervise - open:

Code Block
    def processConfigPars(self):
        print 'processConfigPars'
        try :
            cp.confpars.guiconfigparameters.close()
        except : # AttributeError: #NameError 
            cp.confpars.guiconfigparameters = guiconfigpars.GUIConfigParameters()
            cp.confpars.guiconfigparameters.move(self.pos().__add__(QtCore.QPoint(100,330))) # window offset
            # or use self.parentWidget().pos() for combined widgets:
            # cp.guifilebrowser.move(self.parentWidget().pos().__add__(QtCore.QPoint(240,40)))
            cp.confpars.guiconfigparameters.show()
Note

Sometime it looks like the window does not want to move in specified position...
In particular I have observed, that everything is going correct untill the w.show(). then, suddenly happens moveEvent(), which changes the self.pos(). In my case it happened because at construction of the combined window, its size was changed and it was moved in origin... Reservation of larger window size solved this problem.

Close window and delete object

Code Block
    def closeEvent(self, event):
        try: # try to delete self object in the cp.confpars
            del cp.confpars.guiconfigparameters 
        except # AttributeError:
            pass # silently ignore

Change style of buttons depending on status

For particular QPushButton it works:

Code Block
self.but_path = QtGui.QPushButton('File:')
self.but_path.setObjectName('but_path')
self.but_path.setStyleSheet('QPushButton#but_path:pressed  {color: black; background-color: green;}' +
                            'QPushButton#but_path:disabled {color: white; background-color: pink;}' +
                            'QPushButton                   {color:  blue; background-color: yellow;}')

For entire application it should be like:

Code Block
app = QtGui.QApplication.instance()
app.setStyleSheet('QLabel{color: #fff;} QPushButton{background-color: #000; color: #fff}')

but does not work for me...

Make window visible on the top

Code Block
 widg.raise_()

Scroll down text in

Assuming

Code Block
 self.box_txt = QtGui.QTextEdit()
 self.box_txt.setText('some text')
 self.box_txt.append('a lot of additional text, exceeding the window size')
 self.box_txt.ensureCursorVisible()

Scroll bar can be used, but result is not seen imidiately:

Code Block
  scrol_bar_v = self.box_txt.verticalScrollBar() # QScrollBar
  scrol_bar_v.setValue(scrol_bar_v.maximum()) 

Moving text cursor with repaint() works immidiately:

Code Block
  self.box_txt.moveCursor(QtGui.QTextCursor.End)
  self.box_txt.repaint()

Set optimal table-widget size

Code Block
    self.table = QtGui.QTableWidget(rows, cols, self)
    ...
    self.table.setFixedWidth(self.table.horizontalHeader().length() + 4)
    self.table.setFixedHeight(self.table.verticalHeader().length() + 29)

Show image in QLabel

Assumes:

Code Block
class GUIImage ( QtGui.QLabel ) :
    def __init__ (self, parent=None, app=None) :

        QtGui.QLabel.__init__(self, parent)

        self.setGeometry(200, 100, 100, 100)
        self.setWindowTitle('Image For Grabber')

        self.setFrame()
        ...

i.e. self is an instance of QLabel.

Set pixmap for image

Code Block
    def setPixmapForImage(self):
        if self.r_pixmap == None :
            self.s_pixmap = None
            self.clear()
        else :
            self.s_pixmap = self.r_pixmap.scaled(self.size(), QtCore.Qt.KeepAspectRatio)
            self.setPixmap(self.s_pixmap)
            self.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft)
            self.setScailedMask()

Grab image from monitor

Code Block
    def grabImage(self):
        fname = tempfile.NamedTemporaryFile(mode='r+b',suffix='.ppm')
        if( 0 == os.system('import -trim -frame -border %s' % (fname.name))) :
            self.r_pixmap = QtGui.QPixmap(QtGui.QImage(fname.name)) 
            self.setPixmapForImage()

Grab entire monitor window

Code Block
    def grabEntireWindow(self):
        self.r_pixmap = QtGui.QPixmap.grabWindow(QtGui.QApplication.desktop().winId())
        self.setPixmapForImage()

Load image from file

Code Block
   def loadImageFromFile(self, fname) : 
        #Read formats: bmp, jpg, jpeg, png, ppm, xbm, xpm + gif, pbm, pgm, 
        self.r_pixmap = QtGui.QPixmap(QtGui.QImage(fname))     
        self.setPixmapForImage()

Set the mask to suppress the background layer

Code Block
    def setScailedMask(self):
        size = self.s_pixmap.size()
        print 'Scaled pixmap size: %d x %d' % (size.width(), size.height())
        #==================================
        self.qimage_mask = QtGui.QImage(size, QtGui.QImage.Format_Mono)
        self.qimage_mask.fill(0)
        self.qbitmap_mask = QtGui.QBitmap.fromImage(self.qimage_mask)
        self.s_pixmap.setMask(self.qbitmap_mask)
        #==================================

Save image in file

Code Block
    def saveImageInFile(self, fname='test.png'): 
        #Write formats: bmp, jpg, jpeg, png, pbm, pgm, ppm, xbm, xpm
        if self.r_pixmap is not None :
            self.r_pixmap.save(fname, format=None)

Set transparent frame

Code Block
    def setFrame(self):
        self.frame = QtGui.QFrame(self)
        self.frame.setFrameStyle( QtGui.QFrame.Box | QtGui.QFrame.Sunken ) #Box, Panel | Sunken, Raised 
        self.frame.setLineWidth(0)
        self.frame.setMidLineWidth(1)
        self.frame.setGeometry(self.rect())
        #self.frame.setVisible(False)
        self.frame.setStyleSheet('background: transparent;') 

Resize event

Code Block
    def resizeEvent(self, e):
        s = self.size()
        self.frame.setGeometry(QtCore.QRect(0,0,s.width(),s.height()))
        self.setPixmapForImage()

Show image in QtGui.QGraphicsView

QGraphicsView is a class with scrolled graph window...

Graphics in PyQt4

Code Block
...
        self.poi1  = QtCore.QPoint(0,0)
        self.poi2  = QtCore.QPoint(0,0)
        self.rect1 = QtCore.QRect()
        self.rect2 = QtCore.QRect()

        self.pen1 = QtGui.QPen(QtCore.Qt.black) 
        self.pen2 = QtGui.QPen(QtCore.Qt.white) 
        self.pen1.setStyle(QtCore.Qt.DashLine) 
        self.pen2.setStyle(QtCore.Qt.DashLine) 
        self.pen1.setWidthF(1) 
        self.pen2.setWidthF(1)
...

     def paintEvent(self, e):
        super(GUIImage,self).paintEvent(e)
        qp = QtGui.QPainter()
        # or QPainter can be defined earlier and use it as   qp = self.qp
        qp.begin(self)
        #self.drawPixmap(qp)
        self.drawRect(qp)
        qp.end()
        self.update()

    def setPen(self, qp):
        self.pen.setStyle(QtCore.Qt.DashLine) 
        self.pen.setWidthF(1) 

    def drawRect(self, qp):
        if self.r_pixmap == None:
            return

        p1x, p1y = self.poi1.x(), self.poi1.y()
        p2x, p2y = self.poi2.x(), self.poi2.y()

        R=1
        if abs(p2x-p1x) < R : return
        if abs(p2y-p1y) < R : return

        self.rect1.setCoords( p1x,   p1y,   p2x,   p2y)
        self.rect2.setCoords( p1x+1, p1y+1, p2x-1, p2y-1)
        qp.setPen  (self.pen1)
        qp.drawRect(self.rect1);
        qp.setPen  (self.pen2)
        qp.drawRect(self.rect2);


    def drawPixmap(self, qp):
        if self.r_pixmap != None:
            qp.drawPixmap(0,0,self.s_pixmap)

See other draw options in QPainter class reference.

Style options

Code Block
    self.styleTransp = "background-color: rgb(255,   0,   0, 100);"
    self.styleTitle  = "background-color: rgb(239, 235, 231, 255); color: rgb(100, 160, 100);" # Gray bkgd
    self.styleWhite  = "background-color: rgb(255, 255, 255); color: rgb(0, 0, 0);" 
    self.styleTitleBold = self.styleTitle + 'font-size: 18pt; font-family: Courier; font-weight: bold;'
    self.styleWhiteFixed= self.styleWhite + 'font-family: Fixed;'

    self.colorEditInfo = QtGui.QColor(100, 255, 200)
    self.colorEditBad  = QtGui.QColor(255,   0,   0)
    self.colorEdit     = QtGui.QColor('white') 

    self.but_close .setStyleSheet (cp.styleButton)
    self.but_close .setFlat(True)
    self.but_logger.setVisible(True) 
    self.box_txt   .setReadOnly(True)
    self.tit_title .setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignCenter)
    self.but_logger.setIcon(cp.icon_contents)

    self.setMinimumWidth(400)
    self.setMinimumHeight(320)
    self.setMinimumSize(600,700)
    self.setFixedHeight(350)

Icons

Code Block
     path = './icons/'
     self.icon_contents = QtGui.QIcon(path + 'contents.png')
     self.but_logger.setIcon(cp.icon_contents)

Tooltips

Code Block
        self.edi_usr.setToolTip('Sender of the message')

Matplotlib

In examples below we assume

Code Block
fig = plt.figure(num=1, figsize=(10,10), dpi=100, facecolor='w',edgecolor='w',frameon=True)
axes = fig.add_subplot(111)
axim = axes.imshow(arrwin, interpolation='nearest', origin='bottom', aspect='auto', extent=[xmin, xmax, ymax, ymin])

Save figure in file

Code Block
fig.savefig(fname, dpi=240)

Clear figure

Code Block
fig.clear()

Graphic

Code Block
axes.plot(xarr1, yarr1, '-r', xarr2, yarr2,  '-g')

Histogram

Code Block
axes.hist(arr, bins=100, range=(10,50), log=False) # log for vertical scale only

Image (with colorbar)

Code Block
img = axes.imshow(arr2d, interpolation='nearest', origin='bottom', aspect='auto')
img.set_clim(Amin,Amax)

cbar = self.fig.colorbar(img, orientation='vertical', \
                         fraction=0.1, pad=0.01, shrink=1.0, aspect=20)

        # fraction - of the 2d plot occupied by the color bar
        # pad      - is a space between 2d image and color bar
        # shrink   - factor for the length of the color bar
        # aspect   - ratio length/width of the color bar

Color bar as a separate sub-plot

Code Block
axcb = fig.add_axes([0.1,  0.1, 0.8, 0.1]) # x0, y0, width, height
cbar = fig.colorbar(img, cax=axcb, orientation='horizontal', \
                    fraction=0.1, pad=0.01, shrink=1.0, aspect=20)
axcb.xaxis.set_ticks_position('top') # change position of axis labels

Define subplot(s) with empty axes

Code Block
axes  = fig.add_subplot(111)        

or

Code Block
axes1  = fig.add_subplot(211)        
axes2  = fig.add_subplot(212)        

Make figure with non-equal subplots

Code Block
                    # x0, y0, width, height
axgr = fig.add_axes([0.1,  0.64, 0.80, 0.35])
axhi = fig.add_axes([0.1,  0.14, 0.35, 0.35])
axti = fig.add_axes([0.55, 0.14, 0.35, 0.35])

or using grid:

Code Block
import matplotlib.gridspec as gridspec
gs   = gridspec.GridSpec(20, 20)
# Naive direction        [  Y   ,   X ]
axsa = fig.add_subplot(gs[ 1:16,  0:14])
axsb = fig.add_subplot(gs[ 1:16, 14:19])
axsc = fig.add_subplot(gs[16:  ,  0:14])

Set axes limits

Code Block
    
axes.set_xlim((-50,50))
axes.set_ylim((-10,210))

Draw line

Code Block
import matplotlib.lines  as lines
line = lines.Line2D(arrx, arry, linewidth=1, color='r')   
axes.add_artist(line)

Set a number of ticks along the axis

Code Block
from matplotlib.ticker import MaxNLocator
axes.xaxis.set_major_locator(MaxNLocator(4))

Axis without tick-labels

Code Block
import matplotlib.ticker as mtick
axes.xaxis.set_major_formatter( mtick.NullFormatter() )

Rotate axis tick-labels

Code Block
for label in axes.get_xticklabels() :
    label.set_rotation(60)                  # rotate by 60 degree
    label.set_horizontalalignment('center') # 'right', etc.

Change axis tick-label position on the plot

Code Block
axes.xaxis.set_ticks_position('top')
axes.yaxis.set_ticks_position('right')

Change axis tick-label font size

Code Block
axes.tick_params(axis='both', which='major', labelsize=8)

Axes labels and size

Code Block
axes.set_xlabel('Time index', fontsize=10)
axes.set_ylabel('dt(sec)', fontsize=8)

Axes labels with LaTeX symbols

Use raw string with LaTeX notations inside:

Code Block
axes.set_xlabel(r'$\rho A_i$')

Text in axes

Code Block
plt.text(x, y, text, fontsize=7, color='k', ha='left', rotation=45)
axes.text(x, y, text, fontsize=7, color='k', ha='left', rotation=45)

Window title for figure

Code Block
    fig  = plt.figure(figsize=(15,5), dpi=80, facecolor='w',edgecolor='w',frameon=True)
    fig.canvas.set_window_title('Image And Spectrum ' + u'\u03C6')

Axes title

Code Block
    
plt.title('Image',color='b',fontsize=20)
or
axes.set_title('Image',color='b',fontsize=20)

Log scale methods

Log values:

Code Block
    
from math import log10
log_vmin, log_vmax = log10(vmin), log10(vmax)

Log scale axes:

Code Block
axes.set_xscale('log')
axes.set_yscale('log')

Log scale image data:

Code Block
self.arr2d = np.log10(self.arrwin)
self.imsh = axis.imshow(self.arr2d, origin='upper', \
                                          interpolation='nearest', \
                                          extent=self.range, aspect='auto')
self.imsh.set_clim(log_vmin,log_vmax)

Histogram with log statistics (y axis):

Code Block
axes.hist(self.arrwin.flatten(), bins=self.nbins, range=self.range_his, log=True)

Plot histogram with log bin size:

Code Block
logbins=10**np.linspace(log_vmin, log_vmax, nbins)
# or:
logbins=np.logspace(log_vmin, log_vmax, nbins)
self.axhi.hist(self.arrwin.flatten(), bins=logbins )  

Window title

Code Block
    
    fig.canvas.set_window_title('Image And Spectrum ' + u'\u03C6')

Add unicode symbols in string

Code Block
    
    str = 'Symbol phi: ' + u'\u03C6'

Get canvas and connect it with mouse buttons

Code Block
canvas = fig.canvas
canvas.mpl_connect('button_press_event',   self.processMouseButtonPress) 
canvas.mpl_connect('button_release_event', self.processMouseButtonRelease) 
canvas.mpl_connect('motion_notify_event',  self.processMouseMotion)

...

    def processMouseButtonPress(self, event) :
        print 'MouseButtonPress'
        print 'event: xdata, ydata, x, y =', event.xdata, event.ydata, event.x, event.y

        if event.inaxes == self.axgr : self.mousePressOnGraph(event)
        if event.inaxes == self.axti : self.mousePressOnGraph(event)
        if event.inaxes == self.axhi : self.mousePressOnHisto(event)

        if event.button == 1 : # 1=left, 2=middle, 3=right
            self.gr_xmin = float(event.xdata)

At the edge of matplotlib and PyQt4

We assume that everything is done in our backend basis:

Code Block
import matplotlib
matplotlib.use('Qt4Agg')
import matplotlib.pyplot as plt

Check and set backend

Code Block
import matplotlib
if matplotlib.get_backend() != 'Qt4Agg' : 
    matplotlib.use('Qt4Agg')

Get the current matplotlib figure window position on monitor

Code Block
pos = fig.canvas.manager.window.pos()
print 'x,y=', pos.x(), pos.y()

Move the matplotlib figure window in certain (x,y) position

Code Block
fig.canvas.manager.window.move(x,y) # in pixels from top-left corner

or

Code Block
plt.get_current_fig_manager().window.move(90, 100)

For our backend starting from python 2.7.2:

Code Block
plt.get_current_fig_manager().window.geometry("+100+300")

Move the matplotlib figure window on top (of all pileup windows)

Code Block
fig.canvas.manager.window.activateWindow() # Makes window active
fig.canvas.manager.window.raise_()         # Moves window on top

the attribute trick is that the fig.canvas.manager.window returns the QtGui.QMainWindow, which is subclass of QtGui.QWidget with all that useful methods.

Add figure as a widget of the QtGui

Code Block
fig = plt.figure(num=None figsize=(5,10), dpi=100, facecolor='w',edgecolor='w',frameon=True)
vbox = QtGui.QVBoxLayout()
vbox.addWidget(fig.canvas)    # Wraps figure canvas in widget 
self.setLayout(vbox)

How to recieve a signal in program when window is activated by the mouse click on frame ?

I do not know yet...

But, if you click on figure canvas (the region inside the window frame, use

Code Block
        fig.canvas.mpl_connect('button_press_event', self.onButtonPressEvent) 

#Should be implemented something like:
    def onButtonPressEvent( self, event ):
        """Figure is picked"""
        print 'click on fig number =', event.canvas.figure.number

Receive a signal in program when close window by the click on "X"

Code Block
        fig.canvas.mpl_connect('close_event', self.onCloseEvent)

#Should be implemented something like:
    def onCloseEvent( self, event ):
        print 'close event, fig number =', event.canvas.figure.number

Close figure from program call

Code Block
plt.close( num ) # close figure with known number num
...
plt.close('all') # close all figures

Emit your own signal in PyQt4

Code Block
from PyQt4 import QtGui, QtCore
class Drag ( QtCore.QObject ):
    def __init__(self) :
        QtCore.QObject.__init__(self, None) # need it for signal exchange...
    ...

        self.emit( QtCore.SIGNAL('new_xy_center(int,int)'), x, y)

Receive your own signal in PyQt4

Code Block
from PyQt4 import QtGui, QtCore 
class BatchJobCorAna( QtCore.QObject ) : 
    def __init__(self) :
        QtCore.QObject.__init__(self, None) # need it for signal exchange...
    ...

    def connectToThread1(self):
        #try : self.connect( thread1, QtCore.SIGNAL('update(QString)'), self.updateStatus )
        try : self.connect( thread1, QtCore.SIGNAL('new_xy_center(int,int)'), self.updateStatus )
        except : logger.warning('connectToThread1 IS FAILED !!!', __name__)

    def updateStatus(self, x, y):
        print 'BatchJobCorAna: Signal is recieved, x,y=', x, y 

where thread1 is an object emiting the signal.

NumPy

Import

Code Block
#!/usr/bin/env python
  import numpy as np

Read numpy array from text file

Code Block
    nparr = np.loadtxt('arr.txt', dtype=np.float)

errors = 0.5*np.random.normal(size=len(yn))

Save numpy arrays

Code Block
    np.savetxt(fname, array) # , fmt='%f')
    np.save(fname, array)
    np.savez(fname, [array1, array2,...])

Save image in TIFF file

Code Block
bgColor#DDFFFF
import scipy.misc as scim
    scim.imsave('fname.tiff', arr2d)

Other supported formats: gif, pdf, png, jpeg, eps

Read image from TIFF file

Code Block
bgColor#DDFFFF
import scipy.misc as scim
    arr2d = scim.imread('fname.tiff')

SciPy

Import

Code Block
#!/usr/bin/env python
import numpy as np
from scipy.optimize import curve_fit

Fit to data

Reference to scipy.optimize.curve_fit
Fitting data example

Working example:

Code Block
#!/usr/bin/env python
import numpy as np
from scipy.optimize import curve_fit

def func(x, a, b, c):
    return a*np.exp(-b*x) + c

p0 = [2.5, 1.3, 0.5]
x = np.linspace(0, 5, 50)
y = func(x, *p0)

yn = y + 0.2*np.random.normal(size=len(x))
en = 1.1*np.random.normal(size=len(x))

popt, pcov = curve_fit(func, x, yn, p0, en)

yf = func(x, *popt)

print "p0   = ", p0
print "popt = ", popt
print "pcov:\n", pcov

# Let's plot it now
import matplotlib.pyplot as plt

plt.plot( #x, y,  'r-', \
           x, yn, 'g^', \
           x, yf, 'bs-')
plt.show()