graphing/plotting with python and interface builder

J

Jacob Davis

Hi.

I am developing for mac and using Xcode and Interface Builder 3.0. I
can make a simple application, but I am having a hard time trying to
figure out a good way to create a graph or plot for a class project.

Does anybody have any tips on where to get started, or on how to do
this?

I have searched far for several days now, but I don't know if I am on
the right track. Any help is much appreciated.

Thanks,

Jake
 
P

Peter Wang

Hi.

I am developing for mac and using Xcode and Interface Builder 3.0. I
can make a simple application, but I am having a hard time trying to
figure out a good way to create a graph orplotfor a class project.

Does anybody have any tips on where to get started, or on how to do
this?

I have searched far for several days now, but I don't know if I am on
the right track. Any help is much appreciated.

Thanks,
Jake


Jake, are you using any python-specific GUI libraries like wxPython,
Qt, or Tk? The Chaco plotting toolkit (http://code.enthought.com/
chaco) supports several different mechanisms for rendering on OS X;
the default is to render via Quartz, but this requires wx or Qt. I am
also currently working on a (somewhat experimental) pure OpenGL
backend, which doesn't require wxPython or Qt, just an active OpenGL
context.

Do you want to generate a fairly static plot, or do you want the user
to be able to interact with it in some way?


-Peter
 
D

Diez B. Roggisch

Jacob said:
Hi.

I am developing for mac and using Xcode and Interface Builder 3.0. I
can make a simple application, but I am having a hard time trying to
figure out a good way to create a graph or plot for a class project.

Does anybody have any tips on where to get started, or on how to do this?

I have searched far for several days now, but I don't know if I am on
the right track. Any help is much appreciated.

I use

http://developer.snowmintcs.com/frameworks/sm2dgraphview/index.html


under 10.4. I don't see why it shouldn't work under 10.5. I assume you
use pyobjc? I had to use the signature-decorator to make the
SM2DGraphDataSource-category work - but I'm not sure if pyobjc 2.0
changes anything in that respect.


Diez
 
J

Jacob Davis

Thanks for the reply.

I have wxPython installed and have used it. with wx I have just been
using the wx.lib.plot module and the graphing is fine (although in
other posts I note some focus issues).

I have been looking at moving to using interface builder 3.0 and
building Cocoa apps because for a bigger project it might be faster
and better code.

I only want to make plots that show data... but I need to refresh the
plot at every step. with wx.lib.plot, i just draw it again
(performance is not too big of an issue). No user interaction is
needed.

I will check out Chaco. Like I said, I know how to use wx.lib.plot,
so if there is a way that I can use the graphs created there that
would be great... although I suspect that wx.lib.plot requires a frame
as a parent, which I would not want to use since .nib files (from
interface builder) would handle the gui side with PyObjC (a language
which I don't know).

Thanks

Jake
 
J

Jacob Davis

I found SM2DGraphView, but I guess that I am too much of a newbie with
interface builder and pyobjc to figure out how to get SM2DGraphView to
work. Are there any good tutorials (or better yet, examples) of how
to get SM2DGraphView to work?

I don't know pyobjc well at all.

Thanks

Jake
 
D

Diez B. Roggisch

Jacob said:
I found SM2DGraphView, but I guess that I am too much of a newbie with
interface builder and pyobjc to figure out how to get SM2DGraphView to
work. Are there any good tutorials (or better yet, examples) of how to
get SM2DGraphView to work?

I don't know pyobjc well at all.

There isn't much to it. Unfortunately, there aren't many good tutorials,
but at least a few examples in the pyobjc repository.

below is my code for implementing the SM2DGraphDataSource category. It
is of course interspersed with my application-logic, but should give you
a start.

Additionally, you need to load the SM2DGraphView-framework. The code to
do so is also below.

Diez

#
# BCGraphViewController.py
# BruceControl
#
# Created by Diez Roggisch on 22.02.08.
# Copyright (c) 2008 __MyCompanyName__. All rights reserved.
#

from Foundation import *
from AppKit import *
import sys
from PyObjCTools import NibClassBuilder
import objc
MODES = "displaySpeed", "displayPosition"

kSM2DGraph_Axis_Y = 0
kSM2DGraph_Axis_X = 1

kSM2DGraph_Axis_Y_Right = 2
kSM2DGraph_Axis_Y_Left = kSM2DGraph_Axis_Y

class BCGraphViewController(NibClassBuilder.AutoBaseClass):

_displayPosition = False
_displaySpeed = False


def displayPosition(self):
return self._displayPosition

def setDisplayPosition_(self, v):
self._displayPosition= v
self.reloadData()


def displaySpeed(self):
return self._displaySpeed

def setDisplaySpeed_(self, v):
self._displaySpeed= v
self.reloadData()


def awakeFromNib(self):
self._displayed_mis = []
self._ts_min = 0.0
self._ts_max = 0.0
self.graphView.setDataSource_(self)

def setMotorInfos_(self, motor_infos):
self._motor_infos = motor_infos
# apparently, it's enough to just
# subscribe once
motor_infos[0].subscribeDisplayChanged(self)

def setConnector_(self, connector):
self._connector = connector
connector.subscribeStateListener(self)

def stateArrived_(self, n):
state = n.object()
ts = float(state.timestamp) / 1000000000.0 # nano to seconds
if self._ts_min == 0:
self._ts_min = ts
self._ts_max = ts

def reloadData(self):
if self.numberOfLinesInTwoDGraphView_(None):
self.graphView.reloadData()
self.graphView.reloadAttributes()

def displayChanged_(self, n):
motor_info = n.object()
motor_id = motor_info.motor_id
if motor_info.display() and motor_info not in self._displayed_mis:
self._displayed_mis.append(motor_info)
else:
try:
self._displayed_mis.remove(motor_info)
except ValueError:
pass
self.reloadData()

@property
def active_modes(self):
return [mode for mode in MODES if getattr(self, mode)()]

@property
def activated_views(self):
return len(self.active_modes)

@objc.signature('I@:mad:')
def numberOfLinesInTwoDGraphView_(self, view):
res = len(self._displayed_mis) * self.activated_views
return res

@objc.signature('@@:mad:I')
def twoDGraphView_dataForLineIndex_(self, view, lineIndex):
av = self.activated_views
# first, compute the mi to be used
offset = lineIndex // av
mi = self._motor_infos[offset]
mode = self.active_modes[lineIndex % av]
return mi[mode]

@objc.signature('d@:mad:Ii')
def twoDGraphView_maximumValueForLineIndex_forAxis_(self, view,
lineIndex, axis):
if not self.numberOfLinesInTwoDGraphView_(view):
return .0
av = self.activated_views
mode = self.active_modes[lineIndex % av]
if axis == kSM2DGraph_Axis_Y:
maxs = [mi.max[mode] for mi in self._displayed_mis]
return max(maxs)
elif axis == kSM2DGraph_Axis_X:
return float(self._ts_max)
return .0

@objc.signature('d@:mad:Ii')
def twoDGraphView_minimumValueForLineIndex_forAxis_(self, view,
lineIndex, axis):
if not self.numberOfLinesInTwoDGraphView_(view):
return .0
av = self.activated_views
mode = self.active_modes[lineIndex % av]
if axis == kSM2DGraph_Axis_Y:
mins = [mi.min[mode] for mi in self._displayed_mis]
return min(mins)
elif axis == kSM2DGraph_Axis_X:
return float(self._ts_min)
return .0

@objc.signature('@@:mad:I')
def twoDGraphView_attributesForLineIndex_(self, view, lineIndex):
try:
if not self.numberOfLinesInTwoDGraphView_(None):
return None
av = self.activated_views
# first, compute the mi to be used
offset = lineIndex // av
mi = self._motor_infos[offset]
res = {NSForegroundColorAttributeName : mi.color}
except:
print sys.exc_info()[1]
return None
return res


def crop_(self, sender):
self._ts_min = self._ts_max
for mi in self._motor_infos:
mi._set_min_max_defaults()




import objc, AppKit, Foundation, os
import logging, sys
from ctypes.util import find_library

logger = logging.getLogger('bundles')

frameworks = set(("SM2DGraphView",))
loaded = set()

loading_exceptions = []

for framework in frameworks:
logger.debug('Trying to load framework <%s>', framework)
bundle_path = find_library(framework)
bundle_path = bundle_path[:bundle_path.index('framework')] +
"framework"
logger.debug('from path <%s>', bundle_path)
try:
objc.loadBundle(framework, globals(), bundle_path=bundle_path)
loaded.add(framework)
continue
except:
loading_exceptions.append(sys.exc_info()[1])
pass

if loaded != frameworks and loading_exceptions:
logger.error("Got exceptions loading frameworks")
for e in loading_exceptions:
logger.error(e)
raise loading_exceptions[0]

del objc, AppKit, Foundation, os, bundle_path
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,019
Latest member
RoxannaSta

Latest Threads

Top