Specify rendering window size of OpenAi Gym - openai-gym

Calling env.render() always renders a windows filling the whole screen.
env = gym.make('FetchPickAndPlace-v1')
env.reset()
for i in range(1000):
env.render()

You can give this a try:
import matplotlib
is_ipython = 'inline' in matplotlib.get_backend()
if is_ipython: from IPython import display
env = gym.make('FetchPickAndPlace-v1')
a = env.render(mode='rgb_array')
plt.figure()
plt.imshow(a)
plt.show()
if is_ipython: display.clear_output(wait=True)

Related

Databricks View Image

I am running this in Databricks but the decision tree image will not display.
%pip install pydot
%pip install pydotplus
# Load libraries
from sklearn.tree import DecisionTreeClassifier
from sklearn import datasets
from IPython.display import Image
from sklearn import tree
import pydotplus
# Load data
iris = datasets.load_iris()
X = iris.data
y = iris.target
# Create DOT data
dot_data = tree.export_graphviz(clf, out_file=None,
feature_names=iris.feature_names,
class_names=iris.target_names)
# Draw graph
graph = pydotplus.graph_from_dot_data(dot_data)
# Show graph
Image(graph.create_png())
I only get this message (no visual):
Out[4]: <IPython.core.display.Image object>
I'm stumped. Thoughts?
Databricks has the worst documentation, and their examples do not work at this time, so I had to come up with my own solution using PIL and Matplotlib.
Here is how I display images in Databricks in Python:
from PIL import Image
import matplotlib.pyplot as plt
def display_image(path, dpi=100):
"""
Description:
Displayes an image
Inputs:
path (str): File path
dpi (int): Your monitor's pixel density
"""
img = Image.open(path)
width, height = img.size
plt.figure(figsize = (width/dpi,height/dpi))
plt.imshow(img, interpolation='nearest', aspect='auto')

module '<file_name>' has no attribute '__path__'

I'm using commands on terminal to run this script (plot_test.py is the name of the file):
#python3
import pybullet as p
import pybullet_data as p_data
import time
import matplotlib.pyplot as plt
import numpy as np #to reshape for matplotlib
import os
import matplotlib.animation as animation
# os.environ['MESA_GL_VERSION_OVERRIDE'] = '3.3'
# os.environ['MESA_GLSL_VERSION_OVERRIDE'] = '330'
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
# plt.ion()
# GUI = 0
def animate(i):
graph_data = open('solved_states.bin','r').read()
lines = graph_data.split('\n')
time_stamp = [] #time
torque = [] #torque
for line in lines:
if len(line) > 1:
x, y = line.split(',')
time_stamp.append(float(y))
torque.append(float(x))
ax1.clear()
ax1.plot(time_stamp, torque,color='r',label='Torque')
ax1.set_title('Torque Vs Time')
ax1.set_xlabel('Time')
ax1.set_ylabel('Torque')
ax1.legend(loc="upper right")
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
Altough it plots the graph and, I keep getting this error:
pybullet build time: Oct 8 2020 00:10:04
/usr/bin/python3: Error while finding module specification for 'plot_test.py' (AttributeError: module 'plot_test' has no attribute '__path__')
I'm new to python and I don't know how this works
I've seen similar questions like this before, but here, the file that I am working on is showing up the error.
Are you running the file with command
python -m plot_test.py
?
The flag -m runs the file as a module and then you need to omit the .py
If my assumption is true then you should be good with either:
python -m plot_test
or simply
python plot_test.py

when running gekko for 1st time, got this error "cannot import name 'dump_csp_header' from werkzeug.http'

I'm using Spyder to run Python 3.7 where I installed gekko. However, I tried running a simple gekko code from Wikipedia and it gives me the following error:
ImportError: cannot import name 'dump_csp_header' from 'werkzeug.http' (C:\Users\zulfan.adiputra\AppData\Local\Continuum\anaconda3\envs\PythonNew\lib\site-packages\werkzeug\http.py)
When I check in the Anaconda prompt, the werkzeug installed is 1.0.0. What to do in this regard?
Thanks
You can resolve the error with:
Set GUI=False in m.solve()
Run the Python program from the command line with python myProgram.py. There are sometimes problems with the Flask server if you try to use the GUI by running from an IDE like Spyder or IDLE.
Instead of using the GUI option, it is relatively easy to plot the results with matplotlib. Here is an example script:
from gekko import GEKKO
import numpy as np
import matplotlib.pyplot as plt
m = GEKKO() # initialize gekko
nt = 101
m.time = np.linspace(0, 2, nt)
# Variables
x1 = m.Var(value=1)
x2 = m.Var(value=0)
u = m.Var(value=0, lb=-1, ub=1)
p = np.zeros(nt) # mark final time point
p[-1] = 1.0
final = m.Param(value=p)
# Equations
m.Equation(x1.dt() == u)
m.Equation(x2.dt() == 0.5 * x1 ** 2)
m.Obj(x2 * final) # Objective function
m.options.IMODE = 6 # optimal control mode
m.solve() # solve
plt.figure(1) # plot results
plt.plot(m.time, x1.value, "k-", label=r"$x_1$")
plt.plot(m.time, x2.value, "b-", label=r"$x_2$")
plt.plot(m.time, u.value, "r--", label=r"$u$")
plt.legend(loc="best")
plt.xlabel("Time")
plt.ylabel("Value")
plt.show()

How to show episode in rendered openAI gym environment

If we look at the previews of the environments, they show the episodes increasing in the animation on the bottom right corner. https://gym.openai.com/envs/CartPole-v1/ .Is there a command to explicitly show that?
I don't think there is a command to do that directly available in OpenAI, but I've written some code that you can probably adapt to your purposes. This is the end result:
These is how I achieve the end result:
For each step, you obtain the frame with env.render(mode='rgb_array')
You convert the frame (which is a numpy array) into a PIL image
You write the episode name on top of the PIL image using utilities from PIL.ImageDraw (see the function _label_with_episode_number in the code snippet).
You save the labeled image into a list of frames.
You render the list of frames as a GIF using matplotlib utilities.
Here is the code I wrote for obtaining a GIF of the behavior of a random agent with the Episode number displayed in the top left corner of each frame:
import os
import imageio
import numpy as np
from PIL import Image
import PIL.ImageDraw as ImageDraw
import matplotlib.pyplot as plt
def _label_with_episode_number(frame, episode_num):
im = Image.fromarray(frame)
drawer = ImageDraw.Draw(im)
if np.mean(im) < 128:
text_color = (255,255,255)
else:
text_color = (0,0,0)
drawer.text((im.size[0]/20,im.size[1]/18), f'Episode: {episode_num+1}', fill=text_color)
return im
def save_random_agent_gif(env):
frames = []
for i in range(5):
state = env.reset()
for t in range(500):
action = env.action_space.sample()
frame = env.render(mode='rgb_array')
frames.append(_label_with_episode_number(frame, episode_num=i))
state, _, done, _ = env.step(action)
if done:
break
env.close()
imageio.mimwrite(os.path.join('./videos/', 'random_agent.gif'), frames, fps=60)
env = gym.make('CartPole-v1')
save_random_agent_gif(env)
You can find a working version of the code here: https://github.com/RishabhMalviya/dqn_experiments/blob/master/train_and_visualize.py#L10

multiprocessing show matplotlib plot

I'm trying to open up multiple plots but I ran into a few problems. When I tried to create plots using threading, python would first open a number of windows, then close all but the first.
In another question it was recommended that I use multiprocessing which I have tried. The code runs without error, it just doesn't show any plot.
I'm trying to get something very simple to work before moving on to my main project.
# Import the necessary packages and modules
import matplotlib.pyplot as plt
import numpy as np
#from threading import Thread
import multiprocessing
def plot(datax, datay, name):
# Prepare the data
x = datax
y = datay**2
# Plot the data
plt.scatter(x, y, label=name)
# Add a legend
plt.legend()
# Show the plot
plt.show()
#plot(3,3,)
'''
for i in range(10):
t = Thread(target=plot, args=(i,i+1,i,))
t.start()
'''
for i in range(2):
p = multiprocessing.Process(target=plot, args=(i, i, i))
p.start()
update:
for some reason, multiprocessing stopped working again. I tried creating a function multiP() only to open the processes but it didn't work when I added the input('value: '). scine I can't figure out how to send data to a specific thread I'm going to save data like this: dat = [[x,y0,y1,...yn],[x,y0,y1,...yn],...] and each plot process with check the if something was added to dat.
import matplotlib.pyplot as plt
import numpy as np
import multiprocessing
#multiprocessing.freeze_support() # <- may be required on windows
def plot(datax, datay, name):
x = datax
y = datay**2
plt.scatter(x, y, label=name)
plt.legend()
plt.show()
def multiP():
if __name__ == "__main__":
for i in range(2):
p = multiprocessing.Process(target=plot, args=(i, i, i))
p.start()
if True:
#input('Vlaue: ') # while commented plots are shown
multiP()
The following code produces two figures as desired.
import matplotlib.pyplot as plt
import numpy as np
import multiprocessing
#multiprocessing.freeze_support() # <- may be required on windows
def plot(datax, datay, name):
x = datax
y = datay**2
plt.scatter(x, y, label=name)
plt.legend()
plt.show()
def multiP():
for i in range(2):
p = multiprocessing.Process(target=plot, args=(i, i, i))
p.start()
if __name__ == "__main__":
input('Value: ')
multiP()
Taking ImportanceOfBeingErnest answer, I leave below an implementation which only shows one window and waits for the window to close, which can be very handy. Every time it is called, it displays a new window with the corresponding image (a new pocess will be started for each image). I used a lot to view images when stopped at some breakpoint during debug.
# Library packages needed
import numpy as np
import datetime
import sys
import queue
import multiprocessing
# Plot related packages
import matplotlib.pyplot as plt
def showImage(img: np.ndarray, title: str = str(datetime.datetime.today())):
"""Show an image in a new process without blocking. Usefull for debugging.
Args:
img (np.ndarray): Image to be shown
title (str, optional): Title to be shown. Defaults to
str(datetime.datetime.today()).
"""
def plot(q, title):
fig = plt.figure()
fig.suptitle(title)
try:
q.get(True, 2.0) # Wait a couple of seconds
except queue.Empty:
print('Not image received to plot...quitting')
sys.exit()
plt.imshow(img)
plt.show()
sys.exit()
# Create a queue to share data between process
q = multiprocessing.Queue()
# Create and start the process
proc = multiprocessing.Process(None, plot, args=(q, title))
proc.start()
q.put(img)
To run it, just save this to a show_image.py file and call
from show_image.py import showImage
show_image(img, title)

Resources