I want to plot multiple items in a pyQt4 gui from a list selection which the user can select which plots to show. They can do this as many times as they want. Each time they plot new data, the legend persists even though the plots do not. My code is :
self.DataPlotter.setLabels(left=("magnitude"),bottom=(str(x_ind)))
title = str(y_ind) + " vs " + str(x_ind)
self.DataPlotter.setTitle(title)
self.DataPlotter.addLegend()
for y,c in zip(y_ind,range(len(y_ind))):
self.DataPlotter.plot(self.df[x_ind].tolist(),self.df[y].tolist(), name=y, pen=(c,4))
How do I destroy the old legend each run?
I found the solution here:
https://groups.google.com/forum/#!topic/pyqtgraph/DdWyB1ljQdw
I needed to add this (not sure if try/except is necessary):
try:
self.legend.scene().removeItem(self.legend)
except Exception as e:
print e
Final code looks this:
self.DataPlotter.setLabels(left=("magnitude"),bottom=(str(self.x_ind)))
title = str(self.y_ind) + " vs " + str(self.x_ind)
self.DataPlotter.setTitle(title)
try:
self.legend.scene().removeItem(self.legend)
except Exception as e:
print e
self.legend = self.DataPlotter.addLegend()
for y,c in zip(y_ind,range(len(y_ind))):
self.DataPlotter.plot(self.df[x_ind].tolist(),self.df[y].tolist(), name=y, pen=(c,4))
Related
I am trying to implement an interactive dashboard in Bokeh with a "play" function that loops through all value pairs for two indicators selected by widgets.
Screen cap of dashboard
While the loop works, the dashboard resets the axis values for each step of the loop. So what I need is to set axis values based on the widget.value selected. To this end, I have built a data frame "ranges" that has the name of the indicator as index and the min/max value for each indicator as columns.
The updates for controls work thusly (x_axis,etc. are the names of the widgets):
controls = [x_axis, y_axis, start_yr, end_yr, years]
for control in controls:
control.on_change('value', lambda attr, old, new: update())
The update function is supposed to update the ranges upon change in the controls like this:
def update():
p.x_range = Range1d(start = ranges.loc[x_axis.value,"Min"],
end = ranges.loc[x_axis.value,"Max"])
p.y_range = Range1d(start = ranges.loc[y_axis.value,"Min"],
end = ranges.loc[y_axis.value,"Max"])
What should happen: Whenever I change the value of the widget, the ranges should update, but other than that, they should remain constant
What does happen: The ranges are set based on the value of the widget initially set and don't change on update.
I've tried to find examples trying to achieve something similar but no luck.
This is a working example:
import numpy as np
from bokeh.plotting import figure
from bokeh.models import Range1d
from bokeh.io import curdoc
x = np.linspace(0, 100, 1000)
y = np.sin(x)
p = figure(x_range=(0, 100))
p.circle(x, y)
def cb():
# this works:
p.x_range.start += 1
p.x_range.end += 1
# this also works:
#p.x_range = Range1d(p.x_range.start+1, p.x_range.end+1)
curdoc().add_periodic_callback(cb, 200)
curdoc().add_root(p)
I'm getting the text from the title and href attributes from the HTML. The code runs fine and I'm able to import it all into a PrettyTable fine. The problem that I face now is that there are some titles that I believe are too large for one of the boxes in the table and thus distort the entire PrettyTable made. I've tried adjusting the hrules, vrules, and padding_width and have not found a resolution.
from bs4 import BeautifulSoup
from prettytable import PrettyTable
import urllib
r = urllib.urlopen('http://www.genome.jp/kegg-bin/show_pathway?map=hsa05215&show_description=show').read()
soup = BeautifulSoup((r), "lxml")
links = [area['href'] for area in soup.find_all('area', href=True)]
titles = [area['title'] for area in soup.find_all('area', title=True)]
k = PrettyTable()
k.field_names = ["ID", "Active Compound", "Link"]
c = 1
for i in range(len(titles)):
k.add_row([c, titles[i], links[i]])
c += 1
print(k)
How I would like the entire table to display as:
print (k.get_string(start=0, end=25))
If PrettyTable can't do it. Are there any other recommended modules that could accomplish this?
This was not a formatting error, but rather the overall size of the table created was so large that the python window could not accommodate all the values on the screen.
This proven by changing to a much smaller font size. If it helps anyone exporting as .csv then arranging in Excel helped.
I have a page with a HTML table with 16 rows and 5 columns.
I have a method to loop through the table and print out the cell values.
I get the following error:
raise exception_class(message, screen, stacktrace)
StaleElementReferenceException: Message: Element is no longer valid
The error happens on this line:
col_name = row.find_elements(By.TAG_NAME, "td")[1] # This is the Name column
My method code is:
def get_variables_col_values(self):
try:
table_id = self.driver.find_element(By.ID, 'data_configuration_variables_ct_fields_body1')
#time.sleep(10)
rows = table_id.find_elements(By.TAG_NAME, "tr")
print "Rows length"
print len(rows)
for row in rows:
# Get the columns
print "cols length"
print len(row.find_elements(By.TAG_NAME, "td"))
col_name = row.find_elements(By.TAG_NAME, "td")[1] # This is the Name column print "col_name.text = "
print col_name.text
except NoSuchElementException, e:
return False
Am i getting the element is no longer valid because the dom has updated, changed?
The table has not completed in loading?
How can i solve this please?
Do i need to wait for the page to be fully loaded, completed?
Should i use the following WebdriverWait code to wait for page load completed?
WebDriverWait(self.driver, 10).until(lambda d: d.execute_script('return document.readyState') == 'complete')
Where about in my code should i put this line if this is required?
I ran my code again, the 2nd time it worked. The output was:
Rows length
16
cols length
6
col_name.text =
Name
cols length
6
col_name.text =
Address
cols length
6
col_name.text =
DOB
...
So I need to make my code better so it works every time i run my test case.
What is the best solution?
Thanks,
Riaz
StaleElementReferenceException: Message: Element is no longer valid can mean that the page wasn't completely loaded or a script that changes the page elements was not finished running, so the elements are still changing or not all present after you start interacting with them.
You're on the right track! Using explicate waits are good practice to avoid StaleElementReferenceException and NoSuchElementException, since your script will often execute commands much faster than a web page can load or JavaScript code can finish.
Use WebDriverWait before you use WebDriver commands.
Here's a list of different "Expected Conditions" you can use to detect that page is loaded completely or at least loaded enough: http://selenium-python.readthedocs.org/en/latest/waits.html
An example of where to place the wait in your code, with an example of waiting up to 10 seconds for all 'td' elements to finish loading (you may need to use a different type of condition, amount of time, or wait for a different element, depending on what the web page as a whole is like):
from selenium.webdriver.support import expected_conditions as EC
def get_variables_col_values(self):
try:
WebDriverWait(self.driver, 10).until(EC.presence_of_all_elements_located((By.TAG_NAME,'td')))
table_id = self.driver.find_element(By.ID, 'data_configuration_variables_ct_fields_body1')
#time.sleep(10)
rows = table_id.find_elements(By.TAG_NAME, "tr")
print "Rows length"
print len(rows)
for row in rows:
# Get the columns
print "cols length"
print len(row.find_elements(By.TAG_NAME, "td"))
col_name = row.find_elements(By.TAG_NAME, "td")[1] # This is the Name column print "col_name.text = "
print col_name.text
except NoSuchElementException, e:
return False
I am trying to learn creating GUI using Tkinter .I created a window which includes text,Messagebox,Entry widget,labels and Radio buttons.
I used grid method for frames and tried to make entry boxes in row0 and row1 .And a message Box with Some text.But these are not properly aligned even though i gave correct rows and columns but output is not in order.
Entry box is created very far though i mentioned column1 .And message box is created as per the column specified.Can anyone help me how to solve this.If i am missing anything please let me now .
from Tkinter import*
import tkMessageBox
class Example:
def __init__(self,root):
root.title("Sample")
#Entry functions ---------------------------------------
Label(root, text="First Name").grid(row=0)
Label(root, text="Last Name").grid(row=1)
self.e1 = Entry(root)
self.e1.bind("<Return>",self.ShowChoice_radio)
self.e2 = Entry(root)
self.e2.bind("<Return>",self.ShowChoice_radio)
self.e1.grid(row=0,column=1)
self.e2.grid(row =1,column = 1)
#------------------------------------------------------------------------
self.frame=Frame(root)
self.frame.grid(row=3,sticky=W)
self.label=Label(self.frame, text="mine", width=12,bg="green",fg="white",justify=LEFT)
self.label.grid(row=3,column=4,sticky=W,pady=4)
root.minsize(width=666, height=220)
self.v=IntVar()
role=[("ENGLISH",1),("SPANISH",2),("GERMAN",3)]
Label(self.frame,text="Choose your role of target:",justify=LEFT,padx=2,pady=2).grid(row=4,sticky=W)
i=0
for txt,val in role:
i=i+1
self.rad_bt=Radiobutton(self.frame,text=txt,padx=20,variable=self.v,
command=self.ShowChoice_radio,value=val)
self.rad_bt.grid(row=4,column=i+1)
self.bottomframe = Frame(root)
self.bottomframe.grid(row=12,sticky=W)
self.hello(12)
T=Text(self.bottomframe,height=2,width=30)
T.pack(padx=100,side=TOP)
T.insert(END,"just a normal text to display!\n")
self.mbutton=Button(self.bottomframe,text='Quit',command=self.callback,state='normal')
self.mbutton.pack(padx=3,pady=3,side='left')
self.help=Button(self.bottomframe,text='Help',command=self.help_msg,width=5,justify=CENTER)
self.help.pack(padx=93,pady=3,side='left')
def ShowChoice_radio(self):
print self.v.get()
def help_msg(self):
tkMessageBox.showinfo("Help to print ",message="Not yet implemented")
root.minsize(width=666, height=666)
self.show_entry_fields()
self.help.config(state=DISABLED)
def callback(self):
if tkMessageBox.askyesno('verify','Really Quit?'):
root.destroy()
def hello(self,name):
w=Label(root,text="Hello Tkinter!",width=15).grid(row=10)
whatever_you_do = "Whatever . it is my test that \n i can anble to display manner in this case find out whether it is correct one or wrong \n)"
msg=Message(root, anchor='s',width=200,text = whatever_you_do)
msg.config(bg='lightgreen', font=('times', 14, 'italic'))
msg.grid(row=10,column=1,sticky=W)
def show_entry_fields(self):
print "First Name: %s\nLast Name: %s" % (self.e1.get(), self.e2.get())
if __name__=="__main__":
root=Tk()
app=Example(root)
root.mainloop()
Even the quit and Help buttons are not proper...!!!
I initially voted to close this because there is not a clear question, but mostly only a series of statements and opinions, at least one of which is incorrect. After looking more, I think I can answer your implied question "Why is tkinter behaving in a way that seems wrong to me?". The answer, I believe, is that you do not understand that grid coordinates are independent (start over) for each container gridded. Also, coordinates not used are ignored. In particular:
Root has a grid of 5 rows and 2 columns. Renumbering the rows 0, 1, 2, 3, 4 instead of the confusing labeling you used, there is no entry in column 1 for rows 2 and 4. The width of column 0 is determined by the width of self.frame in row 2, column 0. The entry boxes are far to the right because column 0 is very wide.
Self.frame has a grid of 2 rows and 4 columns. The first 3 columns of row 0 are empty. Self.bottomframe is packed instead of gridded. The buttons are to the left of where you want because you packed them to the left. In other words, tkinter did just what you said, which is apparently not what you want.
You might list the result better if you got rid of self.frame, put 'mine' in (2,0) or (2,0), 'Choose...' in (3, 0), and a frame with 3 radio buttoms in (3,1). Then root column 0 would not be so overly wide.
I am currently using python 2.7, and I am having a little bit of trouble coding this idea I have. I know it is easy enough to color text in the terminal in python 2.7 with libraries like colorama or termcolor, but these methods don't quite work in the way I am trying to use.
You see, I am trying to create a text based adventure game, that not only has colored text, but also gives a quick typewriter-style effect when doing so. I have the typewriter effect down pat, but anytime I try to integrate it with a colorizing library the code fails, giving me the raw ASCII character instead of the actual color.
import sys
from time import sleep
from colorama import init, Fore
init()
def tprint(words):
for char in words:
sleep(0.015)
sys.stdout.write(char)
sys.stdout.flush()
tprint(Fore.RED = "This is just a color test.")
If you run the code, you will see that the typewriter effect works, but the color effect does not. Is there any way I can "embed" the color into the text so that sys.stdout.write will show the color with it?
Thank You
EDIT
I think I may have found a workaround, but it is kind of a pain to change the color of individual words with this method. Apparently, if you use colorama to set the ASCII color before you call the tprint function, it will print in whatever the last set color was.
Here is the example code:
print(Fore.RED)
tprint("This is some example Text.")
I would love any feedback/improvements on my code, as I would really like to find a way to call the Fore library within the tprint function without causing ASCII errors.
TL;DR: Prepend your string with the desired Fore.COLOUR and don't forget to Fore.RESET at the end.
First of all - cool typewriter function!
In your workaround you are merely printing nothing (i.e. '') in red, then by default the next text you print is also in red. All text that follows will be in red until you Fore.RESET the colour (or exit).
A better (more pythonic?) way is to directly and explicitly build your strings with the colour you want.
Here's a similar example, pre-pending Fore.RED and appending Fore.RESET to the string before sending to your tprint() function:
import sys
from time import sleep
from colorama import init, Fore
init()
def tprint(words):
for char in words:
sleep(0.015)
sys.stdout.write(char)
sys.stdout.flush()
red_string = Fore.RED + "This is a red string\n" + Fore.RESET
tprint(red_string) # prints red_string in red font with typewriter effect
Setting aside your tprint() function for simplicity's sake, this method of colour-typing also works for concatenation of strings:
from colorama import init, Fore
init()
red_fish = Fore.RED + 'red fish!' + Fore.RESET
blue_fish = Fore.BLUE + ' blue fish!' + Fore.RESET
print red_fish + blue_fish # prints red, then blue, and resets to default colour
new_fish = red_fish + blue_fish # concatenate the coloured strings
print new_fish # prints red, then blue, and resets to default colour
Going further - to build a single string with multiple colours:
from colorama import init, Fore
init()
rainbow = Fore.RED + 'red ' + Fore.YELLOW + 'yellow ' \
+ Fore.GREEN + 'green ' + Fore.BLUE + 'blue ' \
+ Fore.MAGENTA + 'magenta ' + Fore.RESET + 'and then back to default colour.'
print rainbow # prints in each named colour then resets to default
This is my first answer on Stack so I don't have the reputation required to post images of my terminal window output.
The official colorama docs have more useful examples and explanations. Hope I haven't missed too much, good luck!