Efficient way to build multiple images with lots of patches in matplotlib?

I am writing code that displays function matches between images. At the moment, the code is pretty slow. I have some ideas on how to speed it up, but I'm not 100% more comfortable with matplotlib and how its work is behind the scenes.

Basic code structure: (I leave things to make them more readable)

from matplotlib.patches import Rectangle, Circle, Ellipse
import matplotlib.gridspec as gridspec
from matplotlib.transforms import Affine2D
from scipy.linalg import inv, sqrtm
import matplotlib.pyplot as plt
import numpy as np
  • Add list images. Each image gets its own axis: ax and remembers ax.transData p>

    gs = gridspec.GridSpec( nr, nc )
    for i in range(num_images):
         dm.ax_list[i] = plt.subplot(gs[i])
         dm.ax_list[i].imshow( img_list[i])
         transData_list[i] = dm.ax_list[i].transData
    
  • Visualize the function as ellipses

    for i in range(num_chips):
         axi =  chips[i].axi 
         ax  =  dm.ax_list[axi]
         transData = dm.transData_list[axi]
         chip_feats = chips[i].features
         for feat in chip_feats:
             (x,y,a,c,d) = feat
             A = numpy.array( [ ( a, 0, 0 ) ,
                                      ( c, d, 0 ) ,
                                      ( 0, 0, 1 ) ] , dtype=np.float64)
             EllShape = Affine2D( numpy.array(sqrtm( inv(A) ), dtype=np.float64) )
             transEll  = EllShape.translate(x,y)
             unitCirc = Circle((0,0),1,transform=transEll+transData)
             ax.add_patch(unitCirc)
    

RunSnakeRun , , , , . , , matplotlib, , , , , , .

:

4 , /.

(300 ), . , . , .

, , , - , .

, :

  • ? matplotlib?
  • , ?
  • ? , ? ?
  • sqrtm (inv (A)) A? , ?
  • pyqtgraph? , . (, ).

:

, . .

:

 A = numpy.array( [ ( a, 0, 0 ) ,
                          ( c, d, 0 ) ,
                          ( 0, 0, 1 ) ] , dtype=np.float64)
 EllShape = Affine2D( numpy.array(sqrtm( inv(A) ), dtype=np.float64) )

 EllShape = Affine2D([\
 ( 1/sqrt(a),         0, 0),\
 ((c/sqrt(a) - c/sqrt(d))/(a - d), 1/sqrt(d), 0),\
 (         0,         0, 1)])

:

  num_to_run = 100000
  all_setup  = ''' import numpy as np ; from scipy.linalg import sqrtm ; from numpy.linalg import inv ; from numpy import sqrt
  a=.1 ; c=43.2 ; d=32.343'''

  timeit( \
  'sqrtm(inv(np.array([ ( a, 0, 0 ) , ( c, d, 0 ) , ( 0, 0, 1 ) ])))',\
  setup=all_setup, number=num_to_run)
   >> 22.2588094075 #(Matlab reports 8 seconds for this run) 

  timeit(\
  '[ (1/sqrt(a), 0, 0), ((c/sqrt(a) - c/sqrt(d))/(a - d), 1/sqrt(d), 0), (0, 0, 1) ]',\
  setup=all_setup,  number=num_to_run)
  >> 1.10265190941 #(Matlab reports .1 seconds for this run) 

2

Ive ( ) PatchCollection . , , .

 from matplotlib.collections import PatchCollection
 ell_list = []
 for i in range(num_chips):
     axi =  chips[i].axi 
     ax  =  dm.ax_list[axi]
     transData = dm.transData_list[axi]
     chip_feats = chips[i].features
     for feat in chip_feats:
         (x,y,a,c,d) = feat
         EllShape = Affine2D([\
            ( 1/sqrt(a),         0, x),\
            ((c/sqrt(a) - c/sqrt(d))/(a - d), 1/sqrt(d), y),\
            (         0,         0, 1)])
         unitCirc = Circle((0,0),1,transform=EllShape)
         ell_list = [unitCirc] + ell_list
    ellipses = PatchCollection(ell_list)
    ellipses.set_color([1,1,1])
    ellipses.face_color('none') #'none' gives no fill, while None will default to [0,0,1]
    ellipses.set_alpha(.05)
    ellipses.set_transformation(transData)
    ax.add_collection(ellipses)
+5
1

, . .

:

 A = numpy.array( [ ( a, 0, 0 ) ,
                          ( c, d, 0 ) ,
                          ( 0, 0, 1 ) ] , dtype=np.float64)
 EllShape = Affine2D( numpy.array(sqrtm( inv(A) ), dtype=np.float64) )

 EllShape = Affine2D([\
 ( 1/sqrt(a),         0, 0),\
 ((c/sqrt(a) - c/sqrt(d))/(a - d), 1/sqrt(d), 0),\
 (         0,         0, 1)])

:

  num_to_run = 100000
  all_setup  = ''' import numpy as np ; from scipy.linalg import sqrtm ; from numpy.linalg import inv ; from numpy import sqrt
  a=.1 ; c=43.2 ; d=32.343'''

  timeit( \
  'sqrtm(inv(np.array([ ( a, 0, 0 ) , ( c, d, 0 ) , ( 0, 0, 1 ) ])))',\
  setup=all_setup, number=num_to_run)
   >> 22.2588094075 #(Matlab reports 8 seconds for this run) 

  timeit(\
  '[ (1/sqrt(a), 0, 0), ((c/sqrt(a) - c/sqrt(d))/(a - d), 1/sqrt(d), 0), (0, 0, 1) ]',\
  setup=all_setup,  number=num_to_run)
  >> 1.10265190941 #(Matlab reports .1 seconds for this run) 

2

Ive ( ) PatchCollection . , , .

 from matplotlib.collections import PatchCollection
 ell_list = []
 for i in range(num_chips):
     axi =  chips[i].axi 
     ax  =  dm.ax_list[axi]
     transData = dm.transData_list[axi]
     chip_feats = chips[i].features
     for feat in chip_feats:
         (x,y,a,c,d) = feat
         EllShape = Affine2D([\
            ( 1/sqrt(a),         0, x),\
            ((c/sqrt(a) - c/sqrt(d))/(a - d), 1/sqrt(d), y),\
            (         0,         0, 1)])
         unitCirc = Circle((0,0),1,transform=EllShape)
         ell_list = [unitCirc] + ell_list
    ellipses = PatchCollection(ell_list)
    ellipses.set_color([1,1,1])
    ellipses.face_color('none') #'none' gives no fill, while None will default to [0,0,1]
    ellipses.set_alpha(.05)
    ellipses.set_transformation(transData)
    ax.add_collection(ellipses)
0

All Articles