1 from nucleus_class      
import nucleus
 
    5 from matplotlib 
import cm
 
    6 from matplotlib.colors 
import ListedColormap, LinearSegmentedColormap
 
    7 from matplotlib.collections 
import LineCollection
 
   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]