Graphs/statistics using wxPython

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jan Danielsson

    #1

    Graphs/statistics using wxPython

    Hello all,

    I wanted to plot some statistics, so I wrote a simple wxPython class
    to do it. Then I realized that I would like to draw bar graphs, so I
    added that too.

    Since I'm a complete Python newbie, I haven't done much of it the
    "Python way", I suspect. So, I'm wondering if someone would like to show
    me some of the tricks I should have used.

    You can find the code at:


    It's not finished[*], but it is usable. Oh, you can do whatever you
    want with it. Since I had never touched wxPython before working with
    this, I used some doodle application as a starting point.

    Btw... Has anyone already written statistics classes for wxPython? If
    so, where can I find them? If nothing similar exists, I'll probably add
    support for loading data from a file, and a few other features. Feel
    free to make requests or enhancements.
    [*] There are some size/offset bugs which I am aware of, but they are
    easily fixed. I just haven't got around to it yet.
  • Robert Kern

    #2
    Re: Graphs/statistics using wxPython

    Jan Danielsson wrote:[color=blue]
    > Hello all,
    >
    > I wanted to plot some statistics, so I wrote a simple wxPython class
    > to do it. Then I realized that I would like to draw bar graphs, so I
    > added that too.
    >
    > Since I'm a complete Python newbie, I haven't done much of it the
    > "Python way", I suspect. So, I'm wondering if someone would like to show
    > me some of the tricks I should have used.[/color]

    Trick #1:

    import matplotlib

    ;-)

    --
    Robert Kern
    rkern@ucsd.edu

    "In the fields of hell where the grass grows high
    Are the graves of dreams allowed to die."
    -- Richard Harter

    Comment

    • Jan Danielsson

      #3
      Re: Graphs/statistics using wxPython

      Robert Kern wrote:[color=blue][color=green]
      >> I wanted to plot some statistics, so I wrote a simple wxPython class
      >> to do it. Then I realized that I would like to draw bar graphs, so I
      >> added that too.
      >>
      >> Since I'm a complete Python newbie, I haven't done much of it the
      >> "Python way", I suspect. So, I'm wondering if someone would like to show
      >> me some of the tricks I should have used.[/color]
      >
      >
      > Trick #1:
      >
      > import matplotlib[/color]

      Oh. :-)

      That's a pretty neat trick -- now can you make my embarrassment go away?

      I did do a quick search to see if anyone had done anything similar;
      but I guess I wasn't using the right keywords.
      [color=blue]
      > ;-)[/color]

      You may point and laugh.

      Damn, that's a neat toolkit! Thanks for pointing me to it!

      Comment

      • Robert Kern

        #4
        Re: Graphs/statistics using wxPython

        Jan Danielsson wrote:[color=blue]
        > Robert Kern wrote:[/color]
        [color=blue][color=green]
        >>Trick #1:
        >>
        >>import matplotlib[/color]
        >
        > Oh. :-)
        >
        > That's a pretty neat trick -- now can you make my embarrassment go away?
        >
        > I did do a quick search to see if anyone had done anything similar;
        > but I guess I wasn't using the right keywords.
        >[color=green]
        >>;-)[/color]
        >
        > You may point and laugh.
        >
        > Damn, that's a neat toolkit! Thanks for pointing me to it![/color]

        It's okay. Just about every Pythonista in the sciences has, at one time
        or another, started a plotting library. It's a rite of passage. Welcome
        to the club. :-)

        --
        Robert Kern
        rkern@ucsd.edu

        "In the fields of hell where the grass grows high
        Are the graves of dreams allowed to die."
        -- Richard Harter

        Comment

        • Jan Danielsson

          #5
          Re: Graphs/statistics using wxPython

          Robert Kern wrote:
          [---][color=blue]
          > It's okay. Just about every Pythonista in the sciences has, at one time
          > or another, started a plotting library. It's a rite of passage. Welcome
          > to the club. :-)[/color]

          Question: I need to install SciPy in order to use matplotlib, but on
          the download page I see that there are versions for Python 2.2.x and
          2.3.x. I use 2.4.1 -- will bad things happen if I try to use the build
          for 2.3.x?

          Comment

          • Robert Kern

            #6
            Re: Graphs/statistics using wxPython

            Jan Danielsson wrote:[color=blue]
            > Robert Kern wrote:
            > [---]
            >[color=green]
            >>It's okay. Just about every Pythonista in the sciences has, at one time
            >>or another, started a plotting library. It's a rite of passage. Welcome
            >>to the club. :-)[/color]
            >
            > Question: I need to install SciPy in order to use matplotlib,[/color]

            No you don't.
            [color=blue]
            > but on
            > the download page I see that there are versions for Python 2.2.x and
            > 2.3.x. I use 2.4.1 -- will bad things happen if I try to use the build
            > for 2.3.x?[/color]

            Yes. Scipy has many extension modules; such modules built for 2.3.x
            won't work for 2.4.x, etc.

            --
            Robert Kern
            rkern@ucsd.edu

            "In the fields of hell where the grass grows high
            Are the graves of dreams allowed to die."
            -- Richard Harter

            Comment

            • Jan Danielsson

              #7
              Re: Graphs/statistics using wxPython

              Robert Kern wrote:[color=blue][color=green]
              >> [---]
              >>[color=darkred]
              >>> It's okay. Just about every Pythonista in the sciences has, at one time
              >>> or another, started a plotting library. It's a rite of passage. Welcome
              >>> to the club. :-)[/color]
              >>
              >>
              >> Question: I need to install SciPy in order to use matplotlib,[/color]
              >
              > No you don't.[/color]

              Ah.. I misread. I read
              http://matplotlib.sourceforge.net/installing.html, the section which
              describes what "enthought python" contains, and thought it meant "this
              is relevant to matplot lib".
              [color=blue][color=green]
              >> but on
              >> the download page I see that there are versions for Python 2.2.x and
              >> 2.3.x. I use 2.4.1 -- will bad things happen if I try to use the build
              >> for 2.3.x?[/color]
              >
              > Yes. Scipy has many extension modules; such modules built for 2.3.x
              > won't work for 2.4.x, etc.[/color]

              So, for future reference: I should *never* mix x and y versions in
              verion: x.y.z. I've wondered why there are versions of libraries for
              different versions of Python..

              Comment

              • Robert Kern

                #8
                Re: Graphs/statistics using wxPython

                Jan Danielsson wrote:
                [color=blue]
                > So, for future reference: I should *never* mix x and y versions in
                > verion: x.y.z. I've wondered why there are versions of libraries for
                > different versions of Python..[/color]

                For packages with extension modules at least. Python maintains binary
                compatibility between micro-releases (i.e. different z).

                --
                Robert Kern
                rkern@ucsd.edu

                "In the fields of hell where the grass grows high
                Are the graves of dreams allowed to die."
                -- Richard Harter

                Comment

                • Will McGugan

                  #9
                  Re: Graphs/statistics using wxPython

                  Jan Danielsson wrote:[color=blue]
                  > Hello all,
                  >
                  > I wanted to plot some statistics, so I wrote a simple wxPython class
                  > to do it. Then I realized that I would like to draw bar graphs, so I
                  > added that too.
                  >
                  > Since I'm a complete Python newbie, I haven't done much of it the
                  > "Python way", I suspect. So, I'm wondering if someone would like to show
                  > me some of the tricks I should have used.
                  >
                  > You can find the code at:
                  > http://user.it.uu.se/~jada3673/drawtest.py
                  >
                  > It's not finished[*], but it is usable. Oh, you can do whatever you
                  > want with it. Since I had never touched wxPython before working with
                  > this, I used some doodle application as a starting point.
                  >
                  > Btw... Has anyone already written statistics classes for wxPython? If
                  > so, where can I find them? If nothing similar exists, I'll probably add
                  > support for loading data from a file, and a few other features. Feel
                  > free to make requests or enhancements.
                  >
                  >[*] There are some size/offset bugs which I am aware of, but they are
                  > easily fixed. I just haven't got around to it yet.[/color]

                  If you ever want to add an extra dimension, then using OpenGL with
                  wxWindows is a breeze. See attached file for a 3d pie char..

                  Will McGugan

                  --

                  "".join({'*':'@ ','^':'.'}.get( c,0) or chr(97+(ord(c)-84)%26) for c in
                  "jvyy*jvyyzptht na^pbz")

                  # Pie Chart Window
                  # 2005 Will McGugan (will@willmcgug an.com)


                  import wx

                  from wx import glcanvas
                  from OpenGL.GL import *


                  import math
                  import time

                  sin = math.sin
                  cos = math.cos


                  PI = math.pi
                  def DegToRad(deg):
                  return deg*PI/180.

                  class PieSegment(obje ct):

                  def __init__(self, radius, angle1, angle2, colour, depth):

                  self.display_li st = glGenLists(1)

                  glNewList(self. display_list, GL_COMPILE)

                  self.angle1 = angle1
                  self.angle2 = angle2
                  self.explode_an gle = DegToRad( (angle2 + angle1) / 2.)
                  DrawPieSegment( radius, angle1, angle2, colour, depth)

                  glEndList()

                  def __del__(self):
                  glDeleteLists(s elf.display_lis t, 1)

                  def Draw(self, angle1, angle2, explode):

                  glPushMatrix()

                  glRotate(angle1 , 1.0, 0.0, 0.0);
                  glRotate(angle2 , 0.0, 0.0, 1.0);

                  glTranslatef( sin(self.explod e_angle)*explod e, cos(self.explod e_angle)*explod e, 0. )

                  glCallList(self .display_list)
                  glPopMatrix()



                  def DrawPieSegment( radius, angle1, angle2, colour, depth):

                  angle1 = DegToRad(angle1 )
                  angle2 = DegToRad(angle2 )

                  # Number of divisions in 360 degrees
                  RES = 100.

                  fan2D = []

                  step_degree = ((2*PI)/RES)
                  step_count = int( (angle2 - angle1) / step_degree ) + 1

                  step_degree = ( angle2 - angle1 ) / float(step_coun t)


                  # Precalculate the trig
                  sina1 = sin(angle1)
                  cosa1 = cos(angle1)

                  sina2 = sin(angle2)
                  cosa2 = cos(angle2)

                  # Calculate the points in an arc
                  for p in xrange(step_cou nt+1):

                  a = angle1 + p * step_degree

                  x = sin(a)
                  y = cos(a)

                  fan2D.append( (x,y) )

                  z1 = +depth/2.
                  z2 = -depth/2.

                  glMaterial(GL_F RONT, GL_DIFFUSE, [colour[0], colour[1], colour[2], 1.0])

                  # Create a fan for the top and bottom of the pie segment
                  glNormal(0, 0, +1.)
                  glBegin(GL_TRIA NGLE_FAN)
                  glVertex(0, 0, z1)
                  for x, y in fan2D:
                  glVertex(x*radi us, y*radius, z1)
                  glEnd()

                  glNormal(0, 0, -1.)
                  glBegin(GL_TRIA NGLE_FAN)
                  glVertex(0, 0, z2)
                  for x, y in fan2D:
                  glVertex(x*radi us, y*radius, z2)
                  glEnd()

                  # A strip for the curved edge
                  glBegin(GL_TRIA NGLE_STRIP)
                  for x, y in fan2D:
                  glNormal(x, y, 0.)
                  xr = x * radius
                  yr = y * radius
                  glVertex(xr, yr, z1)
                  glVertex(xr, yr, z2)
                  glEnd()


                  n1 = -cosa1, sina1, 0.
                  n2 = cosa2, -sina2, 0.

                  x1, y1 = sina1 * radius, cosa1 * radius
                  x2, y2 = sina2 * radius, cosa2 * radius


                  # Two quads for the radius edges

                  glNormal(n1)
                  glBegin(GL_QUAD S)

                  glVertex(0, 0, z1)
                  glVertex(x1, y1, z1)
                  glVertex(x1, y1, z2)
                  glVertex(0, 0, z2)

                  glEnd()

                  glNormal(n2)
                  glBegin(GL_QUAD S)

                  glVertex(0, 0, z1)
                  glVertex(x2, y2, z1)
                  glVertex(x2, y2, z2)
                  glVertex(0, 0, z2)

                  glEnd()



                  class PieChartWindow( glcanvas.GLCanv as):
                  def __init__(self, parent):

                  attriblist = None
                  glcanvas.GLCanv as.__init__(sel f, parent, -1, wx.DefaultPosit ion, wx.DefaultSize, 0, "GLCanvas", attriblist, wx.NullPalette)

                  self.init = False

                  self.segments = []


                  self.animating = False
                  self.angle = 0.
                  self.explode = 0.

                  self.downx = 0
                  self.rot = 0.

                  self.captured_m ouse = False

                  self.timer = wx.Timer(self)

                  self.Bind(wx.EV T_TIMER, self.OnTimer)
                  self.Bind(wx.EV T_LEFT_DOWN, self.OnLeftButt onDown)
                  self.Bind(wx.EV T_LEFT_UP, self.OnLeftButt onUp)
                  self.Bind(wx.EV T_MOTION, self.OnMouseMov e)
                  self.Bind(wx.EV T_ERASE_BACKGRO UND, self.OnEraseBac kground)
                  self.Bind(wx.EV T_SIZE, self.OnSize)
                  self.Bind(wx.EV T_PAINT, self.OnPaint)

                  def Animate(self):
                  self.animating = True
                  self.start_anim ate = time.clock()
                  self.timer.Star t(1000/20)


                  def OnTimer(self, event):
                  if self.IsShown():
                  self.Refresh()
                  if not self.animating:
                  self.timer.Stop ();


                  def SetSegments(sel f, segments, angle=0., radius=150., depth=50.):

                  self.segments = []

                  First = True

                  if len(segments):
                  angle = -(segments[0][0]/2. *360./100.)

                  for seg in segments:

                  seg_percent, colour = seg

                  if seg_percent == 0:
                  continue

                  if seg_percent < .2:
                  angle = angle + (seg_percent*36 0./100.)
                  continue

                  if First:
                  angle = -(seg_percent/2. * 360./100.)
                  First = False

                  next_angle = angle + (seg_percent*36 0./100.)
                  self.segments.a ppend(PieSegmen t(radius, angle, next_angle, colour, depth))
                  angle=next_angl e



                  def PerspectiveProj ection(self):

                  w, h = 300., 300.
                  a = 30.

                  tana = math.tan(DegToR ad(a/2.))

                  glMatrixMode(GL _PROJECTION);

                  v = (w/2) / tana

                  near = v / 10.

                  vw = tana * near
                  vh = tana * near

                  glFrustum(-vw, vw, -vh, vh, near, v*3.0);

                  glMatrixMode(GL _MODELVIEW);
                  glTranslatef(0. 0, 0.0, -v*1.2);

                  glLight(GL_LIGH T0, GL_POSITION, [w/2, h/2, v*1.2, 0.0]);

                  def InitGL(self):

                  self.Perspectiv eProjection()

                  glMaterial(GL_F RONT, GL_AMBIENT, [0.3, 0.3, 0.3, 1.0])
                  glMaterial(GL_F RONT, GL_DIFFUSE, [0.9, 0.9, 0.9, 1.0])
                  glMaterial(GL_F RONT, GL_SPECULAR, [1.0, 1.0, 1.0, 1.0])
                  glMaterial(GL_F RONT, GL_SHININESS, 70.0)
                  glLight(GL_LIGH T0, GL_AMBIENT, [0.25, 0.25, 0.25, 1.0])
                  glLight(GL_LIGH T0, GL_DIFFUSE, [1.0, 1.0, 1.0, 1.0])
                  glLight(GL_LIGH T0, GL_SPECULAR, [.1, .1, .1, 1.0])

                  glLightModel(GL _LIGHT_MODEL_AM BIENT, [0.2, 0.2, 0.2, 1.0])
                  glEnable(GL_LIG HTING)
                  glEnable(GL_LIG HT0)
                  glDepthFunc(GL_ LESS)
                  glEnable(GL_DEP TH_TEST)

                  glClearColor(1, 1,1,1)
                  glClear(GL_COLO R_BUFFER_BIT | GL_DEPTH_BUFFER _BIT)
                  glMatrixMode(GL _MODELVIEW);


                  def OnLeftButtonDow n(self, event):
                  self.downx = event.GetPositi on()[0]
                  self.captured_m ouse = True
                  self.CaptureMou se()

                  def OnLeftButtonUp( self, event):
                  if self.captured_m ouse and self.HasCapture ():
                  self.ReleaseMou se()

                  def OnMouseMove(sel f, event):
                  if event.Dragging( ) and event.LeftIsDow n():
                  mx, my = event.GetPositi on()
                  rot_delta = self.downx - mx
                  self.rot+= rot_delta
                  self.downx = mx
                  self.Refresh()

                  def OnEraseBackgrou nd(self, event):
                  pass


                  def OnSize(self, event):
                  size = self.GetClientS ize()
                  if self.GetContext ():
                  self.SetCurrent ()
                  glViewport(0, 0, size.width, size.height)
                  self.Refresh()
                  event.Skip()

                  def OnPaint(self, event):
                  dc = wx.PaintDC(self )
                  self.SetCurrent ()
                  if not self.init:
                  self.InitGL()
                  self.init = True

                  self.OnDraw()


                  def OnDraw(self):

                  glClear(GL_COLO R_BUFFER_BIT | GL_DEPTH_BUFFER _BIT);

                  if self.animating:

                  t = time.clock() - self.start_anim ate
                  if t < 1.:
                  self.angle = 0.
                  self.explode = 0.
                  elif t < 2.:
                  ts = t - 1.
                  self.angle = -50. * ts
                  elif t < 3.:
                  ts = t - 2.
                  self.angle = -50.
                  self.explode = 15. * ts
                  else:
                  self.animating = False
                  self.angle = -50.
                  self.explode = 15.

                  for segment in self.segments:

                  segment.Draw(se lf.angle, self.rot, self.explode)

                  self.SwapBuffer s()

                  if __name__ == "__main__":

                  class TestFrame(wx.Fr ame):
                  def __init__(self):
                  super(TestFrame , self).__init__( None, -1, "Pie Chart Test", style=wx.DEFAUL T_FRAME_STYLE)
                  self.SetClientS ize(wx.Size(300 ,300))

                  pie_chart = PieChartWindow( self)

                  # List of tuples ( <Percentage of Pie>, ( <Red>, <Green>, <Blue> ) )
                  seg = [ ( 20, (1., 0.1, 0.1) ),
                  ( 25, (0.05, .9, .1) ),
                  ( 10, (.2, 0.1, 1.) ),
                  ( 30, (.8, .9, .1) ) ]

                  pie_chart.SetSe gments( seg )
                  pie_chart.Anima te()



                  app = wx.App()
                  frame = TestFrame()
                  frame.Show(True )
                  app.MainLoop()


                  Comment

                  Working...