"""
The user entry point to interrogate the database, and to write custom software
==============================================================================
Direct database interrogation is through these functions
:py:meth:`ndlab.csv_data`, :py:meth:`ndlab.json_data`, :py:meth:`ndlab.csv_nl`,
:py:meth:`ndlab.pandas_csv_nl`, :py:meth:`ndlab.pandas_csv_web`.
Data retrieval cheat sheets
---------------------------
fields='GAMMA.NUC.Z, GAMMA.NUC.N, GAMMA.ENERGY'
filter='GAMMA.ENERGY > 560'
* Data in json format
json_data(fields , filter)"
* Data in csv format
csv_data(fields , filter )
* Data in csv format from a list of ndlab classes
csv_nl(nl_items)
* Creates a pandas dataframe
import pandas as pd
pandas_df(fields, filter, pd)
* Creates a dataframe from a list of ndlab classes
pandas_df_nl(list, pandas)
For how to specify the fields and filter parameters, see :py:mod:`ndlaborm`
Data model and programming
---------------------------
The Base for the classes representing the nuclear model is :py:class:`ndlab.NdmBase`.
Their instance variables are intialized with a json structure
that is passed to each of the instance variables of type :py:class:`ndlab.Quantity`
A set of functions then initialize these classes, querying the database
The :py:class:`ndlab.Property`, :py:class:`ndlab.Nominal`, :py:class:`ndlab.Quantity`,
:py:class:`ndlab.Operator` and :py:class:`ndlab.Unit`
implement the ISO Vocabulary (VIM)
https://www.iso.org/sites/JCGM/VIM/JCGM_200e_FILES/MAIN_JCGM_200e/Start_e.html
- The :py:class:`ndlab.Quantity` embeds the uncerainities propagation using the 'uncertainities' packages
(https://pythonhosted.org/uncertainties/).
- A Quantity is initialised with a json structure.
- The classes representing the model contain variables of type Quantity to store the data
"""
from __future__ import annotations
from gc import DEBUG_LEAK
from re import I
import io
import json
import copy
import ndlabdblink as dl
import sys
# the uncertainities (https://pythonhosted.org/uncertainties/)
from uncertainties import * #
this = sys.modules[__name__]
db_path = 'ndlab_db.s3db'
dblink = dl.Dblink(db_path)
_filter = ""
DEFAULT = "NO_PARAM";
last_fields = ''
last_filter = ''
CSV_SEP = ','
ERROR_FILTER_NOT_VALID = "Fields or Filter not valid, check the rules"
help = ("See https://iaea-nds.github.io/ndlab/interrogation.html on how to construct the fields and filter parameters\n\n"
"fields='GAMMA.NUC.Z, GAMMA.NUC.N, GAMMA.ENERGY'\n"
"filter='GAMMA.ENERGY > 560'\n\n"
"* Data in json format *\n"
"json_data(fields , filter) \n\n"
"* Data in csv format *\n"
"csv_data(fields , filter )\n\n"
"* Data in csv format from a list of ndlab classes *\n"
"csv_nl(nl_items)\n\n"
"* Creates a dataframe *\n"
"import pandas as pd\n"
"pandas_df(fields, filter, pd)\n\n"
"* Creates a dataframe from a list of ndlab classes *\n"
"pandas_df_nl(list, pandas)" )
if __spec__ is not None:
file_path = '''C:/other_file
trtrr'''
name = __spec__.name #'new_name'
__spec__.origin = file_path
if name != __spec__.name:
sys.modules[name] = sys.modules[__spec__.name]
__spec__.name = name
def _float_check(val):
""" Check if a value retrieved from the database is a float
Args:
val: (anything, most likey a string)
Returns:
float: the string converted to float
or
None: no conversion to float possible
"""
try:
return float(val)
except:
return None
def _int_check(val):
""" Check if a value retrieved from the database is an integer
Args:
val (int): The object to be converted
Returns:
integer: the string converted to integer
or
None: no conversion to float possible
"""
try:
return int(val)
except:
return None
def _str_check(val):
if (str(val) == 'None'):
return None
return val
[docs]class Property:
""" Models the ISO VIM
Upper class with only the name of the property
"""
def __init__(self, name = ''):
self.name = name
@property
def name(self):
"""
The name of the property
Returns:
String: name
"""
return self._name_
@name.setter
def name(self, name):
"""
Sets name of the property
Args:
name (str) : the name of the propery
"""
self._name_= name
[docs]class Nominal(Property):
""" Models the ISO VIM
Quantities without magnitude
"""
# value = None
def __init__(self, name = ''):
super(Nominal, self).__init__(name)
[docs]class Operator:
"""Qualifier of a value, e.g. >
Contains the allowed modifiers and the rules of composition to handle matemathical operations between quantities
"""
lt = "<"
gt = ">"
eq = "="
ge = ">="
le = "<="
approx = "~"
calculated = "CA"
problem = "?"
[docs] def compose(oa, ob):
""" Rule for operators composition
Args:
oa (Operator): operator of the first quantity
ob (Operator): operator of the second quantity
Returns:
Operator: oa composed with ob
"""
if(oa == Operator.eq and ob == Operator.eq):
return Operator.eq
if( (oa == Operator.lt or oa == Operator.le or oa == Operator.eq) and (ob == Operator.lt or ob == Operator.le or ob == Operator.eq)):
return Operator.lt
if( (oa == Operator.gt or oa == Operator.ge or oa == Operator.eq) and (ob == Operator.gt or ob == Operator.ge or ob == Operator.eq)):
return Operator.gt
# symmetric below
if( oa == Operator.approx and ob != Operator.eq):
return ob
if( oa == Operator.approx and ob == Operator.eq):
return oa
if( ob == Operator.approx and oa != Operator.eq):
return oa
if( ob == Operator.approx and oa == Operator.eq):
return ob
if(oa == Operator.calculated or ob == Operator.calculated):
return Operator.calculated
return Operator.problem
def test():
ll = [Operator.approx,Operator.eq, Operator.ge,Operator.gt,Operator.le,Operator.lt,Operator.problem]
for o1 in ll:
for o2 in ll:
print (o1, o2,Operator.compose(o1,o2))
[docs]class Unit:
"""Units of measure
"""
normalized = "normalized"
kev = "keV"
mev = "MeV"
amu = "AMU"
mu_amu = "micro AMU"
[docs]class Quantity(Nominal):
"""Models the ISO VIM and handles the uncertainties propagation with ufloat from the `uncertainties <https://pythonhosted.org/uncertainties/>`__ package
Attributes:
sep (string): The CSV separator to be used when dumping to CSV
:ivar string nominal: name
:ivar float value: float value
:ivar string unc: uncertainity as string
:ivar float unc_num: uncertainity as float
:ivar Operator: Operator
"""
sep = CSV_SEP
# name is the key to be used in populate
def __init__(self, name = ''):
super(Quantity, self).__init__(name)
self.value = None
self.unc_num = None
self.unc = None
self.operator = Operator.eq
def _populate(self,data):
"""using a json structure. Fills the instance variables from a json structure:
| value = data[{name}]
| unc = data[{name}_unc]
| operator = data[{name}_limit]
Args:
data (json): data structure to fill the instance variables
Returns:
self: instance of the class
"""
if self.name in data:
self.nominal = data[self.name ]
if(data[self.name] != 'None'):
self.value = _float_check(data[self.name])
if self.name + "_unc" in data:
self.unc = (data[self.name+ "_unc"])
if(data[self.name + "_unc"] != 'None'):
self.unc_num = _float_check(data[self.name + "_unc"])
else:
self.unc = "0"
self.unc_num = 0
if self.name + "_limit" in data:
self.operator = data[self.name + "_limit"]
if (self.operator == ''):
self.operator = Operator.eq
if self.value == None:
self.value = 0;
isnull = True
self.unc_num = 0 if self.unc_num == None else self.unc_num;
return self
[docs] def ufloat(self):
""" ufloat of the `uncertainties <https://pythonhosted.org/uncertainties/`__ package from :py:attr:`value` and :py:attr:`uncertainty`
"""
if(self.value is None):
return None
return ufloat(self.value, self.unc_num if self.unc_num is not None else 0)
[docs] def create( value, unc, operator = Operator.eq):
""" Creates a Quantity from a value, and uncertainty, and an operator.
Used internally from overloaded mathematical functions
Args:
value (float): value
unc (float): uncertainty
operator (Operator): operator
"""
q = Quantity()
q.value = value
q.unc = unc
q.unc_num = unc
q.operator = operator
return q
[docs] def csv(self):
"""Generates the CSV representation of the quantity
Returns:
String: the CSV
"""
return str(self.value) + self.sep + str(self.unc) + self.sep + str(self.operator )
def __add__(self,qtt):
op = Operator.eq
if(qtt.__class__.__name__ != "Quantity"):
sm = self.ufloat() + qtt
else:
sm = self.ufloat() + qtt.ufloat()
op = qtt.operator
return Quantity.create(sm.n, sm.s, Operator.compose(self.operator, op))
def __radd__(self,qtt):
return self + qtt
def __sub__(self,qtt):
op = Operator.eq
if(qtt.__class__.__name__ != "Quantity"):
sm = self.ufloat() - qtt
else:
sm = self.ufloat() - qtt.ufloat()
op = qtt.operator
return Quantity.create(sm.n, sm.s, Operator.compose(self.operator, op))
def __rsub__(self,qtt):
op = Operator.eq
if(qtt.__class__.__name__ != "Quantity"):
sm = qtt - self.ufloat()
else:
sm = qtt.ufloat() - self.ufloat()
op = qtt.operator
return Quantity.create(sm.n, sm.s, Operator.compose(self.operator, op))
def __mul__(self,qtt):
op = Operator.eq
if(qtt.__class__.__name__ != "Quantity"):
sm = self.ufloat() * qtt
else:
sm = self.ufloat() * qtt.ufloat()
op = qtt.operator
return Quantity.create(sm.n, sm.s, Operator.compose(self.operator, op))
def __rmul__(self,qtt):
op = Operator.eq
if(qtt.__class__.__name__ != "Quantity"):
sm = self.ufloat() * qtt
else:
sm = self.ufloat() * qtt.ufloat()
op = qtt.operator
return Quantity.create(sm.n, sm.s, Operator.compose(self.operator, op))
def __truediv__(self,qtt):
op = Operator.eq
if(qtt.__class__.__name__ != "Quantity"):
sm = self.ufloat() / qtt
else:
sm = self.ufloat() / qtt.ufloat()
op = qtt.operator
return Quantity.create(sm.n, sm.s, Operator.compose(self.operator, op))
def __rtruediv__(self,qtt):
op = Operator.eq
if(qtt.__class__.__name__ != "Quantity"):
sm = qtt / self.ufloat()
else:
sm = qtt.ufloat() / self.ufloat()
op = qtt.operator
return Quantity.create(sm.n, sm.s, Operator.compose(self.operator, op))
def __pow__(self,qtt):
op = Operator.eq
if(qtt.__class__.__name__ != "Quantity"):
if(qtt.__class__.__name__ != "Variable"):
sm = self.ufloat() ** ufloat(qtt,0)
else:
sm = self.ufloat() ** qtt
else:
sm = self.ufloat() ** qtt.ufloat()
op = qtt.operator
return Quantity.create(sm.n, sm.s, Operator.compose(self.operator, op))
def __lt__(self, other):
if(other.__class__.__name__ != "Quantity"):
return (self.ufloat() < other)
else:
return (self.ufloat() < other.ufloat())
def __le__(self, other):
if(other.__class__.__name__ != "Quantity"):
return (self.ufloat() <= other)
else:
return (self.ufloat() <= other.ufloat())
def __gt__(self, other):
if(other.__class__.__name__ != "Quantity"):
return (self.ufloat() > other)
else:
return (self.ufloat() > other.ufloat())
def __ge__(self, other):
if(other.__class__.__name__ != "Quantity"):
return (self.ufloat() >= other)
else:
return (self.ufloat() >= other.ufloat())
def __eq__(self, other):
if(other.__class__.__name__ != "Quantity"):
return (self.ufloat() == other)
else:
return (self.ufloat() == other.ufloat())
def __ne__(self, other):
if(other.__class__.__name__ != "Quantity"):
return (self.ufloat() != other)
else:
return (self.ufloat() != other.ufloat())
def __str__(self):
return ("" if self.operator == Operator.eq else self.operator) + " " + str(self.ufloat())
class Ndm_base():
"""Base class of the Nuclar Data Model
Attributes:
_csv_title (str): the title of the csv representation of this class
"""
_csv_title = ''
def __init__(self):
self.myfilter = ''
self.pk = ''
def _populate(self,data):
""" takes a json structure and populates the Quantities of this class, as well as the other variables
"""
pass
def _join_filter(self,filter, fk_filter):
"""Joins the filter specified by the user with the foreign key to follow the link to another class.
For example
if nuc = nuclide("135XE")
nuc.levels("LEVEL.JP = '2+') has an explict filter for JP, but also an embedded foreign key to reach only 135XE
Args:
filter (str): the user-specified filter
fk_filter (str): the foreign key to be added
Returns:
String: the joined flters
"""
_filter = ""
if(filter != ''):
_filter = filter
if(_filter != '' and self.myfilter != ''):
_filter = filter + " AND " + self.myfilter
else:
_filter = self.myfilter
idx = _filter.find("ORDER")
if(idx > 0):
_filter = _filter[0 : idx]
if(_filter != '' and fk_filter != ''):
_filter = _filter + " AND " + fk_filter
else:
_filter = fk_filter
return _filter
def _check_filter(self,filter, prev_filter):
""" to handle the case when a property was first called with a filter, then without
Args:
filter (str): the new filter (DEFAULT means no filter specified)
prev_filter (str): the previous filter, if any
Returns:
str: the filter to be applied
"""
# without a filter, and it is the first call
if(filter == DEFAULT and prev_filter == None):
filter = ''
# without a filter, but previously a filter was set
elif(filter == DEFAULT and prev_filter != None):
filter = prev_filter
return filter
def _property_filler(self, property_name, func_name, filter, fk_filter, skip_prev_filter=False):
"""intialises an instance variable, like :py:meth:`ndlab.Nuclide.levels` for a :py:class:`ndlab.Nuclide`
It uses reflection, the name of the variable to be set, the name of the function that
does the actual retrieval of the data, and the filter to be applied.
Lazy creation : returns the existig value if the property is already filled and the filter has not changed
Args:
property_name (str): name of the property to be intialised
func_name (str): name of the function in this module that performs the task
filter (str): filter passed to the function by the user
fk_filter (str): str: foreign key(s) to be appended to the filter
skip_prev_filter (bool) : False , do not append the exisiting filter
Returns:
object: the instance variable intialised
"""
if(filter == DEFAULT): filter = ""
# pointer to the property from its name
property = getattr(self,property_name)
# pointer to the previous filter from its name
prev_filter = getattr(self,(property_name + "_filter"))
# whether the filter has changed
filter = filter if skip_prev_filter else self._check_filter(filter, prev_filter)
# lazy creator: only if not assigned yet, or if the filter has chenged
if(property == None or prev_filter != filter ):
# pointer to the function from its name
function = getattr(this,func_name)
# assign the result to the property
#property = function(self._join_filter(filter, fk_filter))
property = function( filter + ("" if filter == "" else " AND ") + fk_filter)
# attach property to the instance, otherwise it is local
setattr(self, property_name, property)
# set the new filter
setattr(self, (property_name + "_filter"), filter)
return property
def csv(self):
""" Generates a String with the CSV representation for an instance of class
the attribute _cst_title stores the first row of the csv with the field names
Returns:
string: the csv
"""
sep = CSV_SEP
ret = ""
fields = self._csv_title.split(CSV_SEP)
for field in fields:
if(field.endswith("_unc")):
continue
attr = getattr(self, field, "stop")
if(attr != "stop"):
if(isinstance( attr, Quantity)):
ret += sep + attr.csv()
else:
ret += sep + str(attr)
else:
pass
# print("null " ,field, attr)
return ret[1:]
[docs]class Nuclide(Ndm_base):
"""The properties of given Z and N pair
Note that properties like Half-life, etc are to be accessed through its ground state (gs)
:ivar int z: number of protons
:ivar int n: number of neutrons
:ivar str nucid: nuclide id mass + element symbol 135XE
:ivar Quantity charge_radius: charge radius
:ivar Quantity atomic_mass: atomic mass
:ivar Quantity mass_excess: mass excess
:ivar Quantity binding_en: binding en
:ivar Quantity beta_decay_en: beta decay energy
:ivar Quantity s2n: 2-neutron separation energy
:ivar Quantity s2p: 2-protons separation energy
:ivar Quantity qa: Q-value for alpha decay
:ivar Quantity abundance: natural abundance in mole fraction
:ivar Level gs: ground state
:ivar Nuclide[] daughters: direct daughters of the nuclide, including excited states decays
:ivar Nuclide[] parents: parents of the nuclide
:ivar Nuclide[] daughters_chain: all possible offsprings of the nuclide
:ivar Nuclide[] parents_chain: all possible ancestors of the nuclide
:ivar Decay[] decays: all decays, including fron metastable states, for which decay radiations are given
"""
_csv_title = "z,n,nucid,elem_symbol,charge_radius,charge_radius_unc,charge_radius_limit,atomic_mass,atomic_mass_unc,atomic_mass_limit,mass_excess,mass_excess_unc,mass_excess_limit,binding_en,binding_en_unc,binding_en_limit,qbm,qbm_unc,qbm_limit,qa,qa_unc,qa_limit,qec,qec_unc,qec_limit,sn,sn_unc,sn_limit,sp,sp_unc,sp_limit,qbmn,qbmn_unc,qbmn_limit,abundance,abundance_unc,abundance_limit"
def __init__(self):
super().__init__()
self.z = None
self.n = None
self.nucid = None
self.elem_symbol = None
self.charge_radius = Quantity("charge_radius")
self.atomic_mass = Quantity("atomic_mass")
self.mass_excess = Quantity("mass_excess")
self.binding_en = Quantity("binding_en")
self.qbm = Quantity("beta_decay_en")
self.s2n = Quantity("s2n")
self.s2p = Quantity("s2p")
self.qa = Quantity("qa")
self.qbmn = Quantity("qbmn")
self.sn = Quantity("sn")
self.sp = Quantity("sp")
self.qec = Quantity("qec")
self.abundance = Quantity("abundance")
self._levels = None
self._levels_filter = None
self._gammas = None
self._gammas_filter = None
self._dr_photons = None
self._dr_photons_filter = None
self._daughters = None
self._parents = None
self._decays = None
def _populate(self,data):
self.z = _int_check(data["z"])
self.n = _int_check(data["n"])
self.nucid = data["nucid"]
self.elem_symbol = data["elem_symbol"]
self.charge_radius._populate(data)
self.atomic_mass._populate(data)
self.mass_excess._populate(data)
self.binding_en._populate(data)
self.qbm._populate(data)
self.s2n._populate(data)
self.s2p._populate(data)
self.qa._populate(data)
self.qbmn._populate(data)
self.sn._populate(data)
self.sp._populate(data)
self.qec._populate(data)
self.abundance._populate(data)# = _float_check(data["abundance"])
self.pk = self.nucid
[docs] def levels(self, filter=DEFAULT):
"""Energy levels of this nuclide
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`NUCLIDE <NUCLIDE>` entity
Returns:
the list of :py:class:`ndlab.Level` of this nuclide
"""
return self._property_filler("_levels","levels", filter, " LEVEL.NUC_ID = '" + self.nucid + "' ORDER BY LEVEL.SEQNO" )
[docs] def gammas(self, filter=DEFAULT):
"""Gamma transitions between levels of this nuclide
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`NUCLIDE <NUCLIDE>` entity
Returns:
the list of :py:class:`ndlab.Gamma` of this nuclide
"""
return self._property_filler("_gammas","gammas", filter, " GAMMA.NUC_ID = '" + self.nucid + "' ORDER BY GAMMA.START_LEVEL_SEQNO , GAMMA.SEQNO" , True)
@property
def daughters(self):
if(self._daughters == None):
self._daughters = this._generator("L_DECAY.DAUGHTER.ALL", "Nuclide", "L_DECAY.NUC_ID = '" + self.nucid + "' " )
return self._daughters
@property
def parents(self):
if(self._parents == None):
self._parents = this._generator("L_DECAY.NUC.ALL", "Nuclide", "L_DECAY.DAUGHTER_NUC_ID = '" + self.nucid + "' " )
return self._parents
@property
def decays(self):
if(self._decays == None):
self._decays = this._generator("L_DECAY.ALL", "L_decay", " L_DECAY.NUC_ID = '" + self.nucid + "' ORDER BY L_DECAY.LEVEL_SEQNO , L_DECAY.MODE" ) #DECAY_RAD.PARENT_NUC_ID = L_DECAY.NUC_ID and
return self._decays
@property
def gs(self):
mygs = self.levels( " LEVEL.SEQNO = 0 ")
if(len(mygs) > 0):
return self.levels( " LEVEL.SEQNO = 0 ")[0]
return None
@property
def daughters_chain(self):
offs =[]
dau_ids = self._offsprings(self)
for nid in dau_ids:
offs.append(nuclide(nid))
return offs
@property
def parents_chain(self):
pars =[]
par_ids = self._ancestors(self)
for nid in par_ids:
pars.append(nuclide(nid))
return pars
def _offsprings(self, nuc, offsprings = []):
_daugs = nuc.daughters # direct daughters
go = False # turns true when anything new is added
for d in _daugs: # loop on direct daughters
if not d.nucid in offsprings: # if not already added, add to the list
offsprings.append(d.nucid)
go = True # nuclide added, need to call again
if(not go): return offsprings # nothing added, stop here
# after the first call of daughter_chain, when called again the offstring param still has the previous value - why ?
for d in _daugs:
self._offsprings(d, offsprings)
return offsprings
def _ancestors(self, nuc, allpars = []):
_pars = nuc.parents
go = False # if anythinks new is added
for d in _pars:
if not d.nucid in allpars:
allpars.append(d.nucid)
go = True
if(not go): return allpars
for d in _pars:
self._ancestors(d, allpars)
return allpars
[docs]class Level(Ndm_base):
"""Properties of an energy eigenstate of a Nuclide
z, n, and nucid are for convenience. The can be accessed also through the 'nuclide' property
:ivar int z: number of protons of the nuclide
:ivar int n: number of neutron of the nuclide
:ivar string nucid: nuclide's indentifier, e.g. 135XE
:ivar int l_seqno: sequential number or the level, 0 being the g.s.
:ivar Quantity energy: energy in keV
:ivar Quantity half_life: H-l in the units given by the evaluation
:ivar string half_life_units: units given by the evaluation
:ivar Quantity half_life_sec: H-l given in seconds
:ivar string jp_str: Jp given in the evaluation
:ivar int jp_order: occurrence of this Jp value, 0 being the one closest to the g.s.
:ivar float j: Angular momentum assignment given by :ref:`RIPL <jp-label>`
:ivar int parity: parity assignment given by :ref:`RIPL <jp-label>`
:ivar string jp_method: method of jp assignment by :ref:`RIPL <jp-label>`
:ivar Quantity quadrupole_em: Quadrupole electric moment in barn
:ivar Quantity dipole_mm: Dipole magnetic moment in nuclear magnetons
:ivar string questionable: whether the existence is questionable
:ivar string configuration: nuclear configuration
:ivar string isospin: isospin
:ivar Nuclide nuclide: access to the nuclide
:ivar Nuclide[] daughters: the direct daughters of the level decay, if any
"""
_csv_title = "z,n,nucid,l_seqno,energy,energy_unc,energy_limit,half_life,half_life_unc,half_life_limit,half_life_units,half_life_sec,half_life_sec_unc,half_life_sec_limit,j,parity,jp_order,jp_method,jp_str,quadrupole_em,quadrupole_em_unc,quadrupole_em_limit,dipole_mm,dipole_mm_unc,dipole_mm_limit,questionable,configuration,isospin"
def __init__(self):
super().__init__()
self.z = None
self.n = None
self.nucid = None
self.l_seqno = None
self.energy = Quantity("energy")
self.half_life = Quantity("half_life")
self.half_life_units = None
self.half_life_sec = Quantity("half_life_sec")
self.j = None
self.jp_str = None
self.parity = None
self.jp_order = None
self.jp_method = None
self.quadrupole_em = Quantity("quadrupole_em")
self.dipole_mm = Quantity("dipole_mm")
self.questionable = None
self.configuration = None
self.isospin = None
self._nuclides = None
self._daughters = None
self._gammas = None
self._gammas_filter = None
self._l_decays = None
self._l_decays_filter = None
def _populate(self,data):
self.z = _int_check(data["z"])
self.n = _int_check(data["n"])
self.nucid = data["nucid"]
self.l_seqno = _int_check(data["l_seqno"])
self.energy._populate(data)
self.half_life._populate(data)
self.half_life_units = data["half_life_units"]
self.half_life_sec._populate(data)
self.jp_str = _str_check(data["jp_str"])
self.j = _str_check(data["j"])
self.parity = _int_check(data["parity"])
self.jp_order = _int_check(data["jp_order"])
self.jp_method = _int_check(data["jp_method"])
self.quadrupole_em._populate(data)
self.dipole_mm._populate(data)
self.questionable = _str_check(data["questionable"])
self.configuration = _str_check( data["configuration"])
self.isospin = _str_check( data["isospin"])
self.pk = self.nucid + '-' + str(self.l_seqno)
@property
def nuclide(self):
if(self._nuclides == None):
self._nuclides = this._generator("NUCLIDE", "Nuclide", " NUCLIDE.NUC_ID = '" + self.nucid + "' ")
return self._nuclides[0]
@property
def daughters(self):
if(self._daughters):
return self._daughters
self._daughters = []
for d in self.decays():
self._daughters.append(d.daughter)
return self._daughters
[docs] def gammas(self, filter=DEFAULT):
"""Gamma transitions starting from this level
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`LEVEL <LEVEL>` entity
Returns:
the list of :py:class:`ndlab.Gamma` starting from this level
"""
return self._property_filler("_gammas","gammas", filter, " GAMMA.NUC_ID = '" + self.nucid + "' and GAMMA.START_LEVEL_SEQNO = " + str(self.l_seqno) + " ORDER BY GAMMA.SEQNO")
[docs] def decays(self, filter=DEFAULT):
"""Decay modes of this level
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`NUCLIDE <NUCLIDE>` entity
Returns:
the list of :py:class:`ndlab.L_decays` of this level
"""
return self._property_filler("_l_decays","l_decays", filter, " L_DECAY.NUC_ID = '" + self.nucid + "' and L_DECAY.LEVEL_SEQNO = " + str(self.l_seqno), True )
[docs]class L_decay(Ndm_base):
"""Decay process
Description of a level decay: parent, daughter, radiations, etc...
nucid , l_seqno, and daughter_nucid are for convenience. The can be accessed also through the 'nuclide', 'daughter', and 'level' properties, respectively
:ivar string nucid: decaying nuclide indentifier, e.g. 135XE
:ivar int l_seqno: sequential number or the decaying level, 0 being the g.s.
:ivar string daughter_nucid: daughter nuclide indentifier, e.g. 135XE
:ivar Quantity perc: decays per 100 decay of the parent
:ivar Nuclide nuclide: the parent nuclide
:ivar Level level: the parent level
:ivar Nuclide[] daughters: the direct daughters of the decay
:ivar Nuclide nuclide: the parent nuclide
:ivar Decay_mode mode: the decay mode
:ivar Quantity toten_recoil: total recoil energy [keV]
:ivar Quantity q_togs: Q-value [keV]
"""
_csv_title = "z,n,nucid,l_seqno,code,daughter_nucid,z_dau,n_dau,perc,perc_unc,perc_limit,q_togs,q_togs_unc,q_togs_limit"
def __init__(self):
super().__init__()
self.nucid = None
self.l_seqno = None
self.code = None
self.daughter_nucid = None
self.perc = Quantity("perc")
self._en_recoil = Quantity("recoil_tot_en")
self.q_togs = Quantity("q_togs")
self._gamma = None
self._gamma_filter = None
self._alpha = None
self._alpha_filter = None
self._annihil = None
self._annihil_filter = None
self._betam = None
self._betam_filter = None
self._anti_nu = None
self._anti_nu_filter = None
self._betap = None
self._betap_filter = None
self._annhils = None
self._annhils_filter = None
self._nu = None
self._nu_filter = None
self._x = None
self._x_filter = None
self._ce = None
self._ce_filter = None
self._auger = None
self._auger_filter = None
self._photon_tot = None
self._photon_tot_filter = None
self._nuclide = None
self._levels = None
self._daughters = None
self._mode = None
def _populate(self,data):
self.z = _int_check(data["z"])
self.n = _int_check(data["n"])
self.nucid = data["nucid"]
self.l_seqno = _int_check(data["l_seqno"])
self.code = _int_check(data["decay_code"])
self.daughter_nucid = data["daughter_nucid"]
self.z_dau = _int_check(data["z_dau"])
self.n_dau = _int_check(data["n_dau"])
self.perc._populate(data)
self._en_recoil._populate(data)
self.q_togs._populate(data)
self.pk = self.nucid + '-' + str(self.l_seqno) + '-' + str(self.code)
self._sql_decrad = " DECAY_RAD.PARENT_NUC_ID = '" + self.nucid + "' and DECAY_RAD.PARENT_LEVEL_SEQNO = " + str(self.l_seqno) + " and DECAY_RAD.MODE = " + str(self.code) + " ORDER BY DECAY_RAD.ENERGY"
[docs] def gammas(self, filter=DEFAULT):
"""Gamma radiation from this decay
The radiation is emitted by the daughter
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_GAMMA <DR_GAMMA>` entity
Returns:
the list of :py:class:`ndlab.Dr_gamma` from this decay
"""
return self._property_filler("_gamma","dr_gammas", filter, " DR_GAMMA.PARENT_NUC_ID = '" + self.nucid + "' and DR_GAMMA.PARENT_LEVEL_SEQNO = " + str(self.l_seqno) + " and DR_GAMMA.MODE = " + str(self.code) + " ORDER BY DR_GAMMA.SEQNO")
[docs] def alphas(self, filter=DEFAULT):
"""Alpha radiation from this decay
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_ALPHA <DR_ALPHA>` entity
Returns:
the list of :py:class:`ndlab.Dr_alpha` from this decay
"""
return self._property_filler("_alpha","dr_alphas", filter, self._sql_decrad )
def annihil(self, filter=DEFAULT):
"""Annihilation radiation
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_ANNIHIL <DR_ANNIHIL>` entity
Returns:
the list of :py:class:`ndlab.Dr_annihil` from this decay
"""
return self._property_filler("_annihil","dr_annihil", filter, self._sql_decrad )
[docs] def betas_m(self, filter=DEFAULT):
"""Beta- radiation from this decay
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_BETAM <DR_BETAM>` entity
Returns:
the list of :py:class:`ndlab.Dr_betam` from this decay
"""
return self._property_filler("_betam","dr_beta_ms", filter, self._sql_decrad )
[docs] def anti_nus(self, filter=DEFAULT):
"""Anti neutrino radiation from this decay
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_ANTI_NU <DR_ANTI_NU>` entity
Returns:
the list of :py:class:`ndlab.Dr_anti_nu` from this decay
"""
return self._property_filler("_anti_nu","dr_anti_nus", filter, self._sql_decrad )
[docs] def nus(self, filter=DEFAULT):
"""Neutrino radiation from this decay
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_NU <DR_NU>` entity
Returns:
the list of :py:class:`ndlab.Dr_Nu` from this decay
"""
dm = self._property_filler("_nu","dr_nus", filter, self._sql_decrad )
#ddm = copy.deepcopy(dm)
#for d in dm:
# dd = copy.deepcopy(d)
# dd.energy = d.energy_ec
# dd.intensity = d.intensity_ec
# ddm.append(dd)
#self._nu = ddm
self._nu = dm
return self._nu
[docs] def betas_p(self, filter=DEFAULT):
"""Beta+ radiation from this decay
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_BETAP <DR_BETAP>` entity
Returns:
the list of :py:class:`ndlab.Dr_betap` from this decay
"""
return self._property_filler("_betap","dr_beta_ps", filter, self._sql_decrad )
[docs] def annihil(self, filter=DEFAULT):
"""Annihilation radiation from this decay
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_ANNIHIL <DR_ANNIHIL>` entity
Returns:
the list of :py:class:`ndlab.Dr_annihil` from this decay
"""
return self._property_filler("_annhils","dr_annihil", filter, self._sql_decrad )
[docs] def dr_photon_tot(self, filter=DEFAULT):
"""Photons emitted in the decay process, if any, regardless of the daughter or the radiation type (X- or Gamma- ray)
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_PHOTON_TOTAL <DR_PHOTON_TOTAL>` entity
Returns:
the list of :py:class:`ndlab.Dr_photon_tot` from this decay
"""
return self._property_filler("_photon_tot","dr_photon_tot", filter, " DR_PHOTON_TOTAL.PARENT_NUC_ID = '" + self.nucid + "' and DR_PHOTON_TOTAL.PARENT_LEVEL.SEQNO = " + str(self.l_seqno) + " ORDER BY DR_PHOTON_TOTAL.ENERGY" , True )
@property
def nuclide(self):
if(self._nuclide == None):
self._nuclide = this._generator("NUCLIDE", "Nuclide", " NUCLIDE.NUC_ID = '" + self.nucid + "' " )
if(self._nuclide != None and len(self._nuclide) > 0):
self._nuclide = self._nuclide[0]
return self._nuclide
@property
def level(self):
if(self._levels == None):
self._levels = this._generator("LEVEL", "Levels", " LEVEL.NUC_ID = '" + self.nucid + "' and LEVEL.SEQNO = " + self.l_seqno)
return self._levels
@property
def daughter(self):
if(self._daughters == None):
self._daughters = this._generator("NUCLIDE", "Nuclide", " NUCLIDE.NUC_ID = '" + self.daughter_nucid + "' ")
return self._daughters[0]
@property
def mode(self):
if(self._mode == None):
self._mode = this._generator("DECAY_MODE","Decay_mode" ," DECAY_MODE.CODE = '" + str(self.code) + "' ")
return self._mode[0]
@property
def toten_recoil(self):
return self._en_recoil
[docs] def xs(self, filter=DEFAULT):
"""X-rays radiation from this decay
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_X <DR_X>` entity
Returns:
the list of :py:class:`ndlab.Dr_x` from this decay
"""
return self._property_filler("_x","dr_xs", filter, self._sql_decrad )
[docs] def convels(self, filter=DEFAULT):
"""Conversion electrons from this decay
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_CONV_EL <DR_CONV_EL>` entity
Returns:
the list of :py:class:`ndlab.dr_conv_el` from this decay
"""
return self._property_filler("_ce","dr_convels", filter, self._sql_decrad )
[docs] def augers(self, filter=DEFAULT):
"""Auger electrons from this decay
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_AUGER <DR_AUGER>` entity
Returns:
the list of :py:class:`ndlab.Dr_auger` from this decay
"""
return self._property_filler("_auger","dr_augers", filter, self._sql_decrad )
[docs] def tot_rad_en(self, radiations):
""" Energy emitted by a set of radiations
calculated as energy * intensity / 100
Args:
radiations (Decay_radiation): list of any decay radiations
Returns:
Quantity: the energy
"""
if(radiations == None or len(radiations)==0):
return ufloat(0,0);
return sum([radiations[i].energy * radiations[i].intensity for i in range(len(radiations))])/100
[docs] def tot_measured_en(self):
""" Total energy emitted per 100 decays of the parent
calculated as sum (energy * intensity / 100 ) over all radiations
Returns:
Quantity: the total energy
"""
rads = [self.xs(), self.gammas(), self.convels(), self.augers(), self.alphas(), self.betas_m(), self.betas_p(), self.nus(), self.anti_nus(), self.annihil()]
sm = []
for r in rads:
sm.append(self.tot_rad_en(r))
sm.append(self.toten_recoil)
return sum(sm)
[docs]class Gamma(Ndm_base):
"""Electromagnetic transition between levels of the same nuclide
z, n, and nucid can be accessed also through the 'nuclide' property. l_seqno can be accessed though the 'level' property
:ivar int z: number of protons of the nuclide
:ivar int n: number of neutron of the nuclide
:ivar string nucid: nuclide's indentifier, e.g. 135XE
:ivar int l_seqno: sequential number of the start level, 0 being the g.s.
:ivar int g_seqno: sequential number of this gamma within the start level gammas, 0 being the lowest energy one
:ivar Nuclide nuclide: the nuclide
:ivar Level start_level: the start level
:ivar Level end_level: the start level
:ivar Quantity energy: energy [keV]
:ivar Quantity rel_photon_intens: relative photon intensity %
:ivar string multipolarity: multipolarity
:ivar Quantity mixing_ratio: mixing ratio
:ivar Quantity tot_conv_coeff: total conversion coefficient
:ivar Quantity bew: reduced electric transition probabilities in Weisskopf units
:ivar Quantity bew_order: bew order
:ivar Quantity bmw: reduced magnetic transition probabilities in Weisskopf units
:ivar Quantity bmw_order: bmx order
:ivar string questionable: whether the existence is questionable
"""
_csv_title = 'z,n,nucid,g_seqno,l_seqno,energy,energy_unc,energy_limit,rel_photon_intens,rel_photon_intens_unc,rel_photon_intens_limit,multipolarity,mixing_ratio,mixing_ratio_unc,mixing_ratio_limit,tot_conv_coeff,tot_conv_coeff_unc,tot_conv_coeff_limit,bew,bew_unc,bew_limit,bew_order,bmw,bmw_unc,bmw_limit,bmw_order,questionable,final_l_seqno'
def __init__(self):
super().__init__()
self.z = None
self.n = None
self.nucid = None
self.g_seqno = None
self.l_seqno = None
self.energy = Quantity("energy")
self.rel_photon_intens = Quantity("rel_photon_intens")
self.multipolarity = None
self.mixing_ratio = Quantity("mixing_ratio")
self.tot_conv_coeff = Quantity("tot_conv_coeff")
self.bew = Quantity("bew")
self.bew_order = None
self.bmw = Quantity("bmw")
self.bmw_order = None
self.questionable = None
self.final_l_seqno = None
self._nuclides = None
self._start_level = None
self._end_level = None
@property
def nuclide(self):
if(self._nuclides == None):
self._nuclides = this._generator("NUCLIDE", "Nuclide", " NUCLIDE.NUC_ID = '" + self.nucid + "' ")
return self._nuclides[0]
@property
def start_level(self):
if(self._start_level == None):
self._start_level = this._generator("LEVEL", "Level", " LEVEL.NUC_ID = '" + self.nucid + "' and LEVEL.SEQNO = " + str(self.l_seqno))
return self._start_level
@property
def end_level(self):
if(self._end_level == None):
self._end_level = this._generator("LEVEL", "Level", " LEVEL.NUC_ID = '" + self.nucid + "' and LEVEL.SEQNO = " + str(self.final_l_seqno))
if(self._end_level != None): self._end_level = self._end_level[0]
return self._end_level
def _populate(self,data):
self.z = _int_check(data["z"])
self.n = _int_check(data["n"])
self.nucid = data["nucid"]
self.g_seqno = _int_check(data["g_seqno"])
self.l_seqno = _int_check(data["l_seqno"])
self.energy._populate(data)
self.rel_photon_intens._populate(data)
self.multipolarity = _str_check(data["multipolarity"])
self.mixing_ratio._populate(data)
self.tot_conv_coeff._populate(data)
self.bew._populate(data)
self.bew_order = _int_check(data["bew_order"])
self.bmw._populate(data)
self.bmw_order = _int_check(data["bmw_order"])
self.questionable = _str_check(data["questionable"])
self.final_l_seqno = _int_check(data["final_l_seqno"])
self.pk = self.nucid + '-' + str(self.l_seqno) + '-' + str(self.g_seqno)
[docs]class Decay_radiation(Ndm_base):
"""Base class for decay radiations
Its Attributes are inherited by all the Dr_* classes describing each type of radiation
parent_nucid , parent_l_seqno, daughter_nucid, and daughter_l_seqno are for convenience. The can be accessed also through the 'nuclide', 'daughter', and 'level' properties, respectively
:ivar Nuclide parent: the parent nuclide
:ivar Nuclide daughter: the daughter nuclide
:ivar Level parent_level: the parent level
:ivar Level fed_level: the daughter level populated by the decay
:ivar L_decay decay: access to the level decay, with all the other radiations emitted
:ivar Quantity energy: energy [keV]
:ivar Quantity intensity: for 100 decays of the parent
:ivar string parent_nucid: parent nuclide indentifier, e.g. 135XE
:ivar int parent_l_seqno: sequential number or the parent level, 0 being the g.s.
:ivar string daughter_nucid: daughter nuclide indentifier, e.g. 135XE
:ivar int daughter_l_seqno: sequential number or the daughter level populated, 0 being the g.s.
:ivar int decay_code: code of the decay, see the DECAY_* constants in ndlaborm
"""
_csv_title = 'parent_nucid,parent_l_seqno,parent_z,parent_n,daughter_nucid,daughter_z,daughter_n,daughter_l_seqno,adopted_daughter_g_seqno,decay_code,type_a,type_b,type_c,ec_energy,ec_energy_unc,ec_energy_limit,bpec_intensity,bpec_intensity_unc,bpec_intensity_limit,ec_intensity,ec_intensity_unc,ec_intensity_limit,b_logft,b_logft_unc,b_logft_limit,intensity,intensity_unc,intensity_limit,b_trans_type,energy,energy_unc,energy_limit,a_hindrance,a_hindrance_unc,a_hindrance_limit,b_endpoint,b_endpoint_unc,b_endpoint_limit,d_energy_x,d_energy_x_unc,d_energy_x_limit,r_seqno,energy_nu,energy_nu_unc,energy_nu_limit'
_csv_title_short = 'parent_nucid,parent_l_seqno,parent_z,parent_n,daughter_nucid,daughter_z,daughter_n,daughter_l_seqno,energy,energy_unc,energy_limit,intensity,intensity_unc,intensity_limit'
# adopted_daughter_g_seqno,decay_code,type_a,type_b,type_c,ec_energy,ec_energy_unc,ec_energy_limit,bpec_intensity,bpec_intensity_unc,bpec_intensity_limit,ec_intensity,ec_intensity_unc,ec_intensity_limit,b_logft,b_logft_unc,b_logft_limit,intensity,intensity_unc,intensity_limit,b_trans_type,energy,energy_unc,energy_limit,a_hindrance,a_hindrance_unc,a_hindrance_limit,b_endpoint,b_endpoint_unc,b_endpoint_limit,d_energy_x,d_energy_x_unc,d_energy_x_limit,r_seqno,energy_nu,energy_nu_unc,energy_nu_limit'
def __init__(self):
super().__init__()
self.parent_nucid = None
self.parent_l_seqno = None
self.daughter_nucid = None
self.daughter_l_seqno = None
self.decay_code = None
self.type_a = None
self.type_b = None
self.type_c = None
self.intensity = Quantity("intensity")
self.energy = Quantity("energy")
self.r_seqno = None
self._parent = None
self._daughter = None
self._fed_level = None
self._start_level = None
self._decay = None
def _populate(self,data):
self.parent_nucid = data["parent_nucid"]
self.parent_l_seqno = _int_check(data["parent_l_seqno"])
self.parent_z = _int_check(data["z"])
self.parent_n = _int_check(data["n"])
self.daughter_nucid = data["daughter_nucid"]
self.daughter_l_seqno = _int_check(data["adopted_daughter_l_seqno"])
self.daughter_z = _int_check(data["z_dau"])
self.daughter_n = _int_check( data["n_dau"])
self.decay_code = _int_check(data["decay_code"])
self.type_a = data["type_a"]
self.type_b = data["type_b"]
self.type_c = data["type_c"]
self.intensity._populate(data)
self.energy._populate(data)
self.r_seqno = _int_check(data["r_seqno"])
self.pk = str(self.r_seqno)
@property
def parent(self):
if(self._parent == None):
self._parent = this._generator("NUCLIDE", "Nuclide", " NUCLIDE.NUC_ID = '" + self.parent_nucid + "' ")
return self._parent[0]
@property
def daughter(self):
if(self._daughter == None):
self._daughter = this._generator("NUCLIDE", "Nuclide", " NUCLIDE.NUC_ID = '" + self.daughter_nucid + "' ")
return self._daughter[0]
@property
def fed_level(self):
if(self._fed_level == None):
self._fed_level = this._generator("LEVEL", "Level", " LEVEL.NUC = '" + self.daughter_nucid + "' and LEVEL.SEQNO = " + str(self.daughter_l_seqno) + " ")
return self._fed_level[0]
@property
def parent_level(self):
if(self._parent_level == None):
self._parent_level = this._generator("LEVEL", "Level", " LEVEL.NUC = '" + self.parent_nucid + "' and LEVEL.SEQNO = " + str(self.parent_l_seqno) + " ")
return self._parent_level[0]
@property
def decay(self):
if(self._decay == None):
self._decay = this._generator("L_DECAY","L_decay", " L_DECAY.NUC = '" + self.parent_nucid + "' and L_DECAY.LEVEL = " + str(self.parent_l_seqno) + " and L_DECAY.CODE = " +str(self.decay_code) + " ")
return self._decay[0]
class Decay_mode(Ndm_base):
def __init__(self):
super().__init__()
self.name = None
self.code = None
self.desc = None
#self.ensdf_code = None
#self.decay_code = None
#self.dataset_code = None
def _populate(self,data):
self.name = data["mode"]
self.code = _int_check(data["code"])
self.desc = data["desc"]
self.pk = str(self.code)
class _Fy(Ndm_base):
"""Base class for Fission yields
:ivar Nuclide parent: the fissioning nuclide
:ivar Nuclide daughter: the product nuclide
:ivar Quantity thermal: thermal neutron fission yield
:ivar Quantity fast: fast neutron fission yield
:ivar Quantity mev_14: 14 MeV neutron fission yield
"""
_csv_title = "parent_nucid,daughter_nucid,l_seqno,thermal,thermal_unc,thermal_limit,fast,fast_unc,fast_limit,mev_14,mev_14_unc,mev_14_limit"
def __init__(self):
super().__init__()
self.parent_nucid = None
self.daughter_nucid = None
self.l_seqno = None
self.thermal = Quantity('ther_yield')
self.fast = Quantity('fast_yield')
self.mev_14 = Quantity('mev_14_yield')
self._parent = None
self._daughter = None
def _populate(self,data):
self.parent_nucid = data["parent_nucid"]
self.daughter_nucid = data["daughter_nucid"]
self.l_seqno = _int_check(data["l_seqno"])
self.thermal._populate(data)
self.fast._populate(data)
self.mev_14._populate(data)
self.pk = self.parent_nucid + '-' + self.daughter_nucid + '-' + str(self.l_seqno)
@property
def parent(self):
if(self._parent == None):
self._parent = this._generator("NUCLIDE", "Nuclide", " NUCLIDE.NUC_ID = '" + self.parent_nucid + "' ")
return self._parent[0]
@property
def daughter(self):
if(self._daughter == None):
self._daughter = this._generator("NUCLIDE", "Nuclide", " NUCLIDE.NUC_ID = '" + self.daughter_nucid + "' ")
return self._daughter[0]
[docs]class Cum_fy(_Fy):
"""Cumulative fission yield
:ivar Nuclide parent: the fissioning nuclide
:ivar Nuclide daughter: the product nuclide
:ivar Quantity thermal: thermal neutron fission yield
:ivar Quantity fast: fast neutron fission yield
:ivar Quantity mev_14: 14 MeV neutron fission yield
"""
def __init__(self):
super().__init__()
def _populate(self,data):
super()._populate(data)
[docs]class Ind_fy(_Fy):
"""Independent fission yield
:ivar Nuclide parent: the fissioning nuclide
:ivar Nuclide daughter: the product nuclide
:ivar Quantity thermal: thermal neutron fission yield
:ivar Quantity fast: fast neutron fission yield
:ivar Quantity mev_14: 14 MeV neutron fission yield
"""
def __init__(self):
super().__init__()
def _populate(self,data):
super()._populate(data)
[docs]class Dr_alpha(Decay_radiation):
"""Alpha decay radiation
Inherits all the attributes of :py:class:`Decay_radiation`
:ivar Quantity hindrance: hindrance factor
"""
_csv_title = Decay_radiation._csv_title_short + ",hindrance,hindrance_unc,hindrance_limit"
def __init__(self):
super().__init__()
self.hindrance = Quantity("a_hindrance")
def _populate(self,data):
super()._populate(data)
self.hindrance._populate(data)
[docs]class Dr_betam(Decay_radiation):
"""Beta- decay radiation
Inherits all the attributes of :py:class:`Decay_radiation`
Contains the energy of the associated anti-neutrino
:ivar Quantity logft: Log ft
:ivar Quantity endpoint: end point energy [keV]
:ivar String trans_type: transition type
:ivar Quantity anti_nu_energy: energy ino
"""
_csv_title = Decay_radiation._csv_title_short + ',logft,logft_unc,logft_limit,trans_type,endpoint,endpoint_unc,endpoint_limit,anti_nu_energy,anti_nu_energy_unc,anti_nu_energy_limit'
def __init__(self):
super().__init__()
self.logft = Quantity("logft")
self.trans_type = None
self.endpoint = Quantity("b_endpoint")
self.anti_nu_energy = Quantity("energy_nu")
def _populate(self,data):
super()._populate(data)
self.logft._populate(data)
self.trans_type = _str_check(data["b_trans_type"])
self.endpoint._populate(data)
self.anti_nu_energy._populate(data)
[docs]class Dr_anti_nu(Decay_radiation):
"""Anti neutrino decay radiation
Inherits all the attributes of :py:class:`Decay_radiation`
Contains the energy of the associated electron
"""
_csv_title = Decay_radiation._csv_title_short + ',logft,logft_unc,logft_limit,trans_type,endpoint,endpoint_unc,endpoint_limit,bm_energy,bm_energy_unc,bm_energy_limit'
def __init__(self):
super().__init__()
self.energy.name = "energy_nu"
self.logft = Quantity("logft")
self.trans_type = None
self.endpoint = Quantity("b_endpoint")
self.bm_energy = Quantity("energy")
def _populate(self,data):
super()._populate(data)
self.logft._populate(data)
self.trans_type = _str_check(data["b_trans_type"])
self.endpoint._populate(data)
self.bm_energy._populate(data)
[docs]class Dr_nu(Decay_radiation):
"""Neutrino decay radiation
Inherits all the attributes of :py:class:`Decay_radiation`
The fields energy, intensity, log_ft, trans_type, endpoint, bp_energy refer to the emission via beta+ process
The fields intensity_ec, energy_ec refer to the emission via electron capture
:ivar Quantity intensity: intensity for emission via beta+ process
:ivar Quantity energy: mean energy for emission via beta+ capture process
:ivar Quantity intensity_ec: intensity for emission via electron capture process
:ivar Quantity energy_ec: mean energy for emission via electron capture process
:ivar Quantity logft: Log ft for the beta+ decay
:ivar Quantity endpoint: end point energy [keV] the beta+ decay
:ivar String trans_type: transition type
"""
_csv_title = Decay_radiation._csv_title_short + ',logft,logft_unc,logft_limit,trans_type,endpoint,endpoint_unc,endpoint_limit,bp_energy,bp_energy_unc,bp_energy_limit,energy_ec,energy_ec_unc,energy_ec_limit,intensity_ec,intensity_ec_unc,intensity_ec_limit'
def __init__(self):
super().__init__()
self.energy.name = "energy_nu"
self.intensity_ec = Quantity("intensity_ec")
self.energy_ec = Quantity("energy_nu_ec")
self.logft = Quantity("logft")
self.trans_type = None
self.endpoint = Quantity("b_endpoint")
self.bp_energy = Quantity("energy")
def _populate(self,data):
super()._populate(data)
self.intensity_ec._populate(data)
self.energy_ec._populate(data)
self.logft._populate(data)
self.trans_type = _str_check(data["b_trans_type"])
self.endpoint._populate(data)
self.bp_energy._populate(data)
[docs]class Dr_betap(Dr_betam):
"""Beta+/Electron Capture decay radiation
Inherits all the attributes of :py:class:`Dr_betam`
Contains the energy of the associated neutrino
:ivar Quantity ec_energy: electron capture energy
:ivar Quantity intensity: beta+ intensity
:ivar Quantity ec_intensity: electron capture intensity
:ivar Quantity bpec_intensity: beta+ + electron capture intensity
"""
_csv_title = Decay_radiation._csv_title_short + ',logft,logft_unc,logft_limit,trans_type,endpoint,endpoint_unc,endpoint_limit,nu_energy,nu_energy_unc,nu_energy_limit,ec_energy,ec_energy_unc,ec_energy_limit,bpec_intensity,bpec_intensity_unc,bpec_intensity_limit,ec_intensity,ec_intensity_unc,ec_intensity_limit'
def __init__(self):
super().__init__()
self.ec_energy = Quantity("ec_energy")
self.bpec_intensity = Quantity("bpec_intensity")
self.ec_intensity = Quantity("ec_intensity")
self.nu_energy = Quantity("energy_nu")
def _populate(self,data):
super()._populate(data)
self.ec_energy._populate(data)
self.bpec_intensity._populate(data)
self.ec_intensity._populate(data)
self.nu_energy._populate(data)
[docs]class Dr_delayed(Decay_radiation):
"""Delayed particle emission
Inherits all the attributes of :py:class:`Decay_radiation`
:ivar Quantity energy_x: energy of the intermediate state
:ivar string particle: delayed particle
"""
_csv_title = Decay_radiation._csv_title_short + ",particle,energy_x,energy_x_unc,energy_x_limit"
def __init__(self):
super().__init__()
self.energy_x = Quantity("energy_x")
self.particle = None
def _populate(self,data):
super()._populate(data)
self.energy_x._populate(data)
self.particle = self.type_a
[docs]class Dr_gamma(Gamma):
"""Gamma decay radiation
Inherits all the attributes of :py:class:`Gamma`
:ivar Nuclide parent: the parent nuclide
:ivar Level parent_level: the parent level
:ivar L_decay decay: access to the level decay, with all the other radiations emitted
:ivar Quantity intensity: for 100 decays of the parent
:ivar string parent_nucid: parent nuclide indentifier, e.g. 135XE
:ivar int parent_l_seqno: sequential number or the parent level, 0 being the g.s.
:ivar int decay_code: code of the decay, see the DECAY_* constants in ndlaborm
"""
_csv_title = 'parent_z,parent_n,parent_nucid,parent_l_seqno,decay_code,z,n,nucid,g_seqno,l_seqno,final_l_seqno,energy,energy_unc,energy_limit,,intensity,intensity_limit,intensity_unc,rel_photon_intens,rel_photon_intens_unc,rel_photon_intens_limit,multipolarity,mixing_ratio,mixing_ratio_unc,mixing_ratio_limit,tot_conv_coeff,tot_conv_coeff_unc,tot_conv_coeff_limit,bew,bew_unc,bew_limit,bew_order,bmw,bmw_unc,bmw_limit,bmw_order,questionable'
def __init__(self):
super().__init__()
self.decay_code = None
self.intensity = Quantity("intensity")
self.parent_z = None
self.parent_n = None
self._parent = None
self._parent_level = None
self._decay = None
def _populate(self,data):
super()._populate(data)
self.parent_z = _int_check(data["parent_z"])
self.parent_n = _int_check(data["parent_n"])
self.parent_nucid = data["parent_nucid"]
self.parent_l_seqno = _int_check(data["parent_l_seqno"])
self.decay_code = _int_check(data["decay_code"])
self.intensity._populate(data)
@property
def parent(self):
if(self._parent == None):
self._parent = this._generator("NUCLIDE", "Nuclide", " NUCLIDE.NUC_ID = '" + self.nucid + "' ")
return self._parent[0]
@property
def parent_level(self):
if(self._parent_level == None):
self._parent_level = this._generator("LEVEL", "Levels", " LEVEL.NUC = '" + self.parent_nucid + "' and LEVEL.SEQNO = " + str(self.parent_l_seqno) + " ", "levels")
return self._parent_level[0]
@property
def decay(self):
if(self._decay == None):
self._decay = this._generator("L_DECAY","L_decays", " L_DECAY.NUC_ID = '" + self.parent_nucid + "' and L_DECAY.LEVEL_SEQNO = " + str(self.parent_l_seqno) + " and L_DECAY.CODE = " +str(self.decay_code) + " ")
return self._decay[0]
class Dr_photon_tot(Ndm_base):
"""Total photon radiation emitted from a parent, regardless of the decay branch and whether is X- or gamma-ray
:ivar Nuclide parent: the parent nuclide
:ivar Level parent_level: the parent level
:ivar Quantity intensity: for 100 decays of the parent
:ivar Quantity energy: photon energy [keV]
:ivar string parent_nucid: parent nuclide indentifier, e.g. 135XE
:ivar string type: type of the radiation: X, G, AU, CE
:ivar int parent_l_seqno: sequential number or the parent level, 0 being the g.s.
:ivar int decay_code: code of the decay, see the DECAY_* constants in ndlaborm
:ivar int count: number of decay branches in which this energy is present
"""
_csv_title = "parent_nucid,parent_l_seqno,energy,energy_unc,energy_limit,intensity,intensity_unc,intensity_limit,type,count"
def __init__(self):
self.parent_nucid = None
self.parent_l_seqno = None
self.energy = Quantity("energy")
self.intensity = Quantity("intensity");
self.count = 0
self.type = None
self._parent = None
self._parent_level = None
def _populate(self,data):
self.parent_nucid = data["parent_nucid"]
self.parent_l_seqno = data["parent_l_seqno"]
self.energy._populate(data)
self.intensity._populate(data)
self.type = data["type"]
self.count = data["cnt"]
self.pk = self.parent_nucid + '-' + str(self.parent_l_seqno)
@property
def parent(self):
if(self._parent == None):
self._parent = this._generator("NUCLIDE", "Nuclide", " NUCLIDE.NUC_ID = '" + self.parent_nucid + "' ")
return self._parent[0]
@property
def parent_level(self):
if(self._parent_level == None):
self._parent_level = this._generator("LEVEL", "Level", " LEVEL.NUC_ID = '" + self.parent_nucid + "' and LEVEL.SEQNO = " + str(self.parent_l_seqno) + " ")
return self._parent_level[0]
class Dr_annihil(Decay_radiation):
_csv_title = Decay_radiation._csv_title_short
def __init__(self):
super().__init__()
def _populate(self,data):
super()._populate(data)
class Dr_atomic(Decay_radiation):
"""Radiation emitted by atomic processes: X-rays, Conversion Electrons, Auger Electrons
Inherits all the attributes of :py:class:`Decay_radiation`
:ivar String shell: the atomic shell involved
"""
_csv_title = "parent_nucid,parent_l_seqno,decay_code,intensity,intensity_unc,intensity_limit,energy,energy_unc,energy_limit,shell"
def __init__(self):
super().__init__()
self.shell = None
def _populate(self,data):
super()._populate(data)
self.shell = data["type_c"]
self.pk = str(data["r_seqno"])
class Dr_x(Dr_atomic):
""" X-rays emitted
Inherits all the attributes of :py:class:`Dr_atomic` restricted to X
"""
def __init__(self):
super().__init__()
def _populate(self,data):
super()._populate(data)
class Dr_conv_el(Dr_atomic):
""" Conversion Electrons emitted
Inherits all the attributes of :py:class:`Dr_atomic` restricted to CE
"""
def __init__(self):
super().__init__()
def _populate(self,data):
super()._populate(data)
class Dr_auger(Dr_atomic):
""" Auger Electrons emitted
Inherits all the attributes of :py:class:`Dr_atomic` restricted to AU
"""
def __init__(self):
super().__init__()
def _populate(self,data):
super()._populate(data)
def _generator(orm_table: str, nl_class_name: str , filter : str = ''):
""" fills an array of ndlab classes by querying the database.
The 'populate' function of the ndlab entity performs the job, it makes use of reflection.
The constructed query is a 'select * from tablename' + filter
Args:
orm_table (str): the name of the :py:mod:`ndlaborm` class for the query, e.g. 'NUCLIDE'
nl_class_name (str): the name of the ndlab class that will be filled by the query result set, e.g. 'Nuclide'.
The 'populate' function on the class links the result set with the class properties
filter (str) = '' : the filter to produce the where condition in the query
Returns:
Object[]: list of nl_class_name instances
"""
# overwrite the filter
_filter = this._filter if filter == "" else filter
#print("class ",nl_class_name, " filter ",filter, " _filter ", _filter, dblink.query_check(orm_table+".*",filter), "orm_table" , orm_table)
if(not dblink.is_query_ok(orm_table+".*",filter)):
return ERROR_FILTER_NOT_VALID
tablename = orm_table if orm_table.endswith("ALL") else orm_table + ".*"
# call to the database
jss = json.loads(json_data(tablename , _filter ))
#print(" tablename ",tablename)
#print(" sql ", dblink.lastsql)
#print(" json ", jss)
#print("")
# the return array
objs = []
# instanciate the factory
classfact = getattr(this, nl_class_name)
# instanciate and fill the entities
for js in jss:
obj = classfact()
# let the object remember its filter
obj.myfilter = _filter
obj._populate(js)
objs.append(obj)
return objs
def query_check(table, conditions=""):
""" Check if users parameters produce a valid query, return errors if any
interface to sqlbuilder
"""
return dblink.query_check(table, conditions)
def is_query_ok(table, conditions=""):
""" Check if users parameters produce a valid query, return true/false
interface to sqlbuilder
"""
return dblink.is_query_ok(table, conditions)
[docs]def check_filter(filter, function):
"""Whether a filter is okay when applied to a given function
Filter should query only one table (besides embedded foreign keys)
Args:
filter (str): the filter
function (Function) : the ndlab function accepting the filter
Returns:
Boolean :
"""
table = function.__name__[:-1].upper() + ".*"
return dblink.is_query_ok(table,filter)
[docs]def nuclide(nucid):
"""A :py:class:`ndlab.Nuclide` from its identifyer
Args:
nucid (str): mass+element symbol, e.g.135XE
Returns:
Nuclide : the :ref:`NUCLIDE <NUCLIDE>` with this id
"""
old_filter = this._filter
this._filter = "NUCLIDE.NUC_ID = '" + nucid.upper() + "'"
nuc = nuclides()
this._filter = old_filter
if (nuc == None or len(nuc) == 0):
return None
return nuc[0]
[docs]def nuclides(filter = ""):
"""A list of :py:class:`ndlab.Nuclide`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`NUCLIDE <NUCLIDE>` entity
Returns:
Nuclide :
"""
return _generator("NUCLIDE","Nuclide", filter)
[docs]def levels(filter = ""):
"""A list of :py:class:`ndlab.Level`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`LEVEL <LEVEL>` entity
Returns:
Level :
"""
return _generator("LEVEL","Level", filter)
[docs]def gammas(filter = ""):
"""A list of :py:class:`ndlab.Gamma`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`GAMMA <GAMMA>` entity
Returns:
Gamma :
"""
return _generator("GAMMA","Gamma", filter)
[docs]def l_decays(filter = ""):
"""A list of :py:class:`ndlab.L_decays`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`L_DECAY <L_DECAY>` entity
Returns:
L_decay :
"""
return _generator("L_DECAY","L_decay", filter)
def decay_codes(filter = ""):
return _generator("DECAY_CODE","Decay_code", filter)
[docs]def dr_alphas(filter = ""):
"""A list of :py:class:`ndlab.Dr_alpha`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_ALPHA <DR_ALPHA>` entity
Returns:
Dr_alpha :
"""
return _generator("DR_ALPHA","Dr_alpha", filter)
[docs]def dr_gammas(filter = ""):
"""A list of :py:class:`ndlab.Dr_gamma`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_GAMMA <DR_GAMMA>` entity
Returns:
Dr_gamma :
"""
return _generator("DR_GAMMA","Dr_gamma", filter)
def dr_annihil(filter = ""):
"""A list of :py:class:`ndlab.Dr_annihil`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_GAMMA <DR_GAMMA>` entity
Returns:
Dr_annihil :
"""
return _generator("DR_ANNIHIL","Dr_annihil", filter)
[docs]def dr_beta_ms(filter = ""):
"""A list of :py:class:`ndlab.Dr_betam`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_GAMMA <DR_GAMMA>` entity
Returns:
Dr_betam :
"""
return _generator("DR_BETAM","Dr_betam", filter)
[docs]def dr_anti_nus(filter = ""):
"""A list of :py:class:`ndlab.Dr_anti_nu`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_GAMMA <DR_GAMMA>` entity
Returns:
Dr_anti_nu :
"""
return _generator("DR_ANTI_NU","Dr_anti_nu", filter)
[docs]def dr_nus(filter = ""):
"""A list of :py:class:`ndlab.Dr_nu`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_GAMMA <DR_GAMMA>` entity
Returns:
Dr_nu :
"""
return _generator("DR_NU","Dr_nu", filter)
[docs]def dr_beta_ps(filter = ""):
"""A list of :py:class:`ndlab.Dr_betap`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_GAMMA <DR_GAMMA>` entity
Returns:
Dr_betap :
"""
return _generator("DR_BETAP","Dr_betap", filter)
[docs]def dr_xs(filter = ""):
"""A list of :py:class:`ndlab.Dr_x`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_GAMMA <DR_GAMMA>` entity
Returns:
Dr_x :
"""
return _generator("DR_X","Dr_x", filter)
def dr_photon_tot(filter = ""):
"""A list of :py:class:`ndlab.Dr_photon_tot`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_GAMMA <DR_GAMMA>` entity
Returns:
Dr_photon_tot :
"""
return _generator("DR_PHOTON_TOTAL","Dr_photon_tot", filter)
[docs]def dr_convels(filter = ""):
"""A list of :py:class:`ndlab.Dr_conv_el`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_GAMMA <DR_GAMMA>` entity
Returns:
Dr_conv_el :
"""
return _generator("DR_CONV_EL","Dr_conv_el", filter)
[docs]def dr_augers(filter = ""):
"""A list of :py:class:`ndlab.Dr_Augher`
Shells included are K and L
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_GAMMA <DR_GAMMA>` entity
Returns:
Dr_Auger :
"""
return _generator("DR_AUGER","Dr_auger", filter)
def dr_delayeds(filter = ""):
"""A list of :py:class:`ndlab.Dr_delayed`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_GAMMA <DR_GAMMA>` entity
Returns:
Dr_delayed :
"""
return _generator("DR_DELAYED","Dr_delayed", filter)
[docs]def cum_fys(filter = ""):
"""A list of :py:class:`ndlab.Cum_fy`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_GAMMA <DR_GAMMA>` entity
Returns:
Cum_fy :
"""
return _generator("CUM_FY","Cum_fy", filter)
[docs]def ind_fys(filter = ""):
"""A list of :py:class:`ndlab.Ind_fy`
Args:
filter (str): :ref:`filter <filter-label>` passed to the function by the user. It may contain only fields of the :ref:`DR_GAMMA <DR_GAMMA>` entity
Returns:
Ind_fy :
"""
return _generator("IND_FY","Ind_fy", filter)
def setfilter(where: str):
''' appendeds a filter to each query'''
this._filter = where
def remove_doublers(doublers):
""" removes doublers from a list
When one wants to be sure that each item is present only once
Args:
doublers (list): list of same-class items
Returns:
list: the list with only singlers
"""
if(len(doublers) == 0): return doublers
singlers = []
pks = []
for n in doublers:
if n.pk in pks: continue
singlers.append(n)
pks.append(n.pk)
return singlers
def getfilter():
return this._filter
[docs]def json_data(fields , filter ):
"""JSON data from a query
Args:
fields (str): list of comma-separated :py:mod:`ndlaborm` fields
filter (str): filter condition built with :py:mod:`ndlaborm` fields
Returns:
str: JSON structure with the result set
"""
return _data_deliverer ('json', fields , filter )
# string
[docs]def csv_data(fields , filter ):
"""CSV data from a query
Args:
fields (str): list of comma-separated :py:mod:`ndlaborm` fields
filter (str): filter condition built with :py:mod:`ndlaborm` fields
Returns:
str: CSV structure with the data
"""
return _data_deliverer ('csv', fields , filter )
def _data_deliverer(return_type,fields , filter):
"""Delivers the data by querying the database
It refers to dblink, the variable with an instance of ndlabdblink.DbLink class
that handles the database
It checks whether the db is local, or is remote and accessed through http
Args:
return_type (str): 'csv' or 'json'
fields (str): list of comma-separated :py:mod:`ndlaborm` fields
filter (str): filter condition built with :py:mod:`ndlaborm` fields
Returns:
str: either a csv or a json structure with the data
"""
this.last_fields = fields
this.last_filter = filter
if(not dblink.is_query_ok(fields,filter)):
return ERROR_FILTER_NOT_VALID
if(dblink.connected):
return dblink.data_deliverer (return_type, fields , filter )
else:
return _httprequest(return_type,fields, filter).read().decode("utf8").strip()
# dblink
#def force_clean_query(force):
# dblink.force_clean_query(force)
# dblink
#def lastquery_desc():
# return dblink.query_desc(last_fields,last_filter)
[docs]def csv_nl(nl_items):
"""CSV from a list of :py:class:`ndlab.Ndm_base` classes
for each instance, calls its csv() method and composes the overall result
Args:
nl_items (Object[]): list with ndlab class instances
Returns:
String: the CSV
"""
if nl_items is None:
return ""
try:
nl_items[0]
except:
return nl_items._csv_title + "\n" + nl_items.csv();
return nl_items[0]._csv_title + "\n" + "".join([item.csv() + "\n" for item in nl_items] )
[docs]def pandas_csv_nl( nl_items):
"""Text stream with CSV from a list of :py:class:`ndlab.Ndm_base` classes
Ready to be plugged into pandas. For each instance, calls its csv() method and composes the overall result
Args:
nl_items (Object[]): list with ndlab class instances
Returns:
StringIO: text stream with the CSV
"""
return io.StringIO(csv_nl(nl_items))
[docs]def pandas_df_nl(list, pandas):
""" Returns a Dataframe from a list of :py:class:`ndlab.Ndm_base` classes
Args:
list (List): list of ndlab class instances
pandas (Object): the pandas module imported in the calling environment. E.g. pass when :code:`pd` when using :code:`import pandas as pd`
Returns:
Dataframe: the pandas dataframe
"""
if(list == None or len(list) == 0):
return None
if (list.__class__.__name__ != 'str' and list[0].__module__ != 'ndlab'):
return None
# this is an error
if(list.__class__.__name__ == 'str'):
return pandas.read_csv(io.StringIO("MESSAGE\n"+list))
return pandas.read_csv(pandas_csv_nl(list))
[docs]def pandas_df(fields, filter, pandas):
"""Creates a dataframe
If the database is local, calls pandas' read_sql method using :py:class:`query_build` to build the query, and :py:class:`query_con`
to get the db connection
If the database is remote, calls the server API
Args:
fields (str): list of comma-separated :py:mod:`ndlaborm` fields
filter (str): filter condition built with :py:mod:`ndlaborm` fields
pandas (Object): the pandas module imported in the calling environment. E.g. pass when :code:`pd` when using :code:`import pandas as pd`
Returns:
Dataframe: the pandas dataframe
"""
if(dblink.connected):
try:
return pandas.read_sql(query_build(fields, filter), query_con())
except:
try:
# try to put blank spaces where needed
force = dblink._sqlbuilder.force_clean
dblink.force_clean_query(True)
qry = query_build(fields, filter)
dblink.force_clean_query(force)
return pandas.read_sql(qry, query_con())
except Exception as e:
print("Error , check the rules for the fields and filter parameters\n" +str(e))
return None
else:
return pandas.read_csv(pandas_csv_web(fields, filter) )
def pandas_csv_web(fields, filter=""):
"""CSV data from the web server
Ready to be plugged into pandas, accessing the database through http.
To be used when the databse is not local, otherwise use :code:`pd.readsql(` :py:meth:`ndlab.query_build`, :py:meth:`ndlab.query_con`)
Args:
fields (str): list of comma-separated :py:mod:`ndlaborm` fields
filter (str): filter condition built with :py:mod:`ndlaborm` fields
Returns:
http.client.HTTPResponse : the response to be read
"""
return _httprequest('csv',fields, filter)
[docs]def query_con():
"""The connection to the database
Returns:
Connection: The connection to the database
"""
return dblink._con_lite
[docs]def query_build(fields, filter=""):
"""The SQL query associated with fields and filter
Args:
fields (str): list of comma-separated :py:mod:`ndlaborm` fields
filter (str): filter condition built with :py:mod:`ndlaborm` fields
Returns:
String : the SQL
"""
return dblink.query_build(fields, filter)
def _httprequest(return_type, fields, filter=""):
""" Queries the database through http
Args:
return_type (str): 'csv' or 'json'
fields (str): list of comma-separated :py:mod:`ndlaborm` fields
filter (str): filter condition built with :py:mod:`ndlaborm` fields
Returns:
http.client.HTTPResponse : the response to be read
"""
import urllib.request
import urllib.parse
url = "http://localhost:8123/cgi-bin/ndlab_server.py?"
#url = "http://int-nds.iaea.org/cgi-bin/mvtest/ndlab_server.py?"
query = "return_type=" + return_type + "&fields=" + urllib.parse.quote(fields) + "&where=" + urllib.parse.quote( " " + filter)
#print( url+query)
req = urllib.request.Request(url + query)
req.add_header('User-Agent',
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0')
return urllib.request.urlopen(req)
def print_shell():
res = dblink.query_exec("select distinct type_c from decay_radiations order by 1")
for r in res:
print("SHELL_" + r[0] + " = '" + r[0]+ "'")
def print_transition():
res = dblink.query_exec("select distinct b_trans_type from decay_radiations order by 1")
for r in res:
print("TRANS_" + r[0] + " = '" + r[0]+ "'")