nucleus_multiple_class.py
Go to the documentation of this file.
1 # Author: M. Reichert
2 import pandas as pd
3 import numpy as np
4 from .nucleus_class import nucleus
5 import os
6 
7 
8 class nucleus_multiple(object):
9  """
10  Class to deal with lists of nucleus objects
11  """
12  def __init__(self,names=None,A=None,Z=None,N=None,Y=None,X=None):
13  """
14  Initialize the class
15  Input:
16  nuclist - list of nucleus names
17  """
18  self.names = names
19  self.A = A
20  self.Z = Z
21  self.N = N
22  # Get sophisticated names, A, Z, N
23  if not (names is None):
24  self.__init_with_list()
25  elif not(A is None) or not(Z is None) or not (N is None):
26  self.__init_with_data()
27 
28  if not(Y is None):
29  self.Y = np.array(Y)
30  elif not(X is None):
31  self.Y = np.array(X)/self.A
32  else:
33  self.Y = np.zeros(len(self.A))
34 
35 
36  def __repr__(self):
37  return self.df.__str__()
38 
39  def __init_with_list(self):
40  """
41  Initialize the class using the list of nucleinames
42  """
43  self.A = np.array([nucleus(n).get_A() for n in self.names])
44  self.Z = np.array([nucleus(n).get_Z() for n in self.names])
45  self.N = self.A-self.Z
46  self.names = np.array(self.names)
47 
48  def __init_with_data(self):
49  """
50  Initialize the class using A,Z,N
51  """
52  # Sanity checks
53  if np.sum([not(self.A is None), not(self.Z is None), not (self.N is None)]) <2:
54  raise Exception("You need to provide at least two of A, Z, N!")
55 
56  if not (self.A is None):
57  if not (self.Z is None):
58  self.A = np.array(self.A)
59  self.Z = np.array(self.Z)
60  # Sanity check
61  if len(self.A)!=len(self.Z):
62  raise Exception("A and Z had different lengths (A: "+str(len(self.A))+", Z:"+str(len(self.Z))+")!")
63  self.N = self.A-self.Z
64  elif not (self.N is None):
65  self.A = np.array(self.A)
66  self.N = np.array(self.N)
67  # Sanity check
68  if len(self.A)!=len(self.N):
69  raise Exception("A and N had different lengths (A: "+str(len(self.A))+", N:"+str(len(self.N))+")!")
70  self.Z = self.A-self.N
71  else:
72  raise Exception("Something strange happened!")
73  elif not (self.Z is None):
74  self.N = np.array(self.N)
75  self.Z = np.array(self.Z)
76  if len(self.Z)!=len(self.N):
77  raise Exception("N and Z had different lengths (N: "+str(len(self.N))+", Z:"+str(len(self.Z))+")!")
78  self.A = self.Z+self.N
79  else:
80  raise Exception("Something strange happened!")
81 
82  # Sanity check
83  if np.min(self.N)<0:
84  raise Exception("N was smaller zero!")
85  elif np.min(self.Z)<0 :
86  raise Exception("Z was smaller zero!")
87  elif np.min(self.A)<0:
88  raise Exception("A was smaller zero!")
89 
90  # Create the names
91  self.names = np.array([nucleus(N=self.N[ind],Z=self.Z[ind]).get_name() for ind in range(len(self.N))])
92 
93 
94 
95  def __sum_over(self,A,Y):
96  max_A = max(A)
97  # second_dimension = len(Y[0,:])
98  Y_new = np.zeros([max_A+1,])
99  for i in range(len(A)):
100  Y_new[int(A[i])] += Y[i]
101  return np.array(range(max_A+1)),Y_new
102 
103 
104 
105  @property
106  def X(self):
107  """
108  Mass fraction
109  """
110  return self.Y*self.A
111 
112  @X.setter
113  def X(self,value):
114  """
115  Mass fraction
116  """
117  self.Y=value/self.A
118 
119 
120  @property
121  def A_X(self):
122  """
123  Get sum over equal A's
124  """
125  atmp,xtmp = self.__sum_over(self.A,self.X)
126  return np.array(atmp),np.array(xtmp)
127 
128  @property
129  def Z_Y(self):
130  """
131  Get sum over equal Z's
132  """
133  ztmp,ytmp = self.__sum_over(self.Z,self.Y)
134  return ztmp,ytmp
135 
136  @property
137  def Z_X(self):
138  """
139  Get sum over equal Z's
140  """
141  ztmp,ytmp = self.__sum_over(self.Z,self.X)
142  return ztmp,ytmp
143 
144 
145  @property
146  def Yprot(self):
147  """
148  Abundance of protons
149  """
150  mask = (self.A==1) & (self.Z==1)
151  if sum(mask)!=1:
152  raise Exception("Problem when getting hydrogen abundances!")
153  else:
154  return self.Y[mask][0]
155  @property
156  def Yneut(self):
157  """
158  Abundance of protons
159  """
160  mask = (self.A==1) & (self.N==1)
161  if sum(mask)!=1:
162  raise Exception("Problem when getting neutron abundances!")
163  else:
164  return self.Y[mask][0]
165  @property
166  def Yhe4(self):
167  """
168  Abundance of protons
169  """
170  mask = (self.A==4) & (self.Z==2)
171  if sum(mask)!=1:
172  raise Exception("Problem when getting alpha abundances!")
173  else:
174  return self.Y[mask][0]
175 
176 
177  @property
178  def df(self):
179  """
180  Get a dataframe out
181  """
182  df = pd.DataFrame()
183  df["nucleus"] = self.names
184  df["A"] = self.A
185  df["Z"] = self.Z
186  df["N"] = self.N
187  df["Y"] = self.Y
188  df["X"] = self.Y*self.A
189  return df
190 
191 
192  def __merge_nuclei(self,A,Z):
193  """
194  Merge another list of nuclei into the own one.
195  """
196  A_merged = np.append(self.A,A)
197  Z_merged = np.append(self.Z,Z)
198  c_list = np.array([A_merged,Z_merged])
199  # print(A_merged)
200  # print(Z_merged)
201  unique=np.unique(c_list,axis=1)
202  return unique[0,:],unique[1,:]
203 
204 
205  def __mul__(self,other):
206  """
207  Multiply either two instances of nuclei lists or a float with this instance.
208  """
209  if isinstance(other,float) or isinstance(other,int):
210  self.Y=self.Y*other
211  elif isinstance(other,nucleus_multiple):
212  merge_A,merge_Z = self.__merge_nuclei(other.A,other.Z)
213  merge_N = merge_A-merge_Z
214  Y_list = np.zeros(len(merge_N))
215  for ind,atmp in enumerate(merge_A):
216  mask_self = (self.A ==merge_A[ind]) & (self.Z ==merge_Z[ind])
217  mask_other = (other.A==merge_A[ind]) & (other.Z==merge_Z[ind])
218  if (np.any(mask_self)) and (np.any(mask_other)):
219  Y_list[ind] = self.Y[mask_self][0]*other.Y[mask_other][0]
220  self.A = merge_A
221  self.Z = merge_Z
222  self.N = merge_N
223  self.Y = Y_list
224  self.__init_with_data()
225  return self
226 
227  def __truediv__(self,other):
228  """
229  Multiply either two instances of nuclei lists or a float with this instance.
230  """
231  if isinstance(other,float) or isinstance(other,int):
232  self.Y=self.Y/other
233  elif isinstance(other,nucleus_multiple):
234  merge_A,merge_Z = self.__merge_nuclei(other.A,other.Z)
235  merge_N = merge_A-merge_Z
236  Y_list = np.zeros(len(merge_N))
237  for ind,atmp in enumerate(merge_A):
238  mask_self = (self.A ==merge_A[ind]) & (self.Z ==merge_Z[ind])
239  mask_other = (other.A==merge_A[ind]) & (other.Z==merge_Z[ind])
240  if (np.any(mask_self)) and (np.any(mask_other)):
241  Y_list[ind] = self.Y[mask_self][0]/other.Y[mask_other][0]
242  self.A = merge_A
243  self.Z = merge_Z
244  self.N = merge_N
245  self.Y = Y_list
246  self.__init_with_data()
247  return self
248 
249 
250 
251  def __rmul__(self,other):
252  return self.__mul__(other)
253 
254 
255  def __add__(self,other):
256  """
257  Add to instances of this class. The abundances are added for each nucleus.
258  """
259  if isinstance(other,float) or isinstance(other,int):
260  self.Y=self.Y+other
261  elif isinstance(other,nucleus_multiple):
262  merge_A,merge_Z = self.__merge_nuclei(other.A,other.Z)
263  merge_N = merge_A-merge_Z
264  Y_list = np.zeros(len(merge_N))
265  for ind,atmp in enumerate(merge_A):
266  mask_self = (self.A ==merge_A[ind]) & (self.Z ==merge_Z[ind])
267  mask_other = (other.A==merge_A[ind]) & (other.Z==merge_Z[ind])
268  if (np.any(mask_self)):
269  Y_list[ind] += self.Y[mask_self][0]
270  if (np.any(mask_other)):
271  Y_list[ind] += other.Y[mask_other][0]
272  self.A = merge_A
273  self.Z = merge_Z
274  self.N = merge_N
275  self.Y = Y_list
276  self.__init_with_data()
277  return self
278 
279  def write_finab(self,path="finab.dat"):
280  """
281  Write the result (contained in self.__abundances) into a final abundance file. The format is:
282  |A Z N Yi Xi|
283  Input:
284  path - Path to output file
285  """
286  Y = self.Y
287  X = self.Y*self.A
288  A = self.A
289  Z = self.Z
290  N = self.N
291 
292  output = np.array([A,Z,N,Y,X]).T
293  np.savetxt(path,output,fmt=['%7i','%7i','%7i',' %1.9e',' %1.9e'],header='A Z N Y X')
294 
295 
296  def write_seed(self,path=None):
297  """
298  Write a seed file
299  """
300  line=""
301  for i in range(len(self.A)):
302  X = self.Y[i]*self.A[i]
303  mafra = '%1.6e' % float(X)
304  if np.isnan(X) or X<=1e-15:
305  continue
306  nam = self.names[i].lower()
307  # Take care of special names
308  if (nam.strip() == 'neutron') or (nam.strip() == 'neutron1'):
309  nam = 'n'
310  elif nam.strip() == 'h1':
311  nam = 'p'
312  elif nam.strip() == 'h2':
313  nam = 'd'
314  elif nam.strip() == 'h3':
315  nam = 't'
316 
317  line+= nam.rjust(5) + ' '*7 + mafra
318  if i != len(self.A)-1:
319  line+="\n"
320  # Make a default path
321  if path is None:
322  path = "seed.dat"
323 
324  with open(path,"w") as f:
325  f.write(line)
326 
327 
328 if __name__ == "__main__":
329  """ Test the class """
330 
331  nlist = ["o16","ni56"]
332  A = [1,16,17,56]
333  Z = [1,8,8,28]
334  Y = [0.1,0.1,0.1,0.1]
335  nucl = nucleus_multiple(A=A,Z=Z,Y=Y)
336  A = [2,16,10,56,56]
337  Z = [1,8,8,28,26]
338  Y = [0.2,0.2,0.3,0.4,0.1]
339 
340  nucl2 = nucleus_multiple(A=A,Z=Z,Y=Y)
341  print(nucl+nucl2)
342  A,X=nucl2.A_X
bin.class_files.nucleus_multiple_class.nucleus_multiple.__add__
def __add__(self, other)
Definition: nucleus_multiple_class.py:255
bin.class_files.nucleus_multiple_class.nucleus_multiple.Z_Y
def Z_Y(self)
Definition: nucleus_multiple_class.py:129
bin.class_files.nucleus_multiple_class.nucleus_multiple.A
A
Definition: nucleus_multiple_class.py:19
bin.class_files.nucleus_multiple_class.nucleus_multiple.__rmul__
def __rmul__(self, other)
Definition: nucleus_multiple_class.py:251
bin.class_files.nucleus_multiple_class.nucleus_multiple.Yneut
def Yneut(self)
Definition: nucleus_multiple_class.py:156
bin.class_files.nucleus_multiple_class.nucleus_multiple.df
def df(self)
Definition: nucleus_multiple_class.py:178
bin.class_files.nucleus_multiple_class.nucleus_multiple.Yprot
def Yprot(self)
Definition: nucleus_multiple_class.py:146
bin.class_files.nucleus_multiple_class.nucleus_multiple.Z_X
def Z_X(self)
Definition: nucleus_multiple_class.py:137
bin.create_alpha_decay_file.get_name
def get_name(Z, N, Zdict, Ndict)
Definition: create_alpha_decay_file.py:116
bin.class_files.nucleus_multiple_class.nucleus_multiple.__repr__
def __repr__(self)
Definition: nucleus_multiple_class.py:36
bin.class_files.nucleus_multiple_class.nucleus_multiple.Yhe4
def Yhe4(self)
Definition: nucleus_multiple_class.py:166
bin.class_files.nucleus_multiple_class.nucleus_multiple.__mul__
def __mul__(self, other)
Definition: nucleus_multiple_class.py:205
bin.class_files.nucleus_multiple_class.nucleus_multiple.__init_with_list
def __init_with_list(self)
Definition: nucleus_multiple_class.py:39
bin.class_files.nucleus_multiple_class.nucleus_multiple.Z
Z
Definition: nucleus_multiple_class.py:20
bin.class_files.nucleus_multiple_class.nucleus_multiple.__init__
def __init__(self, names=None, A=None, Z=None, N=None, Y=None, X=None)
Definition: nucleus_multiple_class.py:12
bin.class_files.nucleus_multiple_class.nucleus_multiple.__init_with_data
def __init_with_data(self)
Definition: nucleus_multiple_class.py:48
bin.class_files.nucleus_multiple_class.nucleus_multiple.__sum_over
def __sum_over(self, A, Y)
Definition: nucleus_multiple_class.py:95
bin.class_files.nucleus_multiple_class.nucleus_multiple.write_finab
def write_finab(self, path="finab.dat")
Definition: nucleus_multiple_class.py:279
bin.class_files.nucleus_class.nucleus
Definition: nucleus_class.py:9
bin.class_files.nucleus_multiple_class.nucleus_multiple.X
def X(self)
Definition: nucleus_multiple_class.py:106
bin.class_files.nucleus_multiple_class.nucleus_multiple.N
N
Definition: nucleus_multiple_class.py:21
bin.class_files.nucleus_multiple_class.nucleus_multiple.A_X
def A_X(self)
Definition: nucleus_multiple_class.py:121
bin.class_files.nucleus_multiple_class.nucleus_multiple
Definition: nucleus_multiple_class.py:8
bin.class_files.nucleus_multiple_class.nucleus_multiple.Y
Y
Definition: nucleus_multiple_class.py:29
bin.class_files.nucleus_multiple_class.nucleus_multiple.__merge_nuclei
def __merge_nuclei(self, A, Z)
Definition: nucleus_multiple_class.py:192
bin.class_files.nucleus_multiple_class.nucleus_multiple.names
names
Definition: nucleus_multiple_class.py:18
bin.class_files.nucleus_multiple_class.nucleus_multiple.__truediv__
def __truediv__(self, other)
Definition: nucleus_multiple_class.py:227
bin.class_files.nucleus_multiple_class.nucleus_multiple.write_seed
def write_seed(self, path=None)
Definition: nucleus_multiple_class.py:296