1 from .nucleus_class
import nucleus
5 from matplotlib
import cm
6 from matplotlib.colors
import ListedColormap, LinearSegmentedColormap
7 from matplotlib.collections
import LineCollection
10 class nucleus_multiple(object):
12 Class to deal with lists of nucleus objects
14 def __init__(self,names=None,A=None,Z=None,N=None,Y=None,X=None):
18 nuclist - list of nucleus names
25 if not (names
is None):
27 elif not(A
is None)
or not(Z
is None)
or not (N
is None):
33 self.
Y = np.array(X)/self.
A
35 self.
Y = np.zeros(len(self.
A))
37 self.
A = self.
A.astype(int)
38 self.
Z = self.
Z.astype(int)
39 self.
N = self.
N.astype(int)
43 return self.
df.__str__()
47 Initialize the class using the list of nucleinames
51 self.
N = self.
A-self.
Z
56 Initialize the class using A,Z,N
59 if np.sum([not(self.
A is None), not(self.
Z is None),
not (self.
N is None)]) <2:
60 raise Exception(
"You need to provide at least two of A, Z, N!")
62 if not (self.
A is None):
63 if not (self.
Z is None):
64 self.
A = np.array(self.
A).astype(int)
65 self.
Z = np.array(self.
Z).astype(int)
67 if len(self.
A)!=len(self.
Z):
68 raise Exception(
"A and Z had different lengths (A: "+str(len(self.
A))+
", Z:"+str(len(self.
Z))+
")!")
69 self.
N = self.
A-self.
Z
70 elif not (self.
N is None):
71 self.
A = np.array(self.
A).astype(int)
72 self.
N = np.array(self.
N).astype(int)
74 if len(self.
A)!=len(self.
N):
75 raise Exception(
"A and N had different lengths (A: "+str(len(self.
A))+
", N:"+str(len(self.
N))+
")!")
76 self.
Z = self.
A-self.
N
78 raise Exception(
"Something strange happened!")
79 elif not (self.
Z is None):
80 self.
N = np.array(self.
N).astype(int)
81 self.
Z = np.array(self.
Z).astype(int)
82 if len(self.
Z)!=len(self.
N):
83 raise Exception(
"N and Z had different lengths (N: "+str(len(self.
N))+
", Z:"+str(len(self.
Z))+
")!")
84 self.
A = self.
Z+self.
N
86 raise Exception(
"Something strange happened!")
90 raise Exception(
"N was smaller zero!")
91 elif np.min(self.
Z)<0 :
92 raise Exception(
"Z was smaller zero!")
93 elif np.min(self.
A)<0:
94 raise Exception(
"A was smaller zero!")
104 Y_new = np.zeros([max_A+1,])
105 for i
in range(len(A)):
106 Y_new[int(A[i])] += Y[i]
107 return np.array(range(max_A+1)),Y_new
129 Get sum over equal A's
132 return np.array(atmp),np.array(xtmp)
137 Get sum over equal Z's
145 Get sum over equal Z's
156 return np.sum(self.
Y*self.
Z)
163 mask = (self.
A==1) & (self.
Z==1)
165 raise Exception(
"Problem when getting hydrogen abundances!")
167 return self.
Y[mask][0]
173 mask = (self.
A==1) & (self.
N==1)
175 raise Exception(
"Problem when getting neutron abundances!")
177 return self.
Y[mask][0]
183 mask = (self.
A==4) & (self.
Z==2)
185 raise Exception(
"Problem when getting alpha abundances!")
187 return self.
Y[mask][0]
195 return np.sum(self.
Y*self.
A)/np.sum(self.
Y)
202 return np.sum(self.
Y*self.
Z)/np.sum(self.
Y)
210 df[
"nucleus"] = self.
names
215 df[
"X"] = self.
Y*self.
A
227 elnames.append(
''.join([i
for i
in n
if not i.isdigit()]))
229 return np.array(elnames)
235 Merge another list of nuclei into the own one.
237 A_merged = np.append(self.
A,A)
238 Z_merged = np.append(self.
Z,Z)
239 c_list = np.array([A_merged,Z_merged])
242 unique=np.unique(c_list,axis=1)
243 return unique[0,:],unique[1,:]
248 Multiply either two instances of nuclei lists or a float with this instance.
250 if isinstance(other,float)
or isinstance(other,int):
252 elif isinstance(other,nucleus_multiple):
254 merge_N = merge_A-merge_Z
255 Y_list = np.zeros(len(merge_N))
256 for ind,atmp
in enumerate(merge_A):
257 mask_self = (self.
A ==merge_A[ind]) & (self.
Z ==merge_Z[ind])
258 mask_other = (other.A==merge_A[ind]) & (other.Z==merge_Z[ind])
259 if (np.any(mask_self))
and (np.any(mask_other)):
260 Y_list[ind] = self.
Y[mask_self][0]*other.Y[mask_other][0]
270 Multiply either two instances of nuclei lists or a float with this instance.
272 if isinstance(other,float)
or isinstance(other,int):
274 elif isinstance(other,nucleus_multiple):
276 merge_N = merge_A-merge_Z
277 Y_list = np.zeros(len(merge_N))
278 for ind,atmp
in enumerate(merge_A):
279 mask_self = (self.
A ==merge_A[ind]) & (self.
Z ==merge_Z[ind])
280 mask_other = (other.A==merge_A[ind]) & (other.Z==merge_Z[ind])
281 if (np.any(mask_self))
and (np.any(mask_other)):
282 Y_list[ind] = self.
Y[mask_self][0]/other.Y[mask_other][0]
298 Add to instances of this class. The abundances are added for each nucleus.
300 if isinstance(other,float)
or isinstance(other,int):
302 elif isinstance(other,nucleus_multiple):
304 merge_N = merge_A-merge_Z
305 Y_list = np.zeros(len(merge_N))
306 for ind,atmp
in enumerate(merge_A):
307 mask_self = (self.
A ==merge_A[ind]) & (self.
Z ==merge_Z[ind])
308 mask_other = (other.A==merge_A[ind]) & (other.Z==merge_Z[ind])
309 if (np.any(mask_self)):
310 Y_list[ind] += self.
Y[mask_self][0]
311 if (np.any(mask_other)):
312 Y_list[ind] += other.Y[mask_other][0]
322 Write the result (contained in self.__abundances) into a final abundance file. The format is:
325 path - Path to output file
337 output = np.array([A,Z,N,Y,X]).T
338 np.savetxt(path,output,fmt=[
'%7i',
'%7i',
'%7i',
' %1.9e',
' %1.9e'],header=
'A Z N Y X')
366 for i
in range(len(self.
A)):
367 X = self.
Y[i]*self.
A[i]
368 mafra =
'%1.6e' % float(X)
369 if np.isnan(X)
or X<=cutoff:
371 nam = self.
names[i].lower()
373 if (nam.strip() ==
'neutron')
or (nam.strip() ==
'neutron1'):
375 elif nam.strip() ==
'h1':
377 elif nam.strip() ==
'h2':
379 elif nam.strip() ==
'h3':
382 line+= nam.rjust(5) +
' '*7 + mafra
383 if i != len(self.
A)-1:
389 with open(path,
"w")
as f:
398 for i
in range(len(self.
A)):
399 nam = self.
names[i].lower()
401 if (nam.strip() ==
'neutron')
or (nam.strip() ==
'neutron1'):
403 elif nam.strip() ==
'h1':
405 elif nam.strip() ==
'h2':
407 elif nam.strip() ==
'h3':
411 if i != len(self.
A)-1:
417 with open(path,
"w")
as f:
425 for i
in range(len(A)):
426 indices = np.where((self.
A == A[i]) & (self.
Z == Z[i]))
427 self.
Y[indices] = Y[i]
435 Plot the nuclear chart with the nuclei that are here
453 matrix = np.empty([Zmax-Zmin+2,Nmax-Nmin+2])
455 for i
in range(len(Z)):
456 matrix[Z[i]-Zmin,N[i]-Nmin] = X[i]
460 X = np.arange(Nmin-0.5,Nmax+1.5,1)
461 Y = np.arange(Zmin-0.5,Zmax+1.5,1)
462 X,Y = np.meshgrid(X,Y)
464 if "facecolor" in kwargs:
465 cmap = ListedColormap([kwargs[
"facecolor"]])
466 im = ax.pcolor(X,Y,matrix,cmap=cmap,**kwargs)
468 im = ax.pcolor(X,Y,matrix,**kwargs)
472 matrix = np.empty([Zmax+1,Nmax+1])
474 for i
in range(len(Z)):
475 matrix[Z[i],N[i]] = 1
477 matrix[~np.isnan(matrix)] = 1
478 matrix[np.isnan(matrix)] = 0
480 bool_matrix = matrix.astype(bool)
484 ax.set_aspect(
"equal")
497 Get a list of all edges (where the value changes from True to False) in the 2D boolean image.
498 The returned array edges has he dimension (n, 2, 2).
499 Edge i connects the pixels edges[i, 0, :] and edges[i, 1, :].
500 Note that the indices of a pixel also denote the coordinates of its lower left corner.
503 ii, jj = np.nonzero(bool_img)
504 for i, j
in zip(ii, jj):
506 if j == bool_img.shape[1]-1
or not bool_img[i, j+1]:
507 edges.append(np.array([[i, j+1],
510 if i == bool_img.shape[0]-1
or not bool_img[i+1, j]:
511 edges.append(np.array([[i+1, j],
514 if j == 0
or not bool_img[i, j-1]:
515 edges.append(np.array([[i, j],
518 if i == 0
or not bool_img[i-1, j]:
519 edges.append(np.array([[i, j],
523 return np.zeros((0, 2, 2))
525 return np.array(edges)
530 Combine thee edges defined by 'get_all_edges' to closed loops around objects.
531 If there are multiple disconnected objects a list of closed loops is returned.
532 Note that it's expected that all the edges are part of exactly one loop (but not necessarily the same one).
536 while edges.size != 0:
538 loop = [edges[0, 0], edges[0, 1]]
539 edges = np.delete(edges, 0, axis=0)
541 while edges.size != 0:
543 ij = np.nonzero((edges == loop[-1]).all(axis=2))
553 loop.append(edges[i, (j + 1) % 2, :])
554 edges = np.delete(edges, i, axis=0)
556 loop_list.append(np.array(loop))
568 cl = LineCollection(outlines, **kwargs)
569 ax.add_collection(cl)
572 if __name__ ==
"__main__":
573 """ Test the class """
575 nlist = [
"o16",
"ni56"]
578 Y = [0.1,0.1,0.1,0.1]
582 Y = [0.2,0.2,0.3,0.4,0.1]