How to obtain the contour plot data for each scatter points? - python-2.7

I have plotted a contour plot as background which represent the altitude of the area.
And 100 scatter points were set represent the real pollutant emission source. Is there a method to obtain the altitude of each point?
This is my code:
%matplotlib inline
fig=plt.figure(figsize=(16,16))
ax=plt.subplot()
xi,yi = np.linspace(195.2260,391.2260,50),
np.linspace(4108.9341,4304.9341,50)
height=np.array(list(csv.reader(open("/Users/HYF/Documents/SJZ_vis/Concentration/work/terr_grd.csv","rb"),delimiter=','))).astype('float')
cmap = cm.get_cmap(name='terrain', lut=None)
terrf = plt.contourf(xi, yi, height,100, cmap=cmap)
terr = plt.contour(xi, yi, height, 100,
colors='k',alpha=0.5
)
plt.clabel(terr, fontsize=7, inline=20)
ax.autoscale(False)
point= plt.scatter(dat_so2["xp"], dat_so2["yp"], marker='o',c="grey",s=40)
ax.autoscale(False)
for i in range(0,len(dat_so2["xp"]),1):
plt.text(dat_so2["xp"][i], dat_so2["yp"][i],
str(i),color="White",fontsize=16)
ax.set_xlim(225,275)
ax.set_ylim(4200,4260)
plt.show()

You can do this with scipy.interpolate.interp2d
For example, you could add to your code:
from scipy import interpolate
hfunc = interpolate.interp2d(xi,yi,height)
pointheights = np.zeros(dat_so2["xp"].shape)
for i,(x,y) in enumerate(zip(dat_so2["xp"],dat_so2["yp"])):
pointheights[i]=hfunc(x,y)
Putting this together with the rest of your script, and some sample data, gives this (I've simplified a couple of things here, but you get the idea):
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
from scipy import interpolate
fig=plt.figure(figsize=(8,8))
ax=plt.subplot()
#xi,yi = np.linspace(195.2260,391.2260,50),np.linspace(4108.9341,4304.9341,50)
xi,yi = np.linspace(225,275,50),np.linspace(4200,4260,50)
# A made up function of height (in place of your data)
XI,YI = np.meshgrid(xi,yi)
height = (XI-230.)**2 + (YI-4220.)**2
#height=np.array(list(csv.reader(open("/Users/HYF/Documents/SJZ_vis/Concentration/work/terr_grd.csv","rb"),delimiter=','))).astype('float')
cmap = cm.get_cmap(name='terrain', lut=None)
terrf = plt.contourf(xi, yi, height,10, cmap=cmap)
terr = plt.contour(xi, yi, height, 10,
colors='k',alpha=0.5
)
plt.clabel(terr, fontsize=7, inline=20)
ax.autoscale(False)
# Some made up sample points
dat_so2 = np.array([(230,4210),(240,4220),(250,4230),(260,4240),(270,4250)],dtype=[("xp","f4"),("yp","f4")])
point= plt.scatter(dat_so2["xp"], dat_so2["yp"], marker='o',c="grey",s=40)
# The interpolation function
hfunc = interpolate.interp2d(xi,yi,height)
# Now, for each point, lets interpolate the height
pointheights = np.zeros(dat_so2["xp"].shape)
for i,(x,y) in enumerate(zip(dat_so2["xp"],dat_so2["yp"])):
pointheights[i]=hfunc(x,y)
print pointheights
ax.autoscale(False)
for i in range(0,len(dat_so2["xp"]),1):
plt.text(dat_so2["xp"][i], dat_so2["yp"][i],
str(i),color="White",fontsize=16)
# We can also add a height label to the plot
plt.text(dat_so2["xp"][i], dat_so2["yp"][i],
"{:4.1f}".format(pointheights[i]),color="black",fontsize=16,ha='right',va='top')
ax.set_xlim(225,275)
ax.set_ylim(4200,4260)
plt.show()

Related

How to draw sub-structures of a polycyclic aromatic which shows bond angles correctly?

thank you for reading my question.
Assume that I have a polycyclic aromatic (let's call it "parent molecule") as shown below:
smile = "c1ccc2ocnc2c1"
mol = Chem.MolFromSmiles(smile)
When I draw sub-structures of the parent molecule, I notice that the bond angles in sub-structures are different from the bond angles in the parent molecule. Following is the code that I use:
from rdkit import Chem
from rdkit.Chem.Draw import rdMolDraw2D
from IPython.display import SVG
smile_1 = 'c(cc)cc'
smile_2 = 'n(co)c(c)c'
m1 = Chem.MolFromSmiles(smile_1,sanitize=False)
Chem.SanitizeMol(m1, sanitizeOps=(Chem.SanitizeFlags.SANITIZE_ALL^Chem.SanitizeFlags.SANITIZE_KEKULIZE^Chem.SanitizeFlags.SANITIZE_SETAROMATICITY))
m2 = Chem.MolFromSmiles(smile_2,sanitize=False)
Chem.SanitizeMol(m2, sanitizeOps=(Chem.SanitizeFlags.SANITIZE_ALL^Chem.SanitizeFlags.SANITIZE_KEKULIZE^Chem.SanitizeFlags.SANITIZE_SETAROMATICITY))
mols = [m1, m2]
smiles = ["smile_1", "smile_2"]
molsPerRow=2
subImgSize=(200, 200)
nRows = len(mols) // molsPerRow
if len(mols) % molsPerRow:
nRows += 1
fullSize = (molsPerRow * subImgSize[0], nRows * subImgSize[1])
d2d = rdMolDraw2D.MolDraw2DSVG(fullSize[0], fullSize[1], subImgSize[0], subImgSize[1])
d2d.drawOptions().prepareMolsBeforeDrawing=False
d2d.DrawMolecules(mols, legends=smiles)
d2d.FinishDrawing()
SVG(d2d.GetDrawingText())
Which results in the following drawing:
As can be seen, the angles between several bonds in sub-structures are different from the parent molecule.
Is there any way to draw sub-structures with the same bond angles as parent molecule?
Any help is greatly appreciated.
You can set the original positions of your parent to the substructure.
from rdkit import Chem
from rdkit.Chem.Draw import IPythonConsole
from rdkit.Chem import rdDepictor
rdDepictor.SetPreferCoordGen(True)
def getNiceSub(parent, sub):
# Get the coordinates of parent (also need to built a conformer)
mol = Chem.MolFromSmiles(parent)
rdDepictor.Compute2DCoords(mol)
# Get the coordinates of substructure to built a conformer
substruct = Chem.MolFromSmiles(sub, sanitize=False)
rdDepictor.Compute2DCoords(substruct)
# Get the index of the matched atoms
ms = mol.GetSubstructMatch(substruct)
# Get the positions of the matched atoms
conf1 = mol.GetConformer()
p = [list(conf1.GetAtomPosition(x)) for x in ms]
# Set the original positions of parent to substructure
conf2 = substruct.GetConformer()
for n in range(len(ms)):
conf2.SetAtomPosition(n, p[n])
return substruct
parent = 'c1ccc2ocnc2c1'
substructer = 'n(co)c(c)c'
nicesub = getNiceSub(parent, substructer)
parent
substructure

Python 2.7, Tkinter, make a point "trace" a waveform

I'm trying to make a widget that demonstrates the relationship between a sine wave and it's phasor diagram. I want a pointer that follows the user's mouse movements but instead of freely moving around the page, I want it to stick to the waveform I've plotted and only follow the co-ordinates that make up that line. Kind of like a slider but along a sine wave! Any suggestions? Thanks. Here's what I've got so far;
import math
import Tkinter as tk
from Tkinter import PhotoImage, Canvas
from PIL import Image, ImageTk
sinwidget = tk.Tk()
main_canvas = tk.Canvas(sinwidget, width = 400, height = 400, bg= "white")
main_canvas.pack()
def callback(event):
canvas = event.widget
x = canvas.canvasx(event.x)
y = canvas.canvasy(event.y)
print canvas.find_closest(x, y)
draw(event.x, event.y)
def draw(x, y):
box.coords(pointer, x-20, y-20, x+20, y+20)
def exit_():
sinwidget.destroy()
box = main_canvas
box.bind('<Motion>', callback)
box.pack()
pointer = box.create_rectangle(0.2,0.2,0.2,0.2)
wavelength = 360
height = 400
center = height//2
degree = 1
increment = 0.0175
amplitude = -80
sin = []
for x in range(360):
sin.append(x * degree)
sin.append(int(math.sin(x * increment) * amplitude) + center)
sinwave = main_canvas.create_line(sin, fill="red", width=2.0)
xaxis = main_canvas.create_line(0, center, wavelength, center, fill="black",
width=3.0)
yaxis = main_canvas.create_line(2, 100, 2, 300, fill="black", width=3.0)
exit_button = tk.Button(sinwidget, text = "exit", command = exit_)
exit_button.pack()
sinwidget.mainloop()
Thanks for any help you can offer!

Registering screen change in python?

So using tkinter I have made a simple program that changes the color of all shapes on the canvas to a random color every second ,what I am looking for is a way to register every screen change and write down the time between screen changes in a separate file.I also need to do it without the help of too many external libraries if possible.
My code so far:
#!/usr/bin/python -W ignore::DeprecationWarning
import Tkinter
import tkMessageBox
import time
import random
colors = ['DarkOrchid1','chocolate3','gold2','khaki2','chartreuse2','deep pink','white','grey','orange']
top = Tkinter.Tk()
global b
b=0
C = Tkinter.Canvas(top, bg="blue", height=600, width=800)
bcg1=C.create_rectangle(0,0,800,100,fill=random.choice(colors))
bcg2=C.create_rectangle(0,100,800,200,fill=random.choice(colors))
bcg3=C.create_rectangle(0,200,800,300,fill=random.choice(colors))
bcg4=C.create_rectangle(0,300,800,400,fill=random.choice(colors))
bcg5=C.create_rectangle(0,400,800,500,fill=random.choice(colors))
bcg6=C.create_rectangle(0,500,800,600,fill=random.choice(colors))
bcgs=[bcg1,bcg2,bcg3,bcg4,bcg5,bcg6]
coord = 10, 50, 240, 210
rect1=C.create_rectangle(0,0,100,100,fill="green")
rect2=C.create_rectangle(700,500,800,600,fill="green")
rect3=C.create_rectangle(0,500,100,600,fill="green")
rect4=C.create_rectangle(700,0,800,100,fill="green")
def color():
global b
global bcgs
global color
if b==0:
C.itemconfig(rect1,fill='green')
C.itemconfig(rect2,fill='green')
C.itemconfig(rect3,fill='green')
C.itemconfig(rect4,fill='green')
b=1
count=0
for i in range(len(bcgs)):
C.itemconfig(bcgs[i],fill=random.choice(colors))
elif b==1:
C.itemconfig(rect1,fill='red')
C.itemconfig(rect2,fill='red')
C.itemconfig(rect3,fill='red')
C.itemconfig(rect4,fill='red')
b=0
for i in range(len(bcgs)):
C.itemconfig(bcgs[i],fill=random.choice(colors))
top.after(2000, color)
C.pack()
color()
top.mainloop()
Unless you use a real time OS, you will never get perfect timing. You can bank on being a few milliseconds off the mark. To see how much, you can calculate the difference in time.time(). For the best accuracy, move the after call to the first thing in the function.
That plus some other improvements:
#!/usr/bin/python -W ignore::DeprecationWarning
import Tkinter
import time
import random
from itertools import cycle
colors = ['DarkOrchid1','chocolate3','gold2','khaki2','chartreuse2','deep pink','white','grey','orange']
rect_colors = cycle(['green', 'red'])
top = Tkinter.Tk()
C = Tkinter.Canvas(top, bg="blue", height=600, width=800)
bcg1=C.create_rectangle(0,0,800,100,fill=random.choice(colors))
bcg2=C.create_rectangle(0,100,800,200,fill=random.choice(colors))
bcg3=C.create_rectangle(0,200,800,300,fill=random.choice(colors))
bcg4=C.create_rectangle(0,300,800,400,fill=random.choice(colors))
bcg5=C.create_rectangle(0,400,800,500,fill=random.choice(colors))
bcg6=C.create_rectangle(0,500,800,600,fill=random.choice(colors))
bcgs=[bcg1,bcg2,bcg3,bcg4,bcg5,bcg6]
coord = 10, 50, 240, 210
rect1=C.create_rectangle(0,0,100,100,fill="green")
rect2=C.create_rectangle(700,500,800,600,fill="green")
rect3=C.create_rectangle(0,500,100,600,fill="green")
rect4=C.create_rectangle(700,0,800,100,fill="green")
rects = [rect1,rect2,rect3,rect4]
last_time = time.time()
def color():
top.after(2000, color)
global last_time
rect_color = next(rect_colors)
for item in rects:
C.itemconfig(item, fill=rect_color)
for item in bcgs:
C.itemconfig(item, fill=random.choice(colors))
print("{} seconds since the last run".format(time.time() - last_time))
last_time = time.time()
C.pack()
color()
top.mainloop()

How can I add markers on a bar graph in python?

I have made a horizontal bar graph, now I need to add markers on the bars. How can I do so?
The code I have so far is shown below:
def plot_comparison():
lengths = [11380, 44547, 166616, 184373, 193068, 258004, 369582, 462795, 503099, 581158, 660724, 671812, 918449]
y_pos = np.arange(len(length))
error = np.random.rand(len(length))
plt.barh(y_pos, length, xerr=error, align='center', alpha=0.4)
plt.yticks(y_pos, length)
plt.xlabel('Lengths')
plt.title('Comparison of different cuts')
plt.show()
You can simply add a plot command, plotting the y_pos against the lengths. Make sure to specify a maker and set linestyle to "" (or "none") otherwise the markers will be connected by straight lines.
The following code may be what you're after.
import matplotlib.pyplot as plt
import numpy as np
lengths = [11380, 44547, 166616, 184373, 193068, 258004, 369582, 462795, 503099, 581158, 660724, 671812, 918449]
y_pos = np.arange(len(lengths))
error = np.array(lengths)*0.08
plt.barh(y_pos, lengths, xerr=error, align='center', alpha=0.4)
plt.plot(lengths, y_pos, marker="D", linestyle="", alpha=0.8, color="r")
plt.yticks(y_pos, lengths)
plt.xlabel('Lengths')
plt.title('Comparison of different cuts')
plt.show()

Obtaining matplotlib slider widget position from callback in non-global context

I wanted to use the matplotlib slider as seen in an example from a previous question (below) inside a GUI window (such as TkInter etc). But, in a non-global context, the variables for the plot ("spos, fig, ax") are not defined. My understanding is that because update is used as a callback function, one can't or shouldn't pass arguments.
If so, how can a plot be updated without global variables? or
How can I obtain the slider position outside the callback function?
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
t = np.arange(0.0, 100.0, 0.1)
s = np.sin(2*np.pi*t)
l, = plt.plot(t,s)
plt.axis([0, 10, -1, 1])
axcolor = 'lightgoldenrodyellow'
axpos = plt.axes([0.2, 0.1, 0.65, 0.03], axisbg=axcolor)
spos = Slider(axpos, 'Pos', 0.1, 90.0)
def update(val):
pos = spos.val
ax.axis([pos,pos+10,-1,1])
fig.canvas.draw_idle()
spos.on_changed(update)
plt.show()
Related:
1) Another related question seems to cover this topic but does not seem to address how the position of the slider is obtained.
2) A similar question was asked and solved with Slider.set_val(). It seems in my case I would need Slider.get_val() instead.
It is possible to pass more arguments to the callback function, for example with functools.partial
def update(data, val):
pos = spos.val
ax.axis([pos,pos+10,-1,1])
fig.canvas.draw_idle()
data['position'] = pos
import functools
data = dict()
spos.on_changed(functools.partial(update, data))
plt.show()
try:
print data['position']
except KeyError:
pass
A class with __call__ method could also be used as a callback.