Plotting a 2D histogram in matplotlib with different sized arrays - arrays

I am trying to make a 2D histogram using data from an h5 file. This file contains calculations of the Chi1 angle of an amino acid for 100 iterations and the values for each Chi angle are stored as a list of arrays within the file. I want to make a histogram of the values of the Chi1 angle for each iteration. In short, I want the x-axis to be the Chi1 angles and the y-axis to be iteration number. Here is the code that I have tried:
import numpy as np
import h5py
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
auxdata = [] #An empty list
iteration = [] #An empty list
for i in range(1,100): #100 iterations of calculations
string = "iterations/iter_" + str(i).zfill(8) + "/auxdata" + "/Trp43_Chi1" #Going to the right place in the h5 file to find the data I want
f = h5py.File("west.h5") #Loading in the h5 file
Chi1 = f[string] #Defining x-axis variable
iter_variable = i #Defining y-axis variable
auxdata_iter = auxdata + list(Chi1[:]) #X-axis variable becomes a list of arrays of varied sizes
iter_data = iteration + list([iter_variable]) # Y-axis variable becomes an array of a single value, which is the iteration number
###Plotting###
plt.hist2d(auxdata_iter, iter_data, bins=(100)); #2D histogram divided into 100 bins
plt.xlabel("Trp43 Chi1");
plt.ylabel("Frequency");
plt.title("GB1 Trp43 Chi1 Angle Distribution");
plt.savefig("Trp43_Chi1.png")
The problem is that I get the error "ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()".
What I need to learn how to do is to map every Chi1 angle value (x-axis) from a given iteration to the iteration number (y-axis).
Do you have any ideas? Thanks!

Related

How to save a range of images when under a loop in python

In case there is a range of image say the dimensions is said to be (45,128,128) and I have displayed it. Seeing the result now I have decided that I need a range of images between, say, 25-36 so I end up writing a loop in order to display the interested range of image
import itertools as it
for i in it.chain(range(25,32)):
img_disp = (x1[i]) #x1 is the input image with dimension (45,128,128)
plt.imshow(img_disp)
plt.show()
#displays the desired images of given range 25-32
Now this displays an array of images from 25-32, now how do i save this particluar array of images as a single (with dimension (8,128,128)) .npy file?
You should try:
import numpy as np
# Create an empty array to hold the images
img_array = np.empty((8, 128, 128))
# Fill the array with the desired images
for i, j in enumerate(range(25, 33)):
img_array[i] = x1[j]
# Save the array as a .npy file
np.save('img_array.npy', img_array)

Interpolate 2D Array to single point in MATLAB

I have 3 graphs of an IV curve (monotonic increasing function. consider a positive quadratic function in the 1st quadrant. Photo attached.) at 3 different temperatures that are not obtained linearly. That is, one is obtained at 25C, one at 125C and one at 150C.
What I want to make is an interpolated 2D array to fill in the other temperatures. My current method to build a meshgrid-type array is as follows:
H = 5;
W = 6;
[Wmat,Hmat] = meshgrid(1:W,1:H);
X = [1:W; 1:W];
Y = [ones(1,W); H*ones(1,W)];
Z = [vecsatIE25; vecsatIE125];
img = griddata(X,Y,Z,Wmat,Hmat,'linear')
This works to build a 6x6 array, which I can then index one row from, then interpolate from that 1D array.
This is really not what I want to do.
For example, the rows are # temps = 25C, 50C, 75C, 100C, 125C and 150C. So I must select a temperature of, say, 50C when my temperature is actually 57.5C. Then I can interpolate my I to get my V output. So again for example, my I is 113.2A, and I can actually interpolate a value and get a V for 113.2A.
When I take the attached photo and digitize the plot information, I get an array of points. So my goal is to input any Temperature and any current to get a voltage by interpolation. The type of interpolation is not as important, so long as it produces reasonable values - I do not want nearest neighbor interpolation, linear or something similar is preferred. If it is an option, I will try different kinds of interpolation later (cubic, linear).
I am not sure how I can accomplish this, ideally. The meshgrid array does not need to exist. I simply need the 1 value.
Thank you.
If I understand the question properly, I think what you're looking for is interp2:
Vq = interp2(X,Y,V,Xq,Yq) where Vq is the V you want, Xq and Yq are the temperature and current, and X, Y, and V are the input arrays for temperature, current, and voltage.
As an option, you can change method between 'linear', 'nearest', 'cubic', 'makima', and 'spline'

How to transfer a value from an innermost while loop to the outer for loop in python?

Let's assume there is a big sphere with known center (Xo,Yo,Zo) and radius Ro. It contains millions of particles each with known mass and 3d position with respect to the same reference frame. Inside this big sphere there are a dozen of smaller imaginary spheres randomly distributed in the 3d space but otherwise known positions. I would like to calculate the number of the particles inside each smaller sphere, and hence, the resulting mass of each one of the smaller spheres (containers) by counting those particles that are inside each one of them.
Here is my MWE snippet in which I am looping over individual particles to see if they are within each of the smaller sphere and then counting them individually for each sphere in order to come up with a total mass for each smaller sphere:
import numpy as np
from scipy.spatial.distance import euclidean
### there is 10 small spheres inside Big Sphere each containing different number of particles and hence different masses
### small_sphere_id_array is the array of the IDs of the small spheres
### small_sphere_position_array is the array of the position of the center of small spheres
### small_sphere_radius_array is the array of the radii of small spheres
### small_sphere_mass_array is the array of the masses of small spheres
### particle_position_array is the array of the positions of particles inside the Big Sphere
### particle_mass_array is the array of the masses of particles inside the Big Sphere
for small_sphere_index in np.arange(0, 10)):
for particle_index in np.arange(0, 6000000)):
small_sphere_mass_array = []
small_sphere_mass = 0
distances = euclidean(particle_position_array[particle_index], small_sphere_position_array[small_sphere_index])
success_condition = (distances <= small_shpere_radius_array[small_sphere_index])
while success_condition:
small_sphere_mass += particle_mass_array[particle_index]
small_sphere_mass_array.append(small_sphere_mass)
small_sphere_mass = np.sum(small_sphere_mass_array)
else:
break
print('{}, {}'.format(small_sphere_id_array[small_sphere_index], small_sphere_mass))
I am expecting to have printed out 10 lines (corresponding to 10 small spheres) with their IDs first followed by their total mass. But, here is the output I have:
some number, 0
some number, 0
some number, 0
some number, 0
some number, 0
some number, 0
some number, 0
some number, 0
some number, 0
some number, 0
In particular I cannot take the result of while loop and move it to the outer for loop and hence loop over all particles to come up with a single nonzero total mass for each small sphere. I do seem to correctly loop over 10 small spheres but with the problem that the mass ends up being zero which means the middle for loop is not able to account for all 6000000 particles. (hint: all particles do have mass.)
I just learned (through a friend of mine) that I was mixing the syntax between python and C++ in the sense that unlike C++ where the assigned value of a variable cannot be taken from an inner loop to an outer loop, python is actually able to remember the assigned value just through the indent between loops. In python (unlike C++) once a loop is executed and the end of it is arrived, then by one indentation out, the python can still recall what it was calculating and hence have access to the end product of the loop. So instead of using while loop, I am supposed to use if loop to make sure that all the particles have been checked against the condition. Also the initialization of the variables small_sphere_mass and small_sphere_mass_array should be taken outside the inner loop so that I am not forcing the loop to stuck with the first zero value all the times.
import numpy as np
from scipy.spatial.distance import euclidean
### there is 10 small spheres inside Big Sphere each containing different number of particles and hence different masses
### small_sphere_id_array is the array of the IDs of the small spheres
### small_sphere_position_array is the array of the position of the center of small spheres
### small_sphere_radius_array is the array of the radii of small spheres
### small_sphere_mass_array is the array of the masses of small spheres
### particle_position_array is the array of the positions of particles inside the Big Sphere
### particle_mass_array is the array of the masses of particles inside the Big Sphere
for small_sphere_index in np.arange(0, 10)):
small_sphere_mass_array = []
small_sphere_mass = 0
for particle_index in np.arange(0, 6000000)):
distances = euclidean(particle_position_array[particle_index], small_sphere_position_array[small_sphere_index])
if (distances <= small_shpere_radius_array[small_sphere_index]):
part_particle=particle_mass_array[particle_index]
small_sphere_mass += part_particle
small_sphere_mass_array.append(part_particle)
print('{}, {}'.format(small_sphere_id_array[small_sphere_index], small_sphere_mass))

Reshaping an outputted 1 dimensional numpy array into a 2/3 dimensional array

So I'm using an image's pixel data, applying some calculations to it, which gives me a resulting array whose shape is unknown until the calculations are done to it.
I'm having trouble reshaping the outputted array into a 2-dimensional or 3-dimensional array
Here is an example
from PIL import Image
img = Image.open('C:\Users\Amit\Desktop\sample_pic.jpeg').convert("RGB")
pixels =np.array(img)
print(pixels.shape) # (477L, 887L, 3L) PIL seems to switch height and width because original dimensions are 877 x 477
flat = pixels.flatten()
print (flat.shape) # (1269297L,)
filter1= np.array([1,1,0])
pixels2 = np.array([])
for i in range(0, len(flat),2):
pixels2 =np.append(pixels2,np.sum((flat[i:i+3] * filter1)))
The loop at the end is just doing some calculations to the flattened array, and outputting a new array whose shape I don't know till the output
print pixels2.shape
#(634649L,)
So I'm trying to reshape the outputted array into dimensions fit for a picture.
I tried the code
pixels2.reshape(800,-1)
but I got the error
pixels2.reshape(800,-1)
ValueError: total size of new array must be unchanged
same with
pixels.reshape(800,-1,3)
ValueError: total size of new array must be unchanged
I was hoping that adding the (-1) would automatically find the appropriate second dimension but that doesn't seem to be the case. I'm not bound to the number 800 as one of the dimensions but I'm looking for the first two dimensions to be above 300 so (300+, 300+, 3)
Thanks.
Update:
adding one more element to the pixels2 array, makes it a (634650L,) array which is divisible by 3. ( I found it by trial and error)
But finding the other two dimensions involves a lot of trial and error as well it seems. (800, -1, 3) doesn't work.

How do i store sequence of 2D matrices into a 3D array in Matlab?

I have these series of 2D CT images and i have been able to read them into Matlab using "imread". The issue however is that i need the image read-in as a single 3D matrix rather than stack of several 2D matrices. I have been made aware that it is possible to store the number of 2D layers as the 3rd dimension, but i have no idea how to do this as i am still a learner.
The code i have for reading in the 2D stack are as follows:
a = dir('*.tif');
for i = 1: numel(a)
b = imread(a(i).name); %read in the image
b_threshold = graythresh(b); %apply threshold
b_binary = im2bw(b, b_threshold); %binarize image
[m, n] = size(b); %compute the size of the matrix
phi(i) = ((m*n) - sum((b_binary(:))))/(m*n); %compute the fraction of pore pixels in the image
phi(:,i) = phi(i); %store each of the above result
end
I have added just a single image although several of these are needed. Nevertheless, one can easily duplicate the image to create a stack of 2D images. For the code to work, it is however important to rename them in a numerical order.pore_image
Any help/suggestions/ideas is welcomed. Thanks!
You can simply assign along the third dimension using i as your index
stack_of_images(:,:,i) = b_binary
Well, the first advice is try to don't use the variable i and j in matlab because they are reserved (have a look here and here).
After it depends on along which dimension you want to store the 2D images:
if you want to store the images along the first dimension just use this code:
a = dir('*.tif');
for ii = 1: numel(a)
b = imread(a(ii).name); %read in the image
b_threshold = graythresh(b); %apply threshold
b_binary = im2bw(b, b_threshold); %binarize image
[m, n] = size(b); %compute the size of the matrix
phi(ii) = ((m*n) - sum((b_binary(:))))/(m*n); %compute the fraction of pore pixels in the image
phi(:,ii) = phi(ii); %store each of the above result
matrix_3D_images(ii,:,:)=b_binary; %adding a new layer
end
If you want to store the images along other dimensions it is easy to do: just change the posizion of the "pointer" ii:
matrix_3D_images(:,ii,:)=b_binary; or
matrix_3D_images(:,:,ii)=b_binary;

Resources