I'm trying to visualize a pair of two lists, represented by lines_x and lines_y which are meant to be plugged into the coordinates argument of either the plot function in Axes or in Lines2D.
Right now, I'm getting this result, which has extra lines compared to the result I am trying to get.
What I'm currently getting:
Previously, I tried using a loop to plot the lines one by one, and that worked for a while. However, after a few runs, it no longer worked.
Could someone please suggest a way for me to achieve the following result on my window?
The plot I want to achieve:
from pylab import *
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import matplotlib.pylab as plt
import matplotlib.pyplot as pltplot
import matplotlib.lines
from matplotlib.collections import LineCollection
matplotlib.use ("gTkAgg")
import numpy as np
import tkinter as tk
from tkinter import Tk
from tkinter import *
class Window (Frame):
lines_x = [-2, -2, -1, -1, 0, 0, 1, 1, 2, 2, 0, 1, 1, 2, -2, 2, -2, -1, -1, 0]
lines_y = [0, 1, 1, 2, -2, 2, -2, -1, -1, 0, -2, -2, -1, -1, 0, 0, 1, 1, 2, 2]
def __init__(self, parent = None):
Frame.__init__(self,parent)
parent.title("Shape Grammar Interpreter")
self.top=Frame()
self.top.grid()
self.top.update_idletasks
self.menu()
self.makeWidgets()
def makeWidgets(self):
self.f = Figure(figsize = (6,6), dpi = 100)
self.a = self.f.add_subplot(111)
#self.a.plot(self.lines_x, self.lines_y, linewidth = 4.0, picker=5)
line = Line2D(self.lines_x, self.lines_y)
self.a.add_line(line)
for i in range(len(self.lines_x)):
self.a.plot(self.lines_x[i:i+1], self.lines_y[i:i+1], linewidth = 4.0)
#self.a.plot(lines_x, lines_y, linewidth = 4.0, color = "blue")
self.a.margins(y=0.5)
self.a.margins(x=0.5)
#self.a.axes.get_xaxis().set_visible(False)
#self.a.axes.get_yaxis().set_visible(False)
# a tk.DrawingArea
self.canvas = FigureCanvasTkAgg(self.f, master=self.top)
#to show window
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
def menu(self):
menubar = Menu (root)
#to close window
menubar.add_command(label="Exit", command=self.quit_window)
root.config(menu=menubar)
def quit_window(self):
root.quit()
root.destroy()
if __name__ == "__main__":
root = Tk()
my_gui = Window(root)
root.mainloop()
It makes sense if you annotate the order in which the line segments are drawn. For example (only plotting the first 10 points, otherwise it becomes a bit of a mess):
import matplotlib.pylab as pl
lines_x = [-2, -2, -1, -1, 0, 0, 1, 1, 2, 2, 0, 1, 1, 2, -2, 2, -2, -1, -1, 0]
lines_y = [0, 1, 1, 2, -2, 2, -2, -1, -1, 0, -2, -2, -1, -1, 0, 0, 1, 1, 2, 2]
n = 10
pl.figure()
pl.plot(lines_x[:n], lines_y[:n])
# Number the coordinates to indicate their order:
for i in range(len(lines_x[:n])):
pl.text(lines_x[i], lines_y[i], '{}'.format(i))
pl.xlim(-3,3)
pl.ylim(-3,3)
Results in:
If I increase n, it becomes a larger mess since a number of x,y coordinates are duplicates. So:
Make sure that there are no duplicate coordinates
Make sure that the coordinates are ordered correctly.
Try these sequences instead:
lines_x = [-2, -2, -1, -1, 0, 0, 1, 1, 2, 2, -2]
lines_y = [ 0, 1, 1, 2, 2, -2, -2, -1, -1, 0, 0]
Worked for me:
Also I should note that I used simply
In [1]: import matplotlib.pyplot as plt
In [2]: plt.plot(lines_x,lines_y)
So I believe Lines has nothing to do with it.
Related
I tried an example using dtaidistance and dtw, but it did not plot the result.
from dtaidistance import dtw
from dtaidistance import dtw_visualisation as dtwvis
import numpy as np
s1 = np.array([0., 0, 1, 2, 1, 0, 1, 0, 0, 2, 1, 0, 0])
s2 = np.array([0., 1, 2, 3, 1, 0, 0, 0, 2, 1, 0, 0, 0])
path = dtw.warping_path(s1, s2)
dtwvis.plot_warping(s1, s2, path, filename="warp.png")
It should have looked like this:
Unfortunately, it did not show up.
I tried to add "plt.show()" at the end of the code (previously importing pyplot of course). But, in this case, it has not helped.
What is the rason it does not plot the graph, like in the example above?
The picture in the example is not meant to be plotted within python but saved as .png to hard drive where the python code is stored.
import numpy as np
import sympy as sp
Vec = np.matrix([[1,1,1,5],[1,2,0,3],[2,1,3,12]])
Vec_rref = sp.Matrix(Vec).rref()
print(Vec_rref) ##<-- this code prints the RREF, but i am looking for the code for REF (See below)
I have found plenty of codes which solves the RREF but not codes for REF, if **it makes sense. The code i have developed gives the following:
(Matrix([
[1, 0, 2, 7],
[0, 1, -1, -2],
[0, 0, 0, 0]]), (0, 1))
I am looking for a code which should solve the following:
1XXX
REF = 01XX
001X
and not
100X
RREF = 010X
001X
New here so bare with me guys. Thanks in advance :-)
You are using the function of sympy: rref wich is associated to "reduced row-echelon form". You might want to use .echelon_form() instead
import numpy as np
import sympy as sp
from scipy import linalg
Vec = np.matrix([[1,1,1,5],
[1,2,0,3],
[2,1,3,12]])
Vec_rref =sp.Matrix(Vec).echelon_form()
print(Vec_rref)
wich outputs:
Matrix([[1, 1, 1, 5], [0, 1, -1, -2], [0, 0, 0, 0]])
I am learning recursion and came through this code (not mine: https://github.com/kying18/sudoku) and cannot figure out why the variable example_board changes value. It is never addressed again and no other variable is linked to it? I tested it and it does!
Here is the condensed version of the relevant code:
def find_next_empty(puzzle):
#returns a row, col for a empty square
def is_valid(puzzle, guess, row, col):
#checks if guess is True or False
def solve_sudoku(puzzle):
row, col = find_next_empty(puzzle)
if row is None: # this is true if our find_next_empty function returns None, None
return True
for guess in range(1, 10): # range(1, 10) is 1, 2, 3, ... 9
if is_valid(puzzle, guess, row, col):
puzzle[row][col] = guess
if solve_sudoku(puzzle):
return True
puzzle[row][col] = -1
return False
if __name__ == '__main__':
example_board = [
[3, 9, -1, -1, 5, -1, -1, -1, -1],
[-1, -1, -1, 2, -1, -1, -1, -1, 5],
[-1, -1, -1, 7, 1, 9, -1, 8, -1],
[-1, 5, -1, -1, 6, 8, -1, -1, -1],
[2, -1, 6, -1, -1, 3, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1, 4],
[5, -1, -1, -1, -1, -1, -1, -1, -1],
[6, 7, -1, 1, -1, 5, -1, 4, -1],
[1, -1, 9, -1, -1, -1, 2, -1, -1]
]
print(solve_sudoku(example_board))
print(example_board)
'''
Before you dive into the implementatino details you must understand what passing parameter by reference or by value means, because python passes by reference:
Pass means to provide an argument to a function.
By reference means that the argument you’re passing to the function is a reference to a variable that already exists in memory rather than an independent copy of that variable.
Since you’re giving the function a reference to an existing variable, all operations performed on this reference will directly affect the variable to which it refers. Let’s look at some examples of how this works in practice.
Reference this article
When printing in the line: "print(solve_sudoku(example_board))" example_board is passed into solve_sodoku. The solve_sodoku function then changes it values in this line: "puzzle[row][col] = guess" as puzzle is referencing the example_board variable and one of its value is being changed to guess.
Hope this helped!
I have made a morse code translator and I want it to be able to record a flashing light and make it into morse code. I think I will need OpenCV or a light sensor, but I don't know how to use either of them. I haven't got any code for it yet, as I couldn't find any solutions anywhere else.
The following is just a concept of what you could try. Yes, you could also train a neural network for this but if your setup is simple enough, some engineering will do.
We first create a "toy-video" to work with:
import numpy as np
import matplotlib.pyplot as plt
# Create a toy "video"
image = np.asarray([
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 1, 2, 2, 1],
[0, 0, 2, 4, 4, 2],
[0, 0, 2, 4, 4, 2],
[0, 0, 1, 2, 2, 1],
])
signal = np.asarray([0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0])
x = list(range(len(signal)))
signal = np.interp(np.linspace(0, len(signal), 100), x, signal)[..., None]
frames = np.einsum('tk,xy->txyk', signal, image)[..., 0]
Plot a few frames:
fig, axes = plt.subplots(1, 12, sharex='all', sharey='all')
for i, ax in enumerate(axes):
ax.matshow(frames[i], vmin=0, vmax=1)
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
ax.set_title(i)
plt.show()
Now that you have this kind of toy video, it's pretty straight forward to convert it back to some sort of binary signal. You'd simply compute the average brightness of each frame:
reconstructed = frames.mean(1).mean(1)
reconstructed_bin = reconstructed > 0.5
plt.plot(reconstructed, label='original')
plt.plot(reconstructed_bin, label='binary')
plt.title('Reconstructed Signal')
plt.legend()
plt.show()
From here we only have to determine the length of each flash.
# This is ugly, I know. Just for understanding though:
# 1. Splits the binary signal on zero-values
# 2. Filters out the garbage (accept only lists where len(e) > 1)
# 3. Gets the length of the remaining list == the duration of each flash
tmp = np.split(reconstructed_bin, np.where(reconstructed_bin == 0)[0][1:])
flashes = list(map(len, filter(lambda e: len(e) > 1, tmp)))
We can now take a look at how long flashes take:
print(flashes)
gives us
[5, 5, 5, 10, 9, 9, 5, 5, 5]
So.. "short" flashes seem to take 5 frames, "long" around 10. With this we can classify each flash as either being "long" or "short" by defining a sensible threshold of 7 like so:
# Classify each flash-duration
flashes_classified = list(map(lambda f: 'long' if f > 7 else 'short', flashes))
And let's repeat for pauses
# Repeat for pauses
tmp = np.split(reconstructed_bin, np.where(reconstructed_bin != False)[0][1:])
pauses = list(map(len, filter(lambda e: len(e) > 1, tmp)))
pauses_classified = np.asarray(list(map(lambda f: 'w' if f > 6 else 'c', pauses)))
pauses_indices, = np.where(np.asarray(pauses_classified) == 'w')
Now we can visualize the results.
fig = plt.figure()
ax = fig.gca()
ax.bar(range(len(flashes)), flashes, label='Flash duration')
ax.set_xticks(list(range(len(flashes_classified))))
ax.set_xticklabels(flashes_classified)
[ax.axvline(idx-0.5, ls='--', c='r', label='Pause' if i == 0 else None) for i, idx in enumerate(pauses_indices)]
plt.legend()
plt.show()
It somewhat depends on your environment. You might try inexpensively with a Raspberry Pi Zero (£9) or even a Pico (£4) or Arduino and an attached LDR - Light Dependent Resistor for £1 rather than a £100 USB camera.
Your program would then come down to repeatedly measuring the resistance (which depends on the light intensity) and making it into long and short pulses.
This has the benefit of being cheap and not requiring you to learn OpenCV, but Stefan's idea is far more fun and has my vote!
Trying to write a simple lowpass filter in python to run against lena. Then I'd like to run an inverse filter to run against the lowpass and try to get the original back (well, as close to original). I'm new to programming in python and not quite sure where to start.
I tried rearranging a highpass filter code but it doesn't look right.
import matplotlib.pyplot as plt
import numpy as np
import scipy.misc
from scipy import ndimage
import Image
#lowpass
def plot(data, title):
plot.i += 1
plt.subplot(2,2,plot.i)
plt.imshow(data)
plt.gray()
plt.title(title)
plot.i = 0
# Load the data...
img = scipy.misc.lena()
data = np.array(img, dtype=float)
plot(data, 'Original')
#narrow lowpass filter
kernel = np.array([[1, 1, 1],
[1, -8, 1],
[1, 1, 1]])
lp_3 = ndimage.convolve(data, kernel)
plot(lp_3, '3x3 Lowpass')
# A slightly "wider" lowpass filter
kernel = np.array([[1, 1, 1, 1, 1],
[1, -1, -2, -1, 1],
[1, -2, -4, -2, 1],
[1, -1, -2, -1, 1],
[1, 1, 1, 1, 1]])
lp_5 = ndimage.convolve(data, kernel)
plot(lp_5, '5x5 Lowpass')
plt.show()
You should definitely check your kernel first. It does not look like a lowpass (averaging) kernel at all. Try first something like
kernel = np.ones((n,n))
if you want to do a very simple lowpass filter n by n (i.e. blurring):