Shorten a Python turtle program for a house - python-3.x

Below is my turtle program for drawing a yellow house. I can't figure out a way to create a for loop in order to keep the turtle program short. Does anyone have any idea on how to create a loop for the program below?
import turtle
import math
def yellowHouse () :
wn=turtle.Screen()
wn.title("Yellow House")
wn.bgcolor("Blue")
#sideLength = 200
house=turtle.Turtle()
Diagonal_length= 0.5*math.sqrt(2 *(200 ** 2 ))
house.pensize(5)
house.speed(4.6)
house.color("Yellow")
house.left(90)
house.forward(200)
house.right (135)
house.forward(Diagonal_length)
house.right(90)
house.forward(Diagonal_length)
house.left(135)
house.forward(200)
house.left(135)
house.forward(Diagonal_length)
house.right(90)
house.forward(Diagonal_length)
house.left(135)
house.forward(200)
house.right(135)
house.forward(Diagonal_length)
house.right(90)
house.forward(Diagonal_length)
house.right(45)
house.forward(200)
house.left(90)
wn.mainloop()
yellowHouse ()

Since you're building the house out of one shape repeated, I'd opt for stamping over drawing:
from turtle import Turtle, Screen
def yellowHouse(side_length):
wn.register_shape("brick", ((0, 0), (-0.5, -0.5), (0.5, -0.5)))
house = Turtle('brick', visible=False)
house.shapesize(stretch_wid=side_length, outline=5)
house.color("yellow", wn.bgcolor())
house.penup()
for angle in range(360, 0, -90):
house.setheading(angle)
house.stamp()
house.forward(side_length)
house.stamp()
wn = Screen()
wn.title("Yellow House")
wn.bgcolor("blue")
yellowHouse(200)
wn.exitonclick()
This solution prints the house in the center of the screen. You pass in the size of the house you want. (And it's about 1/3 less code.)

Creating a loop is a good way to make the program code short, you can achieve that in many ways, in your example:
Method 1
use loop to draw the square, then draw the diagonal cross lines and the top
import turtle
def yellowHouse() :
wn=turtle.Screen()
wn.title("Yellow House")
wn.bgcolor("Blue")
house=turtle.Turtle()
house.pensize(5)
house.speed(4.6)
house.color("Yellow")
side = 200
diag = (2*(side**2))**0.5
ang = 90
for i in range(4):
house.fd(side)
house.lt(ang)
house.lt(ang/2)
moves = [(diag,ang),(diag/2,ang),(diag/2,ang),(diag,ang)]
for (move,turn) in moves:
house.fd(move)
house.lt(turn)
wn.mainloop()
yellowHouse()
Method 2
use loop through array of steps to draw the whole shape
import turtle
def yellowHouse() :
wn=turtle.Screen()
wn.title("Yellow House")
wn.bgcolor("Blue")
house=turtle.Turtle()
house.pensize(5)
house.speed(4.6)
house.color("Yellow")
side = 200
diag = (2*(side**2))**0.5
ang = 90
moves = [(side,ang),(side,ang),(side,ang),(side,ang),
(0,ang/2),(diag,ang),(diag/2,ang),(diag/2,ang),(diag,ang)]
for (move,turn) in moves:
house.fd(move)
house.lt(turn)
wn.mainloop()
yellowHouse()
Notice we didn't need to import math, since we only need sqrt() to calculate the square root which we can achieve using the ** exponent operator sqrt(x) is same as x**0.5

here is your code with forloop, you have to maintain event and event value index only..
import turtle
import math
def yellowHouse() :
wn=turtle.Screen()
wn.title("Yellow House")
wn.bgcolor("Blue")
#sideLength = 200
house=turtle.Turtle()
Diagonal_length= 0.5*math.sqrt(2 *(200 ** 2 ))
event = ["pensize","speed","color","left","forward","right","forward","right","forward","left","forward","left","forward","right","forward","left","forward","right","forward","right","forward","right","forward","left"]
event_val = [5,4.6,"Yellow",90,200,135,Diagonal_length,90,Diagonal_length,135,200,135,Diagonal_length,90,Diagonal_length,135,200,135,Diagonal_length,90,Diagonal_length,45,200,90]
event_zip = zip(event, event_val)
for i,j in event_zip:
if type(j).__name__ == "str":
eval("house.{}('{}')".format(i,j))
else:
eval("house.{}({})".format(i,j))
yellowHouse()

Related

Modeling the trajectory of the planet around the sun. Ellipse is not closing

I was trying to create the projection of planets around the sun. Using the RungeKutta I'm trying to project and create the matplotlib graph. However, the out ellipse is not closing. Could you please help me, where exactly I'm doing the mistake?
Used Runge Kutta to find a vector R having the position as a function of time. And when I use the plot to draw the trajectory it doesn't make an ellipse which is what I am supposed to find.
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
#unités de normalisation
UA=149.59787e6 #distance moyenne Terre-Soleil
MASSE=6.0e24 #masse Terre
JOUR=24*3600
#données :
k=0.01720209895
G=(k**2) # constante de gravitation en km^3/kg/s²
r0= 1 # distance initiale terre soleil en m
Ms = 2.0e30/MASSE #masse Soleil
Mt = 1 #masse Terre
w0 = 30/(UA/JOUR) #vitesse angulaire en Km/s
C = r0*(w0**2)
m = (Ms*Mt/Ms+Mt) #masse réduite
K = G*m #on choisit K > 0
b = 2 #beta
def RK4(F, h, r, theta, t, *args):
k1=F(t,r,theta,)[0]
l1=F(t,r,theta,)[1]
k2=F(t+h/2,r+h*k1/2,theta+h*l1/2)[0]
l2=(t+h/2,r+h*k1/2,theta+h*l1/2)[1]
k3=F(t+h/2,r+h*k2/2,theta+h*l2/2)[0]
l3=F(t+h/2,r+h*k2/2,theta+h*l2/2)[1]
k4=F(t+h,r+h*k3,theta+h*l3/2)[0]
l4=F(t+h,r+h*k3,theta+h*l3/2)[1]
return [r +(h/6)*(k1+2*k2+2*k3+k4),theta +(h/6)*(l1+2*l2+2*l3+l4)]
def F1(t,r,theta):
return np.array([r[1],r[0]*theta[1]**2-K/r[0]**b]),np.array([theta[1],-2*r[1]*theta[1]/r[0]])
def RK4N(F1,N,r0,r1,theta0,theta1,ta,tb):
h=0.05
ri=np.array([r0,r1])
thetai=np.array([theta0,theta1])
ti=ta
R=np.zeros((N,2))
THETA=np.zeros((N,2))
lt=np.zeros(N)
lt[0], R[0],THETA[0] = ta , ri ,thetai
for i in range (1, N):
a = ri
ri = RK4(F1,h,ri,thetai,ti)[0]
thetai=RK4(F1,h,a,thetai,ti)[1]
ti=ti+h
R[i]=ri
THETA[i]=thetai
lt[i]=ti
return R,THETA,lt
def trace_position(F1,N,r0,r1,theta0,theta1,ta,tb):
R,THETA,lt=RK4N(F1,N,r0,r1,theta0,theta1,ta,tb)
lx,ly=[],[]
for i in range(N):
lx.append(R[i][0]*np.cos(THETA[i][0]))
ly.append(R[i][0]*np.sin(THETA[i][0]))
plt.plot(lx,ly)
plt.plot(0,0)
plt.show()
# rapport a/b
max_x,min_x,max_y,min_y= max(lx),min(lx),max(ly),min(ly)
rapport = (max_x-min_x)/(max_y-min_y)
print("rapport a/b = ",rapport)
if abs(rapport-1)< 10e-2:
print("le mouvement est presque circulaire")
else:
print("le mouvement est elliptique")
def trace_Ep(F1,N,r0,r1,theta0,theta1,ta,tb):
R,THETA,lt=RK4N(F1,N,r0,r1,theta0,theta1,ta,tb)
lEp = []
for i in range(N):
lEp.append(-K/R[i][0]**(b-1))
#fig, (ax1, ax2) = plt.subplots(1, 2)
#ax1.plot(lt,lEp)
#ax2.plot(R[:,0],lEp)
plt.plot(lt,lEp)
plt.show()
trace_position(F1,380,r0,0,0,w0,0,1)
Output:
You made a not so uncommon copy-paste error. There is an erroneous division by two left over in
k4=F(t+h,r+h*k3,theta+h*l3/2)[0]
l4=F(t+h,r+h*k3,theta+h*l3/2)[1]
Note also the missing F in the l2 line.
You can shorten these computation and avoid redundant or duplicated computations, and reduce places for errors by one half, by using tuple assignments like in
k4,l4 = F(t+h,r+h*k3,theta+h*l3)
and later
ri, thetai = RK4(F1,h,ri,thetai,ti)
Changing the step size computation to h=(tb-ta)/N as probably initially intended, and using tb=150 to get a closed loop, for a selection of subdivisions one gets the increasingly closed orbits via
for k in range(4):
N = [16,19,25,120][k]
plt.subplot(2,2,k+1,aspect='equal')
trace_position(F1,N,r0,0,0,w0,0,150)
A Runge-Kutta method can't give you a perfectly closed trajectory, because there is energy drift (energy is gradually decreasing).
If you need energy to remain close to the initial value, you can use a symplectic integrator. You can read more about this in Chris Rackauckas's answer on "What does 'symplectic' mean[...]".
However, as Lutz Lehmann pointed out, your time step is small enough, so that's not why your trajectory isn't visibly closed. This info might be interesting for others to know, so I'm leaving this answer here.

Set centre of geopandas map

I can plot a world map with geopandas with:
world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
fig, ax = plt.subplots()
world.plot(ax=ax, color=(0.8,0.5,0.5))
and it works fine, but I would like to center the map on a different longitude than the Prime Meridian. How do I do this?
This is how you can do it:
from shapely.geometry import LineString
from shapely.ops import split
from shapely.affinity import translate
import geopandas
world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
def shift_map(shift):
shift -= 180
moved_map = []
splitted_map = []
border = LineString([(shift,90),(shift,-90)])
for row in world["geometry"]:
splitted_map.append(split(row, border))
for element in splitted_map:
items = list(element)
for item in items:
minx, miny, maxx, maxy = item.bounds
if minx >= shift:
moved_map.append(translate(item, xoff=-180-shift))
else:
moved_map.append(translate(item, xoff=180-shift))
gdf = geopandas.GeoDataFrame({"geometry":moved_map})
fig, ax = plt.subplots()
gdf.plot(ax=ax)
plt.show()
In the first step, you create your world and split it on a pre defined border of yours.
Then you get the bounds of all elements and check if the bounds match your desired shift. Afterwards you translate every element bigger than your border to the left side of the map and move all other elements to the right side, so that they aling with +180°.
This gives you for example:
A map shifted by 120°
Like in this question I needed to reset the centre of the map, but I also needed to move scatter plot network node positions that where bound to (long,lat) coordinates too.
I am hoping to save someone some time, as it's probably not obvious initially that to solve this problem you will have to wrangle some unfamiliar types.
Here is a method for shifting both the underlying map and some additional points:
import geopandas
world =
geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
import matplotlib.pyplot as plt
import geopandas as gpd
from shapely.geometry import LineString
from shapely.ops import split
from shapely.affinity import translate
def shift_geom(shift, gdataframe,pos_all, plotQ=True):
# this code is adapted from answer found in SO
# will be credited here: ???
shift -= 180
moved_geom = []
splitted_geom = []
border = LineString([(shift,90),(shift,-90)])
for row in gdataframe["geometry"]:
splitted_geom.append(split(row, border))
for element in splitted_geom:
items = list(element)
for item in items:
minx, miny, maxx, maxy = item.bounds
if minx >= shift:
moved_geom.append(translate(item, xoff=-180-shift))
else:
moved_geom.append(translate(item, xoff=180-shift))
# got `moved_geom` as the moved geometry
moved_geom_gdf = gpd.GeoDataFrame({"geometry": moved_geom})
# can change crs here
if plotQ:
fig1, ax1 = plt.subplots(figsize=[8,6])
moved_geom_gdf.plot(ax=ax1)
plt.show()
df = pd.DataFrame({'Latitude': [xy[1] for xy in pos_all.values()],
'Longitude': [xy[0] for xy in pos_all.values()]})
gdf = geopandas.GeoDataFrame(df, geometry=geopandas.points_from_xy(df.Longitude, df.Latitude))
border2 = LineString([(shift,90),(shift,-90)])
geom = gdf.geometry.values
moved_map_points = []
moved_map_dict = {}
for element,key in zip(geom,list(pos_all.keys())):
if float(element.x) >= shift:
moved_map_points.append(translate(element, xoff=-180-shift))
else:
moved_map_points.append(translate(element, xoff=180-shift))
moved_map_dict[key] = (moved_map_points[-1].x,moved_map_points[-1].y)
return moved_geom_gdf,moved_map_dict
In this context pos_all are networkx node positions made of [(lat,long)]
shifted_world,moved_map_points = shift_geom(300, world,pos_all,plotQ= False)

How to generate heat map on the Whole Slide Images (.svs format) using some probability values?

I am trying to generate heat map, or probability map, for Whole Slide Images (WSIs) using probability values. I have coordinate points (which determine areas on the WSIs) and corresponding probability values.
Basic Introduction on WSI: WSIs are large is size (almost 100000 x 100000 pixels). Hence, can't open these images using normal image viewer. The WSIs are processed using OpenSlide software.
I have seen previous posts in Stack Overflow on related to heat map, but as WSIs are processed in a different way, I am unable to figure out how to apply these solutions. Some examples that I followed: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, etc.
To generate heat map on WSIs, follow below instructions:
First of all Extract image patches and save the coordinates. Use below code for patch extraction. The code require some changes as per the requirements. The code has been copied from: patch extraction code link
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import logging
try:
import Image
except:
from PIL import Image
import math
import numpy as np
import openslide
import os
from time import strftime,gmtime
parser = argparse.ArgumentParser(description='Extract a series of patches from a whole slide image')
parser.add_argument("-i", "--image", dest='wsi', nargs='+', required=True, help="path to a whole slide image")
parser.add_argument("-p", "--patch_size", dest='patch_size', default=299, type=int, help="pixel width and height for patches")
parser.add_argument("-b", "--grey_limit", dest='grey_limit', default=0.8, type=float, help="greyscale value to determine if there is sufficient tissue present [default: `0.8`]")
parser.add_argument("-o", "--output", dest='output_name', default="output", help="Name of the output file directory [default: `output/`]")
parser.add_argument("-v", "--verbose",
dest="logLevel",
choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
default="INFO",
help="Set the logging level")
args = parser.parse_args()
if args.logLevel:
logging.basicConfig(level=getattr(logging, args.logLevel))
wsi=' '.join(args.wsi)
""" Set global variables """
mean_grey_values = args.grey_limit * 255
number_of_useful_regions = 0
wsi=os.path.abspath(wsi)
outname=os.path.abspath(args.output_name)
basename = os.path.basename(wsi)
level = 0
def main():
img,num_x_patches,num_y_patches = open_slide()
logging.debug('img: {}, num_x_patches = {}, num_y_patches: {}'.format(img,num_x_patches,num_y_patches))
for x in range(num_x_patches):
for y in range(num_y_patches):
img_data = img.read_region((x*args.patch_size,y*args.patch_size),level, (args.patch_size, args.patch_size))
print_pics(x*args.patch_size,y*args.patch_size,img_data,img)
pc_uninformative = number_of_useful_regions/(num_x_patches*num_y_patches)*100
pc_uninformative = round(pc_uninformative,2)
logging.info('Completed patch extraction of {} images.'.format(number_of_useful_regions))
logging.info('{}% of the image is uninformative\n'.format(pc_uninformative))
def print_pics(x_top_left,y_top_left,img_data,img):
if x_top_left % 100 == 0 and y_top_left % 100 == 0 and x_top_left != 0:
pc_complete = round(x_top_left /img.level_dimensions[0][0],2) * 100
logging.info('{:.2f}% Complete at {}'.format(pc_complete,strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())))
exit()
img_data_np = np.array(img_data)
""" Convert to grayscale"""
grey_img = rgb2gray(img_data_np)
if np.mean(grey_img) < mean_grey_values:
logging.debug('Image grayscale = {} compared to threshold {}'.format(np.mean(grey_img),mean_grey_values))
global number_of_useful_regions
number_of_useful_regions += 1
wsi_base = os.path.basename(wsi)
wsi_base = wsi_base.split('.')[0]
img_name = wsi_base + "_" + str(x_top_left) + "_" + str(y_top_left) + "_" + str(args.patch_size)
#write_img_rotations(img_data_np,img_name)
logging.debug('Saving {} {} {}'.format(x_top_left,y_top_left,np.mean(grey_img)))
save_image(img_data_np,1,img_name)
def gen_x_and_y(xlist,ylist,img):
for x in xlist:
for y in ylist:
img_data = img.read_region((x*args.patch_size,y*args.patch_size),level, (args.patch_size, args.patch_size))
yield (x, y,img_data)
def open_slide():
"""
The first level is always the main image
Get width and height tuple for the first level
"""
logging.debug('img: {}'.format(wsi))
img = openslide.OpenSlide(wsi)
img_dim = img.level_dimensions[0]
"""
Determine what the patch size should be, and how many iterations it will take to get through the WSI
"""
num_x_patches = int(math.floor(img_dim[0] / args.patch_size))
num_y_patches = int(math.floor(img_dim[1] / args.patch_size))
remainder_x = img_dim[0] % num_x_patches
remainder_y = img_dim[1] % num_y_patches
logging.debug('The WSI shape is {}'.format(img_dim))
logging.debug('There are {} x-patches and {} y-patches to iterate through'.format(num_x_patches,num_y_patches))
return img,num_x_patches,num_y_patches
def validate_dir_exists():
if os.path.isdir(outname) == False:
os.mkdir(outname)
logging.debug('Validated {} directory exists'.format(outname))
if os.path.exists(wsi):
logging.debug('Found the file {}'.format(wsi))
else:
logging.debug('Could not find the file {}'.format(wsi))
exit()
def rgb2gray(rgb):
"""Converts an RGB image into grayscale """
r, g, b = rgb[:,:,0], rgb[:,:,1], rgb[:,:,2]
gray = 0.2989 * r + 0.5870 * g + 0.1140 * b
return gray
def save_image(img,j,img_name):
tmp = os.path.join(outname,img_name+"_"+str(j)+".png")
try:
im = Image.fromarray(img)
im.save(tmp)
except:
print('Could not print {}'.format(tmp))
exit()
if __name__ == '__main__':
validate_dir_exists()
main()
Secondly, generate the probability values of each patches.
Finally, replace all the pixel values within a coordinates with the corresponding probability values and display the results using color maps.
This is the basic idea of generating heat map on WSIs. You can modify the code and concept to get a heat map as per your wish.
We have developed a python package for processing whole-slide-images:
https://github.com/amirakbarnejad/PyDmed
Here is a tutorial for getting heatmaps for whole-slide-images:
https://amirakbarnejad.github.io/Tutorial/tutorial_section5.html.
Also here is a sample notebook that gets heatmaps for WSIs using PyDmed:
Link to the sample notebook.
The benefit of PyDmed is that it is multi-processed. The dataloader sends a stream of patches to GPU(s), and the StreamWriter writes to disk in a separate process. Therefore, it is highly efficient. The running time of course depends on the machine, the size of WSIs, etc. On a good machine with a good GPU, PyDmed can generate heatmaps for ~120 WSIs in one day.

How to use a slider callback to filter a ColumnDataSource in Bokeh using Python 3?

I'm trying to use a slider with a callback in Bokeh using Python 3 to filter the rows of my ColumnDataSource objects (which originate from a DataFrame). More specifically, if a slider with options of 0 to 10000000 (in multiples of 1 million) returns a value N of say 2000000, then I want my plot to only show the data for, in this case, US counties where the population is >= 2000000. Below is my code. Everything works as I want it to except for the slider callback.
from bokeh.io import curdoc
from bokeh.layouts import layout
from bokeh.models import HoverTool, ColumnDataSource, Select, Slider
from bokeh.plotting import figure
TOOLS='pan,wheel_zoom,box_zoom,reset,tap,save,box_select,lasso_select'
source1 = ColumnDataSource(df[df.winner == 'Democratic'])
source2 = ColumnDataSource(df[df.winner == 'Republican'])
hover = HoverTool(
tooltips = [
('County Name', '#county'),
('Population', '#population'),
('Land Area', '#land_area'),
('Pop. Density', '#density'),
('Winning Party', '#winner'),
('Winning Vote %', '#winning_vote_pct'),
]
)
# Plot
plot = figure(plot_width=800, plot_height=450, tools=[hover, TOOLS],
title='2016 US Presidential Vote % vs. Population Density (by County)',
x_axis_label='Vote %', y_axis_label='Population Density (K / sq. mi.)')
y = 'density'
size = 'bokeh_size'
alpha = 0.5
c1 = plot.circle(x='pct_d', y=y, size=size, alpha=alpha, color='blue',
legend='Democratic-Won County', source=source1)
c2 = plot.circle(x='pct_r', y=y, size=size, alpha=alpha, color='red',
legend='Republican-Won County', source=source2)
plot.legend.location = 'top_left'
# Select widget
party_options = ['Show both parties', 'Democratic-won only', 'Republican-won only']
menu = Select(options=party_options, value='Show both parties')
# Slider widget
N = 2000000
slider = Slider(start=0, end=10000000, step=1000000, value=N, title='Population Cutoff')
# Select callback
def select_callback(attr, old, new):
if menu.value == 'Democratic-won only': c1.visible=True; c2.visible=False
elif menu.value == 'Republican-won only': c1.visible=False; c2.visible=True
elif menu.value == 'Show both parties': c1.visible=True; c2.visible=True
menu.on_change('value', select_callback)
# Slider callback
def slider_callback(attr, old, new):
N = slider.value
# NEED HELP HERE...
source1 = ColumnDataSource(df.loc[(df.winner == 'Democratic') & (df.population >= N)])
source2 = ColumnDataSource(df.loc[(df.winner == 'Republican') & (df.population >= N)])
slider.on_change('value', slider_callback)
# Arrange plots and widgets in layouts
layout = layout([menu, slider],
[plot])
curdoc().add_root(layout)
Here is a solution using CustomJSFilter and CDSView as suggest in the other answer by Alex. It does not directly use the data as supplied in the question, but is rather a general hint how this can be implemented:
from bokeh.layouts import column
from bokeh.models import CustomJS, ColumnDataSource, Slider, CustomJSFilter, CDSView
from bokeh.plotting import Figure, show
import numpy as np
# Create some data to display
x = np.arange(200)
y = np.random.random(size=200)
source = ColumnDataSource(data=dict(x=x, y=y))
plot = Figure(plot_width=400, plot_height=400)
# Create the slider that modifies the filtered indices
# I am just creating one that shows 0 to 100% of the existing data rows
slider = Slider(start=0., end=1., value=1., step=.01, title="Percentage")
# This callback is crucial, otherwise the filter will not be triggered when the slider changes
callback = CustomJS(args=dict(source=source), code="""
source.change.emit();
""")
slider.js_on_change('value', callback)
# Define the custom filter to return the indices from 0 to the desired percentage of total data rows. You could also compare against values in source.data
js_filter = CustomJSFilter(args=dict(slider=slider, source=source), code=f"""
desiredElementCount = slider.value * 200;
return [...Array(desiredElementCount).keys()];
""")
# Use the filter in a view
view = CDSView(source=source, filters=[js_filter])
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6, view=view)
layout = column(slider, plot)
show(layout)
I hope this helps anyone who stumbles upon this in the future! Tested in bokeh 1.0.2
A quick solution with minimal change to your code would be:
def slider_callback(attr, old, new):
N = new # this works also with slider.value but new is more explicit
new1 = ColumnDataSource(df.loc[(df.winner == 'Democratic') & (df.population >= N)])
new2 = ColumnDataSource(df.loc[(df.winner == 'Republican') & (df.population >= N)])
source1.data = new1.data
source2.data = new2.data
When updating data sources, you should replace the data, not the whole object. Here I still create new ColumnDataSource as shortcut. A more direct way (but more verbose too) would be to create the dictionary from the filtered df's columns:
new1 = {
'winner': filtered_df.winner.values,
'pct_d': filtered_df.pct_d.values,
...
}
new2 = {...}
source1.data = new1
source2.data = new2
Note that there's another solution which would make the callback local (not server based) by using a CDSView with a CustomJSFilter. You can also write the other callback with a CDSView as well make the plot completely server-independent.

Create VTKpolydata using x,y,z coordinates

I am beginner in VTK. I have a dataset as x,y,z points and the value of each point. I want to create a vtkpolydata set using the points and create a contour using values of each point.
Please tell me how to create a vtkPolyData set using a given set of points in c++.
Thanks.
This example shows how to do both parts of your question:
http://www.vtk.org/Wiki/VTK/Examples/Cxx/GeometricObjects/PolyLine
Here is a script adapted from this blog to plot 3D xyz data:
'''
Modified Python 3 VTK script to Display 3D xyz data
Credits to : https://sukhbinder.wordpress.com/2013/09/17/python-vtk-script-to-display-3d-xyz-data/
Script name: xyzviewer.py
'''
import vtk
from numpy import random,genfromtxt,size
class VtkPointCloud:
def __init__(self, zMin=-10.0, zMax=10.0, maxNumPoints=1e6):
self.maxNumPoints = maxNumPoints
self.vtkPolyData = vtk.vtkPolyData()
self.clearPoints()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(self.vtkPolyData)
mapper.SetColorModeToDefault()
mapper.SetScalarRange(zMin, zMax)
mapper.SetScalarVisibility(1)
self.vtkActor = vtk.vtkActor()
self.vtkActor.SetMapper(mapper)
def addPoint(self, point):
if (self.vtkPoints.GetNumberOfPoints() < self.maxNumPoints):
pointId = self.vtkPoints.InsertNextPoint(point[:])
self.vtkDepth.InsertNextValue(point[2])
self.vtkCells.InsertNextCell(1)
self.vtkCells.InsertCellPoint(pointId)
else:
r = random.randint(0, self.maxNumPoints)
self.vtkPoints.SetPoint(r, point[:])
self.vtkCells.Modified()
self.vtkPoints.Modified()
self.vtkDepth.Modified()
def clearPoints(self):
self.vtkPoints = vtk.vtkPoints()
self.vtkCells = vtk.vtkCellArray()
self.vtkDepth = vtk.vtkDoubleArray()
self.vtkDepth.SetName('DepthArray')
self.vtkPolyData.SetPoints(self.vtkPoints)
self.vtkPolyData.SetVerts(self.vtkCells)
self.vtkPolyData.GetPointData().SetScalars(self.vtkDepth)
self.vtkPolyData.GetPointData().SetActiveScalars('DepthArray')
def load_data(filename,pointCloud):
data = genfromtxt(filename,dtype=float,usecols=[0,1,2])
for k in range(size(data,0)):
point = data[k] #20*(random.rand(3)-0.5)
pointCloud.addPoint(point)
return pointCloud
if __name__ == '__main__':
import sys
if (len(sys.argv) < 2):
print ('Usage: xyzviewer.py itemfile')
sys.exit()
pointCloud = VtkPointCloud()
pointCloud=load_data(sys.argv[1],pointCloud)
# Renderer
renderer = vtk.vtkRenderer()
renderer.AddActor(pointCloud.vtkActor)
#renderer.SetBackground(.2, .3, .4)
renderer.SetBackground(0.0, 0.0, 0.0)
renderer.ResetCamera()
# Render Window
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
# Interactor
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
# Begin Interaction
renderWindow.Render()
renderWindow.SetWindowName("XYZ Data Viewer"+sys.argv[1])
renderWindowInteractor.Start()
You could run it as follows:
python xyzviewer.py filename
filename is the file that contains the xyz data.

Resources