tuplex out of range when working with buttons - python

I have a program which works fine but when i try to do it with buttons,when i run it,it gives me
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1413, in call
return self.func(*args) File "fire_buttons.py", line 193, in Plot
result=la.Graph(grids) File "fire_buttons.py", line 181, in Graph
n=sc.shape(data)[2] IndexError: tuple index out of range
The function is that:
def Graph(self,data):
"""Make the plot"""
plt.colormaps()
n=sc.shape(data)[2]
ims=[]
for i in range(n):
mydata=data[:,:,i]
im=plt.imshow(mydata,cmap=plt.get_cmap('jet'))
ims.append([im])
return ims
Some code for the buttons:
def createWidgets(self):
"""Add widgets to main frame"""
top_frame=Frame(self)
self.Tree=StringVar()
self.Tree_entry=Entry(top_frame,textvariable=self.Tree)
self.label1=Label(top_frame,text="Probability of existence of a tree")
self.Tree_entry.pack(side='right')
self.label1.pack()
top_frame.pack(side=TOP)
......
bottom_frame=Frame(self)
bottom_frame.pack(side=TOP)
self.QUIT=Button(bottom_frame,text='Quit',command=self.quit)
self.QUIT.pack(side=LEFT)
self.operate=Button(bottom_frame,text='Run',command=self.Plot)
self.operate.pack(side=LEFT)
def Plot(self):
if (self.area.get().isdigit() and p.match(self.Tree.get()) and p.match(self.Burning.get()) and p.match(self.Lighting.get()) and p.match(self.ResistBurn.get()) and p.match(self.RegenerateTree.get()) and self.time_step.get().isdigit()):
la=myfire()
grids=la.fire(int(self.area.get()),float(self.Tree.get()),float(self.Burning.get()),float(self.Lighting.get()),float(self.ResistBurn.get()),float(self.RegenerateTree.get()),int(self.time_step.get()))
result=la.Graph(grids)
fig=plt.gcf()
ArtistAnimation(fig,result,interval=10,repeat=False)
plt.show()
Also,if i want to use slide widget i tried sth like:
self.Tree_entry=Scale(top_frame,from_=0,to=1,orient=HORIZONTAL,length=1000, tickinterval=0.001)
self.Tree_entry.set(40)
I want values from 0 to 1 and increment by 0.0001.But this just gives me 0 and 1 only.
--------------------UPDATE--------------------
In the version without the buttons instead of Plot function i use:
grids=fire(area,Tree,Burning,Lighting,ResistBurn,RegenerateTree,time_step)
result=Graph(grids)
fig=plt.gcf()
ani=ArtistAnimation(fig,result,interval=10,repeat=False)
plt.show()
and it runs fine,so maybe i have sth wrong in the Plot?

Your first question might be answered by getting the size of grids, prior to using it in the la.Graph(grids) line of code. Perhaps it's just a tuple with a single item? (Or less than three anyway, since [2] is giving the error.)
EDIT: Your second question needs to=100 I believe. I misread that you wanted to go between 0 and 1. You may be only seeing 0 or 1 since you set the value to 40.
EDIT: The following has been tested.
import tkinter as tk
if __name__ == "__main__":
root = tk.Tk()
tree_entry = tk.Scale(root, from_=0, to=1, resolution=0.001)
tree_entry.pack()
tree_entry.set(0.5)
root.mainloop()

Your error is on this line:
n=sc.shape(data)[2]
From the evidence you've given, this has nothing to do with buttons or widgets in any way. You're simply trying to get element 2 from a tuple but the tuple doesn't have that many elements. You need to find where you define sc.shape(data) and see why it doesn't have as many items as you think it should.

Related

Python: how to pass a function as a variable command in Tkinter

This is my first time creating a GUI using Tkinter to simulate a DSP setup. I'm stuck.
This GUI requires multiple scales. Therefore I wrote a generic scale function.
# Overlap percent scale
def overlap_percent():
print("Testing")
# op=var.get()
# olive_features['overlap_perc']=op
# generic scale function
def create_scale(self,parent,xval,yval,start,end,resolution,orient,default,lng,clr,cmdtrig):
OHA_scale = tk.Scale(parent,resolution=resolution, from_=start, to=end, orient=orient,length=lng,fg=clr,command=cmdtrig)
OHA_scale.grid(row=xval, column=yval, sticky=tk.E + tk.W + tk.N + tk.S, padx=20, pady=4)
OHA_scale.set(default)
# Overlap %
yval=yval+2
xval=1
self.create_label(Oliveframe,xval,yval,"Overlap %")
xval=3
self.create_scale(Oliveframe,xval,yval,25,75,25,"vertical",75,90,'Black',"overlap_percent")
xval=1
yval=yval+1
self.create_arrow(Oliveframe,xval,yval)
Based on the code above, i figured it would print 'Testing' on the cmd line, when i adjust the Overlap scale. Nothing happened. To test the code, i replaced the command in generic scale to
def create_scale(self,parent,xval,yval,start,end,resolution,orient,default,lng,clr,cmdtrig):
OHA_scale = tk.Scale(parent,resolution=resolution, from_=start, to=end, orient=orient,length=lng,fg=clr,command=overlap_percent)
This resulted in an error.
OHA_scale = tk.Scale(parent,resolution=resolution, from_=start, to=end, orient=orient,length=lng,fg=clr,command=overlap_percent)
NameError: name 'overlap_percent' is not defined
I can't quite figure out what I'm doing wrong. How exactly can i use the generic scale function to control multiple scales?
on this line
OHA_scale = tk.Scale(parent,resolution=resolution, from_=start, to=end,
orient=orient,length=lng,fg=clr,command=cmdtrig)
command take function parameters but you send a string value
self.create_scale(Oliveframe,xval,yval,25,75,25,"vertical",75,90,'Black',overlap_percent)
If you do it will be alright

Strange behaviour when function returns NdOverlay to DynamicMap

I've encountered something very strange when having a function which generates an NdOverlay of Points to a DynamicMap, where the function is tied to panel widgets (I don't think the panel widgets are important).
The below code is a working example which produces the expected behavior. Whenever you change the widget values a new plot is generated with two sets of Points overlaid, with different colors and respective legend entries. Image shown below code.
a_widget = pn.widgets.Select(name='A', options=[1,2,3,4])
b_widget = pn.widgets.IntSlider(name='B', start=10, end=20, value=10)
widget_box = pn.WidgetBox(a_widget, b_widget, align='center')
#pn.depends(a=a_widget.param.value, b=b_widget.param.value)
def get_points(a, b):
return hv.NdOverlay({x: hv.Points(np.random.rand(10,10)) for x in range(1,3)})
points = hv.DynamicMap(get_points)
pn.Row(widget_box, points)
The second example shown below, is meant to demonstrate that in certain situations you might want to just simply return an empty plot and the way that I've done it in this example is done in the same way as in this example: http://holoviews.org/gallery/demos/bokeh/box_draw_roi_editor.html#bokeh-gallery-box-draw-roi-editor
The result of this code is an empty plot as expected when a == 1, but when a has values other than 1, the result is quite strange as illustrated in the image below the code.
The points all have the same color
When changing the slider for instance, some points are frozen and never changes, which is not the case in the above working example.
a_widget = pn.widgets.Select(name='A', options=[1,2,3,4])
b_widget = pn.widgets.IntSlider(name='B', start=10, end=20, value=10)
widget_box = pn.WidgetBox(a_widget, b_widget, align='center')
#pn.depends(a=a_widget.param.value, b=b_widget.param.value)
def get_points(a, b):
if a == 1:
return hv.NdOverlay({None: hv.Points([])})
else:
return hv.NdOverlay({x: hv.Points(np.random.rand(10,10)) for x in range(1,3)})
points = hv.DynamicMap(get_points)
pn.Row(widget_box, points)
While I can not help the observed issue with NdOverlay, creating plots with or without content can be done with the help of Overlay.
As b_widget is never used in your code, I removed it for simplicity.
a_widget = pn.widgets.Select(name='A', options=[1,2,3,4])
widget_box = pn.WidgetBox(a_widget, align='center')
#pn.depends(a=a_widget.param.value)
def get_points(a):
images = []
if a == 3:
images.append(hv.Points(np.random.rand(10,10), label='None'))
else:
for x in range(1,3):
images.append(hv.Points(np.random.rand(10,10), label=str(x)))
return hv.Overlay(images)
points = hv.DynamicMap(get_points)
pn.Row(widget_box, points)
The way how to use NdOverlay that is described in the documentation for NdOverlay is different to your approach, this might be a reason for the observed problems.
Anyway, to narrow down which part of the code is responsible for the observed issue, I removed all code that is not necessary to reproduce it.
For clarity, I renamed the values of a, and I also made sure, that a start value for a is provided.
It turned out while testing the code, that the if-else-statement is neither important, so I removed that too.
And just to make sure, that variables behave like expected, I added some print-statements.
This gives the following minimal reproducable example:
a_widget = pn.widgets.Select(name='A', value='Test', options=['Test','Test1', 'Test2'])
#pn.depends(a=a_widget.param.value)
def get_points(a):
dict_ = {}
dict_[str(a)] = hv.Points(np.random.rand(10,10))
print(dict_)
overlay = hv.NdOverlay(dict_)
print(overlay)
return overlay
points = hv.DynamicMap(get_points)
# using the server approach here to see the outpout of the
# print-statements
app = pn.Row(a_widget, points)
app.app()
When running this code, and choosing the different options in the select widget, it turns out that option Test is not updated, once one of the options Test1 and Test3 have been choosen.
When we change the default value in the first line like this
a_widget = pn.widgets.Select(name='A', value='Test2', options=['Test','Test1', 'Test2'])
now Test2 is not updated correctly.
So it looks like this is an issue of DynamicMap using NdOverlay.
So I suggest you report this issue to the developers (if not already done), either wait for new release or use a different approach (e.g. as shown above).

canvasObjects; found PartInstance, expecting tuple in Abaqus/CAE

I'm developening an Abaqus/CAE plug-in, in this plug-in i'm using the gui toolkit, and i have a button that uses the PickStep, on click the button i can select a PartInstance in the viewport.
Then i want to export the selected PartInstance to an .obj file but when i try it, abaqus displays an error.
This is an example of my PICK BUTTON:
# PICK BUTTON 1
pickHf = FXHorizontalFrame(p=col2, opts=0, x=0, y=0, w=0, h=0, pl=0, pr=0, pt=0, pb=0, hs=DEFAULT_SPACING,
vs=DEFAULT_SPACING)
# Note: Set the selector to indicate that this widget should not be
# colored differently from its parent when the 'Color layout managers'
# button is checked in the RSG Dialog Builder dialog.
pickHf.setSelector(99)
label1 = FXLabel(p=pickHf, text='' + ' (None)', ic=None, opts=LAYOUT_CENTER_Y | JUSTIFY_LEFT)
pickHandler1 = DBPickHandler(form, form.uper, 'Select a 3D, discrete and dependent meshed instance', INSTANCES,
1, label1)
icon = afxGetIcon('select', AFX_ICON_SMALL)
FXButton(p=pickHf, text='\tPick Items in Viewport', ic=icon, tgt=pickHandler1, sel=AFXMode.ID_ACTIVATE,
opts=BUTTON_NORMAL | LAYOUT_CENTER_Y, x=0, y=0, w=0, h=0, pl=2, pr=2, pt=1, pb=1)
I save the value in an ObjectKeyword:
self.uper = AFXObjectKeyword(self.cmd, 'uper', True, pickedDefault)
This is how i export the PartInstance to .obj:
print 'Uper - ' + uper[0].name
f.write('Uper - '+uper[0].name+'\n')
session.writeOBJFile(fileName='C:/temp/Uper.obj', canvasObjects=(uper[0]))
That displays and error, and i also tried this:
print 'Fixed - ' + fixed[0].name
f.write(fixed[0].name+'\n')
fixedobj = open('Fixed.obj', 'w')
pickle.dump(fixed[0], fixedobj)
fixedobj.close()
But that does not work either.
I get this error:
canvasObjects;found PartInstance, expecting tuple
This answer will help you. On your call to session.writeOBJFile you are trying to create a one element tuple for the canvasObjects argument. Simply wrapping the item in parentheses won't achieve that. You need to add a comma to make it a tuple:
session.writeOBJFile(fileName='C:/temp/Uper.obj', canvasObjects=(uper[0],))
The Abaqus documentation says this about canvasObjects:
canvasObjects
A sequence of canvas objects to export.
I'm not sure if PartInstance is considered a canvas object or not, but you may still have problems even after correcting the argument to be a tuple. If so, make sure the items of the tuple are proper canvas objects.

How can i use a function to condense my code?

fairly new to programming & i know i can use a function to condense this code bc its just mainly text im writing and ive used so many lines already. I've played around with defining my own function etc and i failed. Anyone know how i can make a function that includes like font size, if i want bold and font face???
This was my most recent attempt at doing it - but it didnt work:
def style(x, y, z,):
return Entry(Point(x,y),"z")
Below is my actual code.
# create the window to hold the contents
win = GraphWin("Text & Shapes Frenzy", 500, 500)
win.setBackground("Yellow")
#Setting the Title Screen:
title=Text(Point(400,250),"Text & Shapes Frenzy")
title.setFace('arial')
title.setSize(30)
title.setStyle('bold')
title.setFill('White')
title.draw(win)
#Mini-Heading
subheading=Text(Point(400,290), "Click to continue!")
subheading.setFace('courier')
subheading.setSize(22)
subheading.setFill('Blue')
subheading.draw(win)
message=Text(Point(400,50),"""Each click on the next page, adds a new
shape or text!""")
message.setFace('arial')
message.setSize(24)
message.setStyle('bold')
message.setFill('Red')
message.draw(win)
Use
def create_title(x,y,text,face,size,style,fill):
title=Text(Point(x,y),text)
title.setFace(face)
title.setSize(size)
title.setStyle(style)
title.setFill(fill)
title.draw(win)
return title
title=condense_funtion(400,250,"Text & Shapes Frenzy",.........)
subheading=condense_funtion(.........)
message=condense_funtion(.........)
replacing your values when calling the function cheers!
This is not the perfect solution but it is just to give you an idea. You can make a function that construct the object for you like this:
def set_obj(x=None, y=None, text=None, face=None, size=None, style=None, fill=None, background=None):
myobj = Text(Point(x,y), text)
if face:
myobj.setFace(face)
if size:
myobj.setSize(size)
...
return myobj
message = set_obj(x=400, y=500, text='bla bla', face='arial', size=24, style='bold', fill='Red', background=None)

Python plots - I fixed this code, but need someone to explain how it worked in the first place

I have the following python code:
def graph(seconds,now, dayold, threedayold,weekold):
x = np.arange(len(seconds))
ynow = np.array(now)
yday = np.array(dayold)
y3day = np.array(threedayold)
yweek = np.array(weekold)
# y2 should go on top, so shift them up
plt.plot(x,ynow)
plt.plot(x,yday)
plt.plot(x,y3day,'purple')
plt.plot(x,yweek)
plt.fill_between(x,ynow,yday,color='lightblue')
plt.fill_between(x,yday,y3day,color='green')
plt.fill_between(x,y3day,yweek,color='purple')
plt.fill_between(x,yweek,0,color='red')
plt.show()
which produces this graph:
However, 'seconds' is a list of non-continues results and what I really want is:
def graph(seconds,now, dayold, threedayold,weekold):
x = np.array(seconds)
ynow = np.array(now)
yday = np.array(dayold)
y3day = np.array(threedayold)
yweek = np.array(weekold)
# y2 should go on top, so shift them up
plt.plot(x,ynow)
plt.plot(x,yday)
plt.plot(x,y3day,'purple')
plt.plot(x,yweek)
plt.fill_between(x,ynow,yday,color='lightblue')
plt.fill_between(x,yday,y3day,color='green')
plt.fill_between(x,y3day,yweek,color='purple')
plt.fill_between(x,yweek,0,color='red')
plt.show()
So that I could get a proper X-Y plot. However when I try the second bit of code I get this error:
josephs-mbp-3$Traceback (most recent call last):
File "./temp.py", line 47, in <module>
graph(a[0],a[1],a[2],a[3],a[4])
File "./temp.py", line 41, in graph
plt.fill_between(x,yweek,0,color='red')
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/matplotlib/pyplot.py", line 2287, in fill_between
ret = ax.fill_between(x, y1, y2, where, interpolate, **kwargs)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/matplotlib/axes.py", line 6489, in fill_between
y2 = np.ones_like(x)*y2
NotImplementedError: Not implemented for this type
Can anyone tell me what is causing this and how I fix it?
EDIT: Ah-ha! I fixed it, but would like someone to tell me how...
Changing
plt.fill_between(x,yweek,0,color='red')
to
plt.fill_between(x,yweek,[0]* len(seconds),color='red')
produced what I wanted - and I can understand why this would be a problem, but I'm confused as to why the first version worked at all... any ideas?
I think that seconds is probably a list of number strings, perhaps loaded from a file, rather than a list of numeric types.
The fill_between function of matplotlib expects an array of numeric type as an argument or else it crashes. This is a bit confusing since the plot function seems to do a cast from string to float when you call it.
So I think doing something like:
x = [float(i) for i in seconds]
rather than:
x = np.array(seconds)
should solve your problem!

Categories

Resources