#
from g import *
import operator
"""
Source Code for graph.py, a quickgraphing tool for
for Python. See http://rlai.cs.ualberta.ca/RLAI/RLtoolkit/graph.html for documentation.
The function graph will draw a graph in a window, with each data line given a
different color.
A graph is a window with various state vars. The simplest way to use this is:
graph(data)
and then, possibly, graphMore(data)
you may also graphLess(color)
or specifying the graphname,
graph(data, color, graph)
graphMore(newdata, color, graph)
graphLess(color, graph)
The graph involved defaults to the first graph or a newly created graph
if there are no graphs yet (or if graph is True). Alternatively, you can make
multiple graphs, and specify the graph as a last argument to all graph routines.
Data can be a simple list of y's (heights) or a list of list of y's.
Or it can be a list of (x y) coordinates, e.g., ((x1 y1) (x2 y2) ...)
Or a list of those!
The span of the graph is initially set from the data. Alternatively:
xGraphLimits(xmin, xmax) does it manually (same for yGraphLimits)
xGraphLimits() sets it back to auto
Tick marks are initially just at the min and max. Alternatively:
xTickmarks([tick1, tick2, tick3 ...]) sets them manually (same for yTickmarks)
xTickmarks() sets them back to auto
xTickmarks(num) sets them to go from the graph minimum to the maximum by num
(call it after you make the graph to use this)
Tick marks are specified by values, e.g., xTickmarks(0 .5, 1.0)
or by a list of valuelabel pairs, e.g., xTickmarks( (0, "0"), (1.0, "1"))
gridgraph(density, graph) creates a grid across the graph
histogram([val1, val2, ...], numbins, minex, maxex, color, hist)
creates a histogram of the values. All parameters except the data list are optional
histogramMore([val1, val2, ...], numbins, minex, maxex, color, hist)
adds another histogram graph on top of the current one
When the graph is drawn, you can highlight lines in it to see them better. The space bar
turns highlighting on and off. Highlighting will start with the first data line. Use the arrow
keys to move to the next or previous lines in the graph.
To get rid of a graph:
closeGraph(graph) can be called with the graph or its name. If None, the first
graph in the list of windows will be closed
"""
class Dataview (Gview):
"dataview of graph"
def __init__(self, parent, gdViewport):
Gview.__init__(self, parent)
gdSetViewport(self, gdViewport[0], gdViewport[1], gdViewport[2], gdViewport[3])
gSetCursor(self, 'crosshair')
def gClickEventHandler(self, x, y):
print "Clicked at", x, y
def gKeyEventHandler(self, key):
graph = self.parent
if key == "Left" or key == "Up":
removeHighlight(graph)
graph.highlightline = (graph.highlightline - 1) % len(graph.data)
drawHighlight(graph)
elif key == "Right" or key == "Down":
removeHighlight(graph)
graph.highlightline = (graph.highlightline + 1) % len(graph.data)
drawHighlight(graph)
elif key == "space":
removeHighlight(graph)
graph.highlightp = not graph.highlightp
drawHighlight(graph)
class Graph (Gwindow):
def __init__(self, title="Graph", dataviewtype=Dataview, **kwargs): #(0,40,500,200)):
self.dataview = None
self.dviewtype = dataviewtype
self.maincolor = gBlack
self.data = None
self.autolimitsx = True # limiting x values from data,
self.autolimitsy = True # or from user and tickmarks?
self.xmax = 1.0
self.xmin = 0.0
self.ymax = 1.0
self.ymin = 0.0
self.xtickmarks = [] # initial tick marks auto from limits
self.ytickmarks = []
self.charstyle = gFont("Geneva", 9, 'normal')
self.charwidth = 6
self.charheight = 8
self.ylabelspace = 0
self.xlabelspace = 0
self.zerospace = 15
self.xendspace = 50
self.yendspace = 10
self.ticklength = None
self.boxy = False
self.griddensity = None
self.highlightp = False
self.highlightcolor = None
self.highlightline = 0
self.lasthighlight = None
if not ('gdViewport' in kwargs or 'gdViewportR' in kwargs or 'gViewport' in kwargs or 'gViewportR' in kwargs):
Gwindow.__init__(self, windowTitle=title, gdViewport=(0,40,600,300))
else:
Gwindow.__init__(self, windowTitle=title, **kwargs)
self.initGraph()
## The data is a list of lists. Each list is either a list of yvalues or
## a list of xypairs.
def initGraph (self):
self.xlabelspace = 11 * self.charwidth
self.ylabelspace = 10 + self.charheight
self.ticklength = self.zerospace / 2
x1, y1, x2, y2 = gdGetViewport(self)
self.dataview = self.dviewtype(self, gdViewport=(self.xlabelspace+1, 0, x2-1, y2-self.ylabelspace-1)) #(10,70,470,170))
gClear(self.dataview, 'white')
gSetCoordinateSystem(self.dataview, self.xmin, self.ymin, self.xmax, self.ymax, 'lowerLeft')
self.maincolor = gColorOn(self.dataview)
self.highlightcolor = gColorPen(self.dataview, gColorFlip(self.dataview), None, None, 2, 2)
def gAcceptNewViewportSize(self):
gSetCSScale(self, 0, 0, 1, 1, 'lowerLeft')
if isinstance(self, Graph) and self.dataview != None:
x1, y1, x2, y2, corner = gGetCoordinateSystem(self)
gSetViewport( self.dataview, \
self.xlabelspace + self.zerospace, \
self.ylabelspace + self.zerospace, \
x2 - self.xendspace, \
y2 - self.yendspace)
gClear(self.dataview, 'white')
def gDrawView(self):
"Draws the graph"
gClear(self, 'white')
gClear(self.dataview, 'white')
self.drawAxes()
if self.data != None:
for color, dlist in self.data:
drawLine(self, dlist, color)
if self.highlightp:
drawHighlight(self)
if self.griddensity != None:
gridGraph(None, self)
def drawAxes (self):
xspace = self.xlabelspace
yspace = self.ylabelspace
gDrawLine(self, xspace, yspace, \
gConvertx(self.dataview, self, self.xmax), \
yspace, \
self.maincolor)
gDrawLine(self, xspace, yspace, \
xspace, \
gConverty(self.dataview, self, self.ymax), \
self.maincolor)
self.drawTickmarks()
def drawTickmarks (self):
if self.xtickmarks != [] and self.xtickmarks != None:
useticks = self.xtickmarks
else:
useticks = regularizeTickmarks([self.xmin, self.xmax])
if self.xmin <= self.xmax:
for x, label in useticks:
gx = gConvertx(self.dataview, self, x)
gDrawLineR(self, gx, self.ylabelspace, 0, -self.ticklength, self.maincolor)
gDrawText(self, label, self.charstyle, \
gx - (self.charwidth * len(label)) /2, \
self.ylabelspace - 5 - self.charheight, self.maincolor)
if self.ytickmarks != [] and self.ytickmarks != None:
useticks = self.ytickmarks
else:
useticks = regularizeTickmarks([self.ymin, self.ymax])
if self.ymin <= self.ymax:
for y, label in useticks:
gy = gConverty(self.dataview, self, y)
gDrawLineR(self, self.xlabelspace, gy, -self.ticklength, 0, self.maincolor)
gDrawText(self, label, self.charstyle, \
self.xlabelspace - 5 - (self.charwidth * len(label)), \
gy - (self.charheight / 2), self.maincolor)
def gKeyEventHandler(self, key): # send key presses to dataview handler
self.dataview.gKeyEventHandler(key)
def graph (newdata, color=None, graph=None): #[Doc]
"Establishes some data for a graph, then draws it"
if newdata == None or reduce(operator.and_, map(lambda a: a == None, newdata)):
print "No graphing data"
else:
if None in newdata:
print "Warning: Some data to be graphed was nil; ignoring"
newdata.remove(None)
graph = chooseGraph(graph)
graph.data = FillInColors (regularizeData(newdata, color))
graph.highlightline = 0
graph.highlightp = False
computeLimitsFromData(graph)
graph.gDrawView()
return graph
def regularizeData (data, color=None):
"regular form is a list of lines, each of which is a list or list of pairs, preceded by color"
if not isinstance(data[0], (tuple,list)): #simple list
return [[color, data]]
elif isinstance(data[0][0], (tuple, list)): # list of lists of pairs
return [[color, d] for d in data]
elif len(data[0]) == 2: # list of pairs
return [[color, data]]
else: # list of lists
return [[color, d] for d in data]
def FillInColors (data):
for colorline in data:
if colorline[0] == None:
colorline[0] = FirstUnusedColor(data)
return data
def graphData (graph):
"Returns the data plotted in graph, with color stripped away of course"
usegraph = chooseGraph(graph)
dataonly = []
for color, dlist in usegraph.data:
dataonly.append(dlist)
return dataonly
def FirstX (data):
"returns the xvalue of the first point in data"
useline = None
for line in data:
if line != None:
useline = line
break
if useline != None:
line = useline[1]
if isinstance(line[0], (tuple, list)):
firstpoint = line[0][0]
else:
firstpoint = 1
return firstpoint
def FirstY (data):
"returns the yvalue of the first point in data"
useline = None
for line in data:
if line != None:
useline = line
break
if useline != None:
line = useline[1]
if isinstance(line[0], (tuple, list)):
firstpoint = line[0][1]
else:
firstpoint = line[0]
return firstpoint
def graphMore (newdata, color=None, graph=None): #[Doc]
addToGraph(newdata, color, graph)
def addToGraph (newdata, color=None, graph=None): #[Doc]
"Adds additional data to a graph"
if newdata == None or reduce(operator.and_, map(lambda a: a == None, newdata)):
print "No graphing data"
else:
if None in newdata:
print "Warning: Some data to be graphed was nil; ignoring"
newdata.remove(None)
graph = chooseGraph(graph)
graph.data.extend(regularizeData(newdata, color))
graph.data = FillInColors (graph.data)
computeLimitsFromData(graph)
graph.gDrawView()
def graphLess (colorkeyword=None, graph=None): #[Doc]
"Remove a line of data points from the graph. Defaults to last line"
if colorkeyword == None:
subtractFromGraph(None, graph)
else:
graph = chooseGraph(graph)
removecolor = ColorFromKeyword(colorkeyword)
linenum = 0
for color, dlist in graph.data:
if color == removecolor:
subtractFromGraph(linenum, graph)
break
else:
linenum +=1
else:
print "No such color used in this graph", colorkeyword
def subtractFromGraph (linenum=None, graph=None): #[Doc]
"Remove a line of data points from the graph. Linenum is from zero or defaults to last line"
originalfrontwindow = Win.FrontWindow()
graph = chooseGraph(graph)
if linenum == None:
linenum = len(graph.data) - 1
num = 0
newdata = []
graph.data[linenum:] = graph.data[linenum+1:]
computeLimitsFromData(graph)
gDrawView(graph)
def xGraphLimits (xmin=None, xmax=None, graph=None): #[Doc]
graph = chooseGraph(graph)
if xmin != None or xmax != None:
graph.autolimitsx = False
if xmin != None:
graph.xmin = xmin
if xmax != None:
graph.xmax = xmax
gSetCoordinateSystem(graph.dataview, graph.xmin, graph.ymin, graph.xmax, graph.ymax, 'lowerLeft')
else:
graph.autolimitsx = True
computeLimitsFromData(graph)
graph.gDrawView()
def yGraphLimits (ymin=None, ymax=None, graph=None): #[Doc]
graph = chooseGraph(graph)
if ymin != None or ymax != None:
graph.autolimitsy = False
if ymin != None:
graph.ymin = ymin
if ymax != None:
graph.ymax = ymax
gSetCoordinateSystem(graph.dataview, graph.xmin, graph.ymin, graph.xmax, graph.ymax, 'lowerLeft')
else:
graph.autolimitsy = True
computeLimitsFromData(graph)
graph.gDrawView()
def xTickmarks (xticks=None, graph=None): #[Doc]
"Sets the ticks marks and possibly resets limits."
graph = chooseGraph(graph)
if xticks == None:
graph.xtickmarks = None
if graph.data != None:
computeLimitsFromData(graph)
elif isinstance(xticks, (tuple, list)):
graph.xtickmarks = regularizeTickmarks(xticks)
graph.xmin = min(graph.xmin, MinTickmark(graph.xtickmarks))
graph.xmax = max(graph.xmax, MaxTickmark(graph.xtickmarks))
gSetCoordinateSystem(graph.dataview, graph.xmin, graph.ymin, graph.xmax, graph.ymax, 'lowerLeft')
else: # a number
if graph.data !=None and graph.data !=[]:
ticks = []
i = graph.xmin
while i <= graph.xmax:
ticks.append(i)
i += xticks
graph.xtickmarks = regularizeTickmarks(ticks)
graph.gDrawView()
def yTickmarks (yticks=None, graph=None): #[Doc]
"Sets the ticks marks and possibly resets limits."
graph = chooseGraph(graph)
if yticks == None:
graph.ytickmarks = None
if graph.data != None:
computeLimitsFromData(graph)
elif isinstance(yticks, (tuple, list)):
graph.ytickmarks = regularizeTickmarks(yticks)
if graph.data != None:
computeLimitsFromData(graph)
else:
graph.ymin = min(graph.ymin, MinTickmark(graph.ytickmarks))
graph.ymax = max(graph.ymax, MaxTickmark(graph.ytickmarks))
else: # a number
if graph.data !=None and graph.data !=[]:
ticks = []
i = graph.ymin
while i <= graph.ymax:
ticks.append(i)
i += yticks
graph.ytickmarks = regularizeTickmarks(ticks)
graph.gDrawView()
def regularizeTickmarks (ticks):
useticks = []
for tick in ticks:
if isinstance(tick, (tuple, list)):
useticks.append(tick)
elif isinstance(tick, float):
useticks.append([tick, str(round(tick, 3))])
else:
useticks.append([tick, str(tick)])
return useticks
def MinTickmark (ticks):
if ticks != None and ticks !=[]:
if isinstance(ticks[0], (tuple, list)):
return ticks[0][0]
else:
return ticks[0]
def MaxTickmark (ticks):
if ticks != None and ticks !=[]:
if isinstance(ticks[-1], (tuple, list)):
return ticks[-1][0]
else:
return ticks[-1]
colors = [ gColorRed(True), gColorGreen(True), gColorBlue(True), gColorBlack(True), \
gColorYellow(True), gColorPink(True), gColorCyan(True), gColorPurple(True), \
gColorMagenta(True), gColorOrange(True), gColorBrown(True), gColorLightBlue(True), \
gColorGray(True), gColorDarkGreen(True), gColorTan(True) ]
def nthColor (n): #[Doc]
return colors[n // length(colors)]
colorList = {'blue': gBlue, 'red': gRed, 'green': gGreen, 'black': gBlack, 'yellow': gYellow, \
'pink': gPink, 'cyan': gCyan, 'purple': gPurple, 'magenta': gMagenta, \
'orange': gOrange, 'brown': gBrown, 'lightBlue': gLightBlue, 'gray': gGray, \
'darkGreen': gDarkGreen, 'tan': gTan, 'white': gWhite, \
'lightGray': gLightGray, 'darkGray': gDarkGray }
def ColorFromKeyword (colorkeyword):
color = colorList.get(colorkeyword, None)
if color == None:
print "Unrecognized color keyword:" ,colorkeyword
return color
def FirstUnusedColor (data):
"Returns first color in the list of colors that is least used in data"
for permittedTimesUsed in range(100):
for color in colors:
if TimesColorUsed(color, data) <= permittedTimesUsed:
return color
def TimesColorUsed (color, data):
count = 0
for c, dlist in data:
if c == color:
count +=1
return count
def chooseGraph (graph=None): #[Doc]
"Select a graph based on input 'graph'"
global GDEVICE
glist = []
for w in GDEVICE.childwindows:
if isinstance(w, Graph):
glist.append(w)
if graph == None: # None given - if first is a graph, use it, else make a new one
if glist == []:
usegraph = Graph("Graph")
else:
usegraph = glist[0]
elif isinstance(graph, Graph): # already have graph
usegraph = graph
elif graph == True:
usegraph = Graph("Graph")
elif isinstance(graph, str): # we have a graph name
for g in glist:
if g.title == graph:
usegraph = g
break
else:
usegraph = Graph(graph)
else:
print "Error: can't choose graph", graph
usegraph = None
return usegraph
def closeGraph(graph=None):
graph.gCloseview()
def drawSegment (graph, x1, y1, x2, y2, color):
l = []
if graph.boxy:
l.append(gDrawLine(graph.dataview, x1, y1, x2, y1, color))
l.append(gDrawLine(graph.dataview, x2, y1, x2, y2, color))
else:
l.append(gDrawLine(graph.dataview, x1, y1, x2, y2, color))
return l
def draw (graph, ylist, color):
l = []
for i in range(len(ylist)-1): #start from 1
x1 = i + 1
x2 = i + 2
y1 = ylist[i]
y2 = ylist[i+1]
l.extend(drawSegment(graph, x1, y1, x2, y2, color))
return l
def drawXY(graph, xylist, color):
l = []
for i in range(len(xylist)-1):
x1, y1 = xylist[i]
x2, y2 = xylist[i+1]
l.extend(drawSegment(graph, x1, y1, x2, y2, color))
return l
def computeLimitsFromData (graph):
if graph.autolimitsx:
graph.xmin = MinTickmark(graph.xtickmarks)
if graph.xmin == None:
graph.xmin = FirstX(graph.data)
graph.xmax = MaxTickmark(graph.xtickmarks)
if graph.xmax == None:
graph.xmax = FirstX(graph.data)
if graph.autolimitsy:
graph.ymin = MinTickmark(graph.ytickmarks)
if graph.ymin == None:
graph.ymin = FirstY(graph.data)
graph.ymax = MaxTickmark(graph.ytickmarks)
if graph.ymax == None:
graph.ymax = FirstY(graph.data)
if graph.autolimitsx or graph.autolimitsy:
for color, dlist in graph.data:
if not isinstance(dlist[0], (tuple, list)):
if graph.autolimitsy:
for y in dlist:
if y < graph.ymin:
graph.ymin = y
if y > graph.ymax:
graph.ymax = y
if graph.autolimitsx:
if 1 < graph.xmin:
graph.xmin = 1
if len(dlist) > graph.xmax:
graph.xmax = len(dlist)
else:
for x, y in dlist:
if graph.autolimitsy:
if y < graph.ymin:
graph.ymin = y
if y > graph.ymax:
graph.ymax = y
if graph.autolimitsx:
if x < graph.xmin:
graph.xmin = x
if x > graph.xmax:
graph.xmax = x
if graph.ymin == graph.ymax:
print "Warning: all lines are flat at", graph.ymin
if graph.ymax > 0:
graph.ymin = 0
else:
graph.ymin = graph.ymax - 1
gSetCoordinateSystem(graph.dataview, graph.xmin, graph.ymin, graph.xmax, graph.ymax, 'lowerLeft')
def gridGraph (griddensit=None, graph=None): #[Doc]
graph = chooseGraph(graph)
if griddensit != None:
graph.griddensity = griddensit
if graph.griddensity == None:
graph.griddensity = 5
for x, label in graph.xtickmarks:
dx = gdCoordx(graph.dataview, x)
if x >= graph.xmin and x <= graph.xmax:
for dy in range(gdCoordy(graph.dataview, graph.ymax), \
gdCoordy(graph.dataview, graph.ymin), \
graph.griddensity):
gdDrawPoint(graph.dataview, dx, dy, graph.maincolor)
for y, label in graph.ytickmarks:
dy = gdCoordy(graph.dataview, y)
if y >= graph.ymin and y <= graph.ymax:
for dx in range(gdCoordx(graph.dataview, graph.xmin), \
gdCoordx(graph.dataview, graph.xmax), \
graph.griddensity):
gdDrawPoint(graph.dataview, dx, dy, graph.maincolor)
def drawHighlight (graph):
if graph.highlightp and graph.highlightline != None:
color, data = graph.data[graph.highlightline]
graph.lasthighlight = drawLine(graph, data, gColorPen(graph, color, None, None, 2))
#drawLine(graph, graph.data[graph.highlightline][1], graph.highlightcolor)
def removeHighlight (graph):
if graph.lasthighlight != None:
gDelete(graph.dataview, graph.lasthighlight)
graph.lasthighlight = None
def drawLine (graph, line, color):
if isinstance(line[0], (tuple,list)):
return drawXY(graph, line, color)
else:
return draw(graph, line, color)
# A histogram is a graph, created in a particular way
# histogram(data, numbins, minex, maxex, graph)
def histogram (data, numbins=None, minex=None, maxex=None, color=None, hist=None): #[Doc]
"plots histogram of data, minex <= data < maxex, in a color on a graph named hist"
if data==None or data == []:
print "No graphing data"
elif len(data) == 1:
print "Cannot histogram a single datum"
else:
if minex == None:
minex = min(data)
mx = max(data)
if minex == mx:
print "Error: min=max - no histogram possible"
else:
if isinstance(mx, int) and isinstance(minex, int):
if maxex==None:
maxex = mx + 1
if numbins == None and (mx - minex) <= 200:
numbins = maxex - minex
if numbins == None:
numbins = 30
if maxex == None:
maxex = mx + (.00001 * ((mx - minex) / numbins))
hgraph = chooseGraph(hist)
hgraph.boxy = True
bins = [0 for i in range(numbins)]
numtoosmall = numtoobig = 0
scalefactor = float(numbins) / (maxex - minex)
for d in data:
bin = int(floor((d - minex) * scalefactor))
if bin < 0:
numtoosmall += 1
elif bin >= numbins:
numtoobig += 1
else:
bins[bin] += 1
gdata = []
for i in range(numbins): # prepare list of bin max, # in that bin
x = minex + (float(i) / scalefactor)
entry = [x , bins[i] ]
gdata.append(entry)
gdata.append([maxex, bins[numbins-1]]) #force the last bar to come out
graph([gdata], color, hgraph)
if numtoosmall != 0:
print numtoosmall, "data points were below the range"
if numtoobig != 0:
print numtoobig, "data points were above the range"
def histogramMore (data, numbins=None, minex=None, maxex=None, color=None, hist=None): #[Doc]
"adds histogram of data, minex <= data < maxex, in a color to a graph named hist"
#histogram(data, numbins, minex, maxex, color, hist)
if data==None or data == []:
print "No graphing data"
elif len(data) == 1:
print "Cannot histogram a single datum"
else:
if minex == None:
minex = min(data)
mx = max(data)
if minex == mx:
print "Error: min=max - no histogram possible"
else:
if isinstance(mx, int) and isinstance(minex, int):
if maxex==None:
maxex = mx + 1
if numbins == None and (mx - minex) <= 200:
numbins = maxex - minex
if numbins == None:
numbins = 30
if maxex == None:
maxex = mx + (.00001 * ((mx - minex) / numbins))
hgraph = chooseGraph(hist)
hgraph.boxy = True
bins = [0 for i in range(numbins)]
numtoosmall = numtoobig = 0
scalefactor = float(numbins) / (maxex - minex)
for d in data:
bin = int(floor((d - minex) * scalefactor))
if bin < 0:
numtoosmall += 1
elif bin >= numbins:
numtoobig += 1
else:
bins[bin] += 1
gdata = []
for i in range(numbins): # prepare list of bin max, # in that bin
x = minex + (float(i) / scalefactor)
entry = [x , bins[i] ]
gdata.append(entry)
gdata.append([maxex, bins[numbins-1]]) #force the last bar to come out
newdata = regularizeData([gdata],color)
hgraph.data.extend(newdata)
hgraph.data = FillInColors (hgraph.data)
hgraph.gDrawView()
#graph(graphData(hgraph.data), None, hgraph)
if numtoosmall != 0:
print numtoosmall, "data points were below the range"
if numtoobig != 0:
print numtoobig, "data points were above the range"
#Testing stuff
"""
histogram([1.2, 1.3, 2.5, 6, 20, 1.4, 5, 30, 5.5, 7, 23, 19, 15, 15], 5, None, None, 'red')
histogramMore([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],5, None, None, 'blue')
histogramMore([1,2,11,12,13,15,21,22,23,24,25],3, None, None, 'green')
xTickmarks([0, 1, 2, 3, 4, 5],"new")
yTickmarks([0,5, 10, 15, 20, 25, 30],"new")
gridGraph(10,"new")
graph([[1,2,3,4,5],[0,1,4,9]],None, "new")
xTickmarks([(1,"st"),(2,"ar"),(3,"ts"),(4,"end")], "new")
#graph([[1, 2, 3, 4],[(1,1),(2,4),(3,6),(4,8)], [1,4,9, 25]])
g = graph([[0,1,2,3,4],[0,1,4,6,8],[0,1,4,9,27],[0,5,10,15,20],[(0,10),(1,20),(2,30)]], None, "test")
xTickmarks(1.5, "test")
yTickmarks(10, "test")
from math import *
def func1 (num):
data = [[0. for j in range(num)] for i in range(num)]
dx = 2. / (num - 1)
y = - 1.
for i in range(num):
x = - 1
for j in range(num):
data[i][j] = abs(exp(-0.5 * (sqr(x) + sqr(y)))) * (1. + (cos(10 * sqrt(sqr(x) + sqr(y)))))
x = x + dx
y = y + dx
return data
def sqr (x):
return x * x
graph(func1(30), graph="Function")
"""
#