changing size of ticklines - python-3.x

I'm trying to change the size of the tick-lines (not the label) of a 3d plot. I've tried different methods. I can easily change the size of the tick-label and its color. But changing size of the tick-lines seems impossible. I'd appreciate any thoughts on this problem.
One of the things I've tried is the following line with trying different numbers and arguments:
plt.tick_params(axis='both', which='both', length=100, labelsize=7 ,width=1, pad=0.5, right='True', color='red', tickdir='in', tick1On = 'True')
but width, length, and tickdir don't change anything.
I've also tried:
for a in (ax.w_xaxis, ax.w_yaxis, ax.w_zaxis):
for n in a.get_ticklines():
# n.set_sketch_params(1)
n.set_alpha(0.5)
n.set_mfc('red')
n.set_mew(20)
n.set_mec('red')
# n.set_drawstyle('steps-pre')
n.set_c((1,0,0,1))
n.set_ms(100)
n.set_ls(' ')
n.set_lw(1.)
n.set_solid_joinstyle('round')
n.set_markersize(900)
n.set_marker('.')
I can change all the other parameters of the tick-lines but not their color or size.
grid didn't seem to help either, since I set its visibility to False.
I'm using python 3.5.0 and matplotlib 2.1.0

Related

How to plot hyperparameter tuning results?

I have the result of a grid search as follows.
"trial","learning_rate","batch_size","accuracy","f1","loss"
1,0.000007,70,0.789,0.862,0.467
2,0.000008,100,0.710,0.822,0.563
3,0.000008,90,0.823,0.874,0.524
4,0.000007,90,0.833,0.878,0.492
5,0.000009,110,0.715,0.825,0.509
6,0.000006,90,0.883,0.885,0.932
7,0.000009,80,0.850,0.895,0.408
8,0.000006,110,0.683,0.812,0.593
9,0.000005,90,0.769,0.848,0.468
10,0.000005,80,0.816,0.868,0.462
11,0.000003,100,0.852,0.901,0.448
12,0.000004,100,0.705,0.818,0.512
13,0.000003,110,0.708,0.818,0.567
14,0.000002,90,0.683,0.812,0.552
15,0.000008,100,0.791,0.857,0.438
16,0.000006,110,0.683,0.812,0.604
17,0.000007,70,0.693,0.816,0.592
18,0.000005,110,0.830,0.883,0.892
19,0.000004,90,0.693,0.816,0.591
20,0.000008,70,0.696,0.818,0.570
I want to create a plot more or less similar to this using matplotlib. I know this is plotted using weights and biases but I cannot use that.
Though I don't care for the inference part. I just want the plot. I've been trying to do this using twinx but have not been successful. This is what I have so far.
from csv import DictReader
import matplotlib.pyplot as plt
trials = list(DictReader(open("hparams_trials.csv")))
trials = {f"trial_{trial['trial']}": [int(trial["batch_size"]),
float(trial["f1"]),
float(trial["loss"]),
float(trial["accuracy"]),
float(trial["learning_rate"])] for trial in trials}
items = ["batch_size", "f1", "loss", "accuracy", "learning_rate"]
host_y_values_index = 0
parts_y_values_indexes = [1, 2, 3, 4]
fig, host = plt.subplots(figsize=(8, 5)) # (width, height) in inches
fig.dpi = 300. # Figure resolution
# Removing extra spines
host.spines.top.set_visible(False)
host.spines.bottom.set_visible(False)
host.spines.right.set_visible(False)
# Creating subplots which share the same x axis.
parts = {index: host.twinx() for index in parts_y_values_indexes}
# Setting the limits of the host plot
host.set_xlim(0, len(trials["trial_1"]))
host.set_ylim(min([i[host_y_values_index] for i in trials.values()]),
max([i[host_y_values_index] for i in trials.values()]))
# Removing the extra spines from the other plots and setting y limits
for part in parts_y_values_indexes:
parts[part].spines.top.set_visible(False)
parts[part].spines.bottom.set_visible(False)
parts[part].set_ylim(min([trial[part] for trial in trials.values()]),
max([trial[part] for trial in trials.values()]))
# Colors of the trials
colors = ["gold", "lightcoral", "maroon", "springgreen", "cyan", "steelblue", "darkmagenta", "fuchsia", "crimson",
"lime", "mediumblue", "cadetblue", "dodgerblue", "olivedrab", "sandybrown", "bisque", "orangered", "black",
"rosybrown", "chocolate"]
# The plots
plots = []
# Plotting the trials. This is where I'm having problems with.
for index, trial in enumerate(trials):
plots.append(host.plot(items, trials[trial], color=colors[index], label=trial)[0])
# Creating the legend
host.legend(handles=plots, fancybox=True, loc='right', facecolor="snow", bbox_to_anchor=(1.02, 0.495), framealpha=1)
# Defining the positions of the spines.
spines_positions = [-104.85 * i for i in parts_y_values_indexes]
# Repositioning the spines
for part in parts_y_values_indexes:
parts[part].spines['right'].set_position(('outward', spines_positions[-part]))
# Adjust spacings around fig
fig.tight_layout()
host.grid(True)
# This is better than the one above but it appears on top of the legend.
# plt.grid(True)
plt.draw()
plt.show()
I'm having several problems with that code. First, I cannot place each value of a single trial based on a different spine and then connect them to one another. What I mean is that each trial has a batch size, an f1, a loss, accuracy and a learning rate. Each of those need to be plotted based on their own spine while connected to each other in that order. However, I cannot plot them based their dedicated spines and then connect them to one another to have a line plot per trial. Accordingly, for now I have placed everything in the host plot but I know that is wrong and have no idea what the correct approach is. Second problem, the ticks of the learning rate change. It gets shown as a range of 2 to 9 and then a 1e-6 appears at the top. I want to keep the original value. Third problem is probably part of the second one. The 1e-6 appears at the top right above the legend rather than above the spine for some reason. I'm struggling with resolving all three of these problems and would appreciate any help anyone can provide. If what I am doing is totally wrong, please help me in finding the correct solution. I'm somewhat going in circles here and haven't been able to find any working solutions so far.

Matplotlib scatter - imshow offset

I am overlaying a scatter plot of points on an imshow 128 x 128 pixels. If you look closely here:
the objects do not always fall exactly on the center of the corresponding pixels. I tried different interpolations on imshow and origins for scatter, but nothing changed. So I thought I could overlay a grid to see how much this offset actually is:
and I noticed that the grid also falls exactly on the objects and not the center of the imshow pixels. The script for the above plot is:
fig = plt.figure(figsize=(15,8))
plt.imshow(counts_pre[:,:,slice_z],cmap='viridis',interpolation=None)
plt.scatter(j_index,i_index, s = 0.1, c = 'red', marker = 'o')
myInterval=1.
loc = matplotlib.ticker.MultipleLocator(base=myInterval)
plt.gca().xaxis.set_minor_locator(loc)
plt.gca().yaxis.set_minor_locator(loc)
plt.grid(which="both", linewidth=0.72,color="white",alpha=0.1)
plt.tick_params(which="minor", length=0)
plt.show()
Any ideas on why this offset exists and how I can fix it? Notice that the grid is not very homogeneous, i.e. some squares are rectangular.
Edit:
Upgrading to the newest matplotlib version did not resolve the
issue.
I created objects where the entries are non-zero, such that I know that the points should be perfectly aligned, but they still don't match up.

Change width of image in Opencv using Numpy

I'm making a Python file that will make a filter to have color on the Canny filter in OpenCV. I do this change from grayscale to color using the code provided below. My problem is when I apply the concatenate method (to add the color back as Canny filter is converted to grayscale), it cuts the width of the screen in 3 as I show in the 2 screenshots of before the color is added and after. The code snippet shown is only the transformation from grayscale to colored images.
What I've tried:
Tried using NumPy.tile: this wasn't the wisest attempt as it just repeated the same 1/3 of the screen twice more and didn't expand it to take up the whole screen as I had hoped.
Tried changing the image to only be from the index of 1/3 of the screen to cover the entire screen.
Tried setting the column index that is blank to equal None.
Image without the color added
Image with the color added
My code:
def convert_pixels(image, color):
rows, cols = image.shape
concat = np.zeros(image.shape)
image = np.concatenate((image, concat), axis=1)
image = np.concatenate((image, concat), axis=1)
image = image.reshape(rows, cols, 3)
index = image.nonzero()
#TODO: turn color into constantly changing color wheel or shifting colors
for i in zip(index[0], index[1], index[2]):
color.next_color()
image[i[0]][i[1]] = color.color
#TODO: fix this issue below:
#image[:, int(cols/3):cols] = None # turns right side (gliched) into None type
return image, color
In short, you're using concatenate on the wrong axis. axis=1 is the "columns" axis, so you're just putting two copies of zeros next to each other in the x direction. Since you want a three-channel image I would just initialize color_image with three channels and leave the original grayscale image alone:
def convert_pixels(image,color):
rows, cols = image.shape
color_image = np.zeros((rows,cols,3),dtype=np.uint8)
idx = image.nonzero()
for i in zip(*idx):
color_image[i] = color.color
return color_image,color
I've changed the indexing to match. I can't check this exactly since I don't know what your color object is, but I can confirm this works in terms of correctly shaping and indexing the new image.

Detect Color of particular area of Image Nodejs OpenCV

I'm trying to write code to detect the color of a particular area of an image.
So far I have come across is using OpenCV, we can do this, But still haven't found any particular tutorial to help with this.
I want to do this with javascript, but I can also use python OpenCV to get the results.
can anyone please help me with sharing any useful link or can explain how can I achieve detecting the color of the particular area in the image.
For eg.
The box in red will show a different color. I need to figure out which color it is showing.
What I have tried:
I have tried OpenCV canny images, though I am successful to get area separated with canny images, how to detect the color of that particular canny area is still a challenge.
Also, I tried it with inRange method from OpenCV which works perfect
# find the colors within the specified boundaries and apply
# the mask
mask = cv2.inRange(image, lower, upper)
output = cv2.bitwise_and(image, image, mask = mask)
# show the images
cv2.imshow("images", np.hstack([image, output]))
It works well and extracts the color area from the image But is there any callback which responds if the image has particular color so that it can be all done automatically?
So I am assuming here that, you already know the location of the rect which is going to be dynamically changed and need to find out the single most dominant color in the desired ROI. There are a lot of ways to do the same, one is by getting the average, of all the pixels in the ROI, other is to count all the distinct pixel values in the given ROI, with some tolerance difference.
Method 1:
import cv2
import numpy as np
img = cv2.imread("path/to/img.jpg")
region_of_interest = (356, 88, 495, 227) # left, top, bottom, right
cropped_img = img[region_of_interest[1]:region_of_interest[3], region_of_interest[0]:region_of_interest[2]]
print cv2.mean(cropped_img)
>>> (53.430516018839604, 41.05708814243569, 244.54991977640907, 0.0)
Method 2:
To find out the various dominant clusters in the given image you can use cv2.kmeans() as:
import cv2
import numpy as np
img = cv2.imread("path/to/img.jpg")
region_of_interest = (356, 88, 495, 227)
cropped_img = img[region_of_interest[1]:region_of_interest[3], region_of_interest[0]:region_of_interest[2]]
Z = cropped_img.reshape((-1, 3))
Z = np.float32(Z)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 4
ret, label, center = cv2.kmeans(Z, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
# Sort all the colors, as per their frequencies, as:
print center[sorted(range(K), key=lambda x: np.count_nonzero(label == [x]), reverse=True)[0]]
>>> [ 52.96525192 40.93861389 245.02325439]
#Prateek... nice to have the question narrowed down to the core. The code you provided does not address this issue at hand and remains just a question. I'll hint you towards a direction but you have to code it yourself.
steps that guide you towards a scripting result:
1) In your script add two (past & current) pixellists to store values (pixeltype + occurance).
2) Introduce a while-loop with an action true/stop statement (link to "3") for looping purpose because then it becomes a dynamic process.
3) Write a GUI with a flashy warning banner.
4) compare the pixellist with current_pixellist for serious state change (threshhold).
5) If the delta state change at "4" meets threshold throw the alert ("3").
When you've got written the code and enjoyed the trouble of tracking the tracebacks... then edit your question, update it with the code and reshape your question (i can help wiht that if you want). Then we can pick it up from there. Does that sound like a plan?
I am not sure why you need callback in this situation, but maybe this is what you mean?
def test_color(image, lower, upper):
mask = cv2.inRange(image, lower, upper)
return np.any(mask == 255)
Explanations:
cv2.inRange() will return 255 when pixel is in range (lower, upper), 0 otherwise (see docs)
Use np.any() to check if any element in the mask is actually 255

Specify Width and Height of Plot

I have a panel containing three plots. How can I use par to specify the width and height of the main panel so it is always at a fixed size?
You do that in the device, e.g.
x11(width=4, height=6)
and similarly for the file-based ones
pdf("/tmp/foo.pdf", width=4, height=6)
You can read the physical size via par("cin") etc but not set it.
Neither solution works in Jupyter notebooks. Here is a general approach that works in any environment:
options(repr.plot.width=6, repr.plot.height=4)
Just keep the following function handy:
set_plot_dimensions <- function(width_choice, height_choice) {
options(repr.plot.width=width_choice, repr.plot.height=height_choice)
}
EXAMPLE
Data
x <- c(37.50,46.79,48.30,46.04,43.40,39.25,38.49,49.51,40.38,36.98,40.00,38.49,37.74,47.92,44.53,44.91,44.91,40.00,41.51,47.92,36.98,43.40)
Call function with dimensions, and draw plot:
set_plot_dimensions(6, 4)
show_distribution(x, 'test vector')
set_plot_dimensions(16, 4)
show_distribution(x, 'test vector')
I usually set this at the start of my session with windows.options:
windows.options(width=10, height=10)
# plot away
plot(...)
If you need to reset to "factory settings":
dev.off()
windows.options(reset=TRUE)
# more plotting
plot(...)

Resources