14#include "tkisotope_builder.h"
54 fTable = &fDataBase->new_table(fTableName);
56 fTable->add_column(
"isotope_id",
"INT PRIMARY KEY NOT NULL");
57 fTable->add_column(
"element_id",
"INT NOT NULL");
58 fTable->add_column(
"mass",
"INT");
62 fTable->add_column(
"isotope_year_discovered",
"INT");
64 add_measure(
"mass_excess",
false);
65 add_measure(
"electric_quadrupole",
false);
66 add_measure(
"magnetic_dipole",
false);
67 add_measure(
"radius",
false);
71 add_measure(
"abundance",
false);
72 add_measure(
"quadrupoleDeformation",
false);
74 add_measure(
"FY235U",
false);
75 add_measure(
"FY238U",
false);
76 add_measure(
"FY239Pu",
false);
77 add_measure(
"FY241Pu",
false);
78 add_measure(
"FY252Cf",
false);
80 add_measure(
"cFY235U",
false);
81 add_measure(
"cFY238U",
false);
82 add_measure(
"cFY239Pu",
false);
83 add_measure(
"cFY241Pu",
false);
84 add_measure(
"cFY252Cf",
false);
86 fTable->add_column(
"decay_modes",
"TEXT");
90 fTable->add_column(
"spin",
"REAL");
91 fTable->add_column(
"parity",
"INT");
92 fTable->add_column(
"spin_parity",
"TEXT");
94 add_measure(
"lifetime",
false);
96 fTable->add_constraint(
"FOREIGN KEY (element_id) REFERENCES ELEMENT (element_id)");
97 fTable->write_to_database();
99 glog <<
info <<
"Creating '" << _table_name <<
"' table" <<
do_endl;
104void tkisotope_builder::fill_isotope(
const json_nucleus &_json_nuc)
110 (*fTable)[
"isotope_id"].set_value(fIsotopeIdx);
111 (*fTable)[
"element_id"].set_value(_json_nuc.Z+1);
112 (*fTable)[
"mass"].set_value(_json_nuc.A);
113 (*fTable)[
"isotope_year_discovered"].set_value(_json_nuc.year);
115 fill_measure(
"mass_excess",_json_nuc.mass_excess,
false);
116 fill_measure(
"abundance",_json_nuc.abundance,
false);
117 fill_measure(
"quadrupoleDeformation",_json_nuc.quadrupoleDeformation,
false);
119 fill_measure(
"FY235U",_json_nuc.FY235U,
false);
120 fill_measure(
"FY238U",_json_nuc.FY238U,
false);
121 fill_measure(
"FY239Pu",_json_nuc.FY239Pu,
false);
122 fill_measure(
"FY241Pu",_json_nuc.FY241Pu,
false);
123 fill_measure(
"FY252Cf",_json_nuc.FY252Cf,
false);
125 fill_measure(
"cFY235U",_json_nuc.cFY235U,
false);
126 fill_measure(
"cFY238U",_json_nuc.cFY238U,
false);
127 fill_measure(
"cFY239Pu",_json_nuc.cFY239Pu,
false);
128 fill_measure(
"cFY241Pu",_json_nuc.cFY241Pu,
false);
129 fill_measure(
"cFY252Cf",_json_nuc.cFY252Cf,
false);
131 fill_measure(
"electric_quadrupole",_json_nuc.electric_quadrupole,
false);
132 fill_measure(
"magnetic_dipole",_json_nuc.magnetic_dipole,
false);
133 fill_measure(
"radius",_json_nuc.radius,
false);
136 if(_json_nuc.Z==0 && _json_nuc.N ==1) {
138 lifetime.
value = 613.9;
142 fill_measure(
"lifetime",lifetime,
false);
146 for(
auto &dec: _json_nuc.decay_modes) decays.
append(
tkstring::form(
"[%s;%g]",dec.first.data(),dec.second));
147 (*fTable)[
"decay_modes"].set_value(decays.data());
154 glog.set_class(
"db_isotope_builder");
155 glog.set_method(
tkstring::form(
"fill_database('%s','%s')",_json_filename,_gs_filename));
157 tkdb_table &fTable = (*fDataBase)[fTableName.data()];
159 tkstring message =
"Building '" + fTable.get_name() +
"' table";
161 std::ifstream ifs(_json_filename);
168 json jf = json::parse(ifs);
170 auto &nuclides = jf.at(
"nuclides");
171 int NNucs = nuclides.size();
174 map<int, map<int, json_nucleus>> nuclei;
177 for(
auto &nuc: nuclides) {
178 json_nucleus json_nuc = read_nucleus(nuc);
180 bool do_push = ((_only_charge==0) && (_only_mass==0));
181 if((_only_charge == json_nuc.Z) && (_only_mass == 0)) do_push =
true;
182 if((_only_charge == json_nuc.Z) && (_only_mass == json_nuc.A)) do_push =
true;
183 if((_only_charge == 0) && (_only_mass == json_nuc.A)) do_push =
true;
186 nuclei[json_nuc.Z][json_nuc.A] = json_nuc;
189 glog.progress_bar(NNucs,inuc,message.data());
194 fstream file (_gs_filename, ios::in);
198 if(!getline(file,line))
return 1;
201 std::map<int,tkn::tkstring> gs_columns;
202 for(
const auto &cname : line.
tokenize(
",")) gs_columns[ic++] = cname;
205 while(getline(file, line))
207 std::map<tkn::tkstring, tkn::tkstring> values;
211 for(
auto val : line.
tokenize(
",")) {val.remove_all(
" "); values[gs_columns[ic]] = val; ic++;}
214 if(!nread.
contains(
tkstring::form(
"(%d,%d)",values[
"z"].atoi(),values[
"n"].atoi()+values[
"z"].atoi())))
continue;
215 auto& nuc = nuclei[values[
"z"].atoi()][values[
"n"].atoi()+values[
"z"].atoi()];
216 if(!values[
"massexcess"].is_empty()) nuc.mass_excess = {values[
"massexcess"].atof(),values[
"unc_me"].atof(),-1.,-1.,
"keV",values[
"me_systematics"].equal_to(
"Y")?
";ERR=SY":
"",
true};
217 if(!values[
"radius"].is_empty())nuc.radius = {values[
"radius"].atof(),values[
"unc_r"].atof(),-1.,-1.,
"fm",
"",
true};
218 if(!values[
"electric_quadrupole"].is_empty()) nuc.electric_quadrupole = {values[
"electric_quadrupole"].atof(),values[
"unc_eq"].atof(),-1.,-1.,
"barn",
"",
true};
219 if(!values[
"magnetic_dipole"].is_empty()) nuc.magnetic_dipole = {values[
"magnetic_dipole"].atof(),values[
"unc_md"].atof(),-1.,-1.,
"mun",
"",
true};
220 if(!values[
"discovery"].is_empty()) nuc.year = values[
"discovery"].atoi();
224 fDataBase->exec_sql(
"BEGIN TRANSACTION");
227 for(
auto &z: nuclei) {
228 for(
auto &a: z.second) {
231 fill_isotope(a.second);
233 fDataBase->exec_sql(
tkstring::form(
"CREATE VIEW nuc%s as select * from isotope INNER JOIN element on isotope.element_id=element.element_id where element.charge=%d AND isotope.mass=%d",a.second.name.data(),a.second.Z,a.second.A));
234 glog.progress_bar(NNucs,inuc,message.data());
239 fDataBase->exec_sql(
"END TRANSACTION");
241 fDataBase->exec_sql(
"CREATE INDEX element_index ON isotope(element_id)");
242 fDataBase->exec_sql(
"CREATE INDEX mass_index ON isotope(mass)");
252 auto to_number = [](
const json &value) {
253 if(value.is_string())
return value.get<
tkstring>().atof();
254 if(value.is_number())
return value.get<
double>();
257 bool value_set =
false;
258 for(
auto &_item: entry.items()) {
259 const auto &_key = _item.key();
260 const auto &_val = _item.value();
261 if(_key ==
"formats")
continue;
262 if(_key ==
"uncertainty") {
263 if(_val.is_object()) {
264 const auto type = _val.value(
"type",
"");
265 if(type ==
"symmetric") _data.
err = to_number(_val.at(
"value"));
266 else if(type ==
"range") {
267 if(_val.contains(
"upperLimit") && _val.contains(
"lowerLimit")) {
268 const double upper = to_number(_val.at(
"upperLimit"));
269 const double lower = to_number(_val.at(
"lowerLimit"));
270 if(!value_set) _data.
value = 0.5 * (upper + lower);
277 _data.
err = to_number(_val);
280 else if(_key ==
"value") {
281 _data.
value = to_number(_val);
284 else if(_key ==
"unit") _data.
unit = _val.get<tkstring>();
285 else if(_key ==
"evaluatorInput")
continue;
286 else if(_key ==
"isSystematics" && (_val ==
"true" || (_val.is_boolean() && _val.get<
bool>()))) _data.
info.
append(
";ERR=SY");
288 glog <<
error << key <<
": unkown key: " << _key <<
" type: "<< _item.value().type_name() <<
do_endl;
289 cout << _val << endl;
294 if(entry.contains(
"formats") && entry.at(
"formats").contains(
"STD")) {
295 tkstring format = entry.at(
"formats").at(
"STD").get<tkstring>();
298 if(tokens.size()==2) {
299 _data.
err = tokens.back().
atof();
306tkisotope_builder::json_nucleus tkisotope_builder::read_nucleus(json &entry) {
309 for(
auto &item: entry.items())
311 auto &key = item.key();
312 auto &val = item.value();
313 if(key ==
"name") nuc.name = val;
314 else if(key ==
"z") nuc.Z = val;
315 else if(key ==
"n") nuc.N = val;
316 else if(key ==
"a") nuc.A = val;
317 else if(key ==
"bindingEnergy")
continue;
318 else if(key ==
"bindingEnergyLDMFit")
continue;
319 else if(key ==
"levels") {
321 auto is_ground_state = [](
const json &level) {
322 if(!level.contains(
"energy"))
return false;
323 const auto &energy = level.at(
"energy");
324 if(!energy.is_object() || !energy.contains(
"value"))
return false;
325 const auto &energy_val = energy.at(
"value");
326 if(energy_val.is_string())
return energy_val.get<tkstring>().atof() == 0.0;
327 if(energy_val.is_number())
return energy_val.get<
double>() == 0.0;
330 const json *level_ptr =
nullptr;
331 const auto it = std::find_if(val.begin(), val.end(), is_ground_state);
332 bool picked_ground = (it != val.end());
333 if(picked_ground) level_ptr = &(*it);
334 else if(!val.empty()) level_ptr = &val.front();
335 if(!level_ptr)
continue;
336 for(
auto &_item: level_ptr->items()) {
337 const auto &_key = _item.key();
338 const auto &_val = _item.value();
339 if(_key ==
"decayModes") {
340 if(_val.is_object() && (_val.contains(
"observed") || _val.contains(
"predicted"))) {
341 if(_val.contains(
"observed")) {
342 for(
const auto &mode : _val.at(
"observed")) {
343 tkstring type = mode.value(
"mode",
"");
344 tkstring ratio =
"-1";
345 if(mode.contains(
"value")) {
346 if(mode.at(
"value").is_string()) ratio = mode.at(
"value").get<tkstring>();
347 else if(mode.at(
"value").is_number()) ratio =
tkstring::form(
"%g", mode.at(
"value").get<
double>());
349 nuc.decay_modes.emplace_back(type, ratio.
atof());
352 if(_val.contains(
"predicted")) {
353 for(
const auto &mode : _val.at(
"predicted")) {
354 tkstring type = mode.value(
"mode",
"");
355 tkstring ratio =
"-1";
356 nuc.decay_modes.emplace_back(type, ratio.
atof());
360 for(
auto &mode: _val.items()) {
361 if(mode.value().size()==3) {
362 tkstring type = mode.value().at(
"name");
363 tkstring symbol = mode.value().at(
"symbol");
370 else ratio = mode.value().at(
"value");
371 nuc.decay_modes.emplace_back(type,ratio.
atof());
374 tkstring type = mode.value().at(
"name");
376 tkstring symbol =
"=";
377 tkstring ratio =
"-1";
378 nuc.decay_modes.emplace_back(type,ratio.
atof());
383 else if(_key ==
"energy") {
384 if(_val.empty())
continue;
385 if(_val.size()<2)
continue;
387 const auto &energy_val = _val.at(
"value");
388 if(energy_val.is_string()) ener = energy_val.get<tkstring>().atof();
389 else if(energy_val.is_number()) ener = energy_val.get<
double>();
390 if(ener != 0. && picked_ground) {
391 glog <<
error << nuc.name <<
": level is not ground state ! " << _val <<
do_endl;
394 else if(_key ==
"massExcess") read_measure(_key, _val, nuc.mass_excess);
395 else if(_key ==
"abundance") {
396 read_measure(_key, _val, nuc.abundance,
true);
397 nuc.abundance.unit =
"%";
400 else if(_key ==
"halflife" || _key ==
"spinAndParity" || _key ==
"spinParity")
continue;
402 glog <<
error <<
"levels: unkown key: " << _key <<
" type: "<< _item.value().type_name() <<
do_endl;
403 cout << _val << endl;
407 else if(key ==
"pairingGap")
continue;
408 else if(key ==
"qValues")
continue;
409 else if(key ==
"separationEnergies")
continue;
410 else if(key ==
"webLinks")
continue;
411 else if(key ==
"BE4DBE2")
continue;
412 else if(key ==
"excitedStateEnergies") {
413 for(
auto &_item: val.items()) {
414 const auto &_key = _item.key();
415 const auto &_val = _item.value();
416 if(_key ==
"firstExcitedStateEnergy")
continue;
417 if(_key ==
"firstTwoPlusEnergy")
continue;
418 if(_key ==
"firstFourPlusEnergy")
continue;
419 if(_key ==
"firstFourPlusOverFirstTwoPlusEnergy")
continue;
420 if(_key ==
"firstThreeMinusEnergy")
continue;
421 glog <<
error << key <<
": unkown key: " << _key <<
" type: "<< _item.value().type_name() <<
do_endl;
422 cout << _val << endl;
425 else if(key ==
"fissionYields") {
426 for(
auto &_item: val.items()) {
427 const auto &_key = _item.key();
428 const auto &_val = _item.value();
429 if(_key ==
"FY235U") read_measure(_key, _val, nuc.FY235U);
430 else if(_key ==
"FY238U") read_measure(_key, _val, nuc.FY238U);
431 else if(_key ==
"FY239Pu") read_measure(_key, _val, nuc.FY239Pu);
432 else if(_key ==
"FY241Pu") read_measure(_key, _val, nuc.FY241Pu);
433 else if(_key ==
"FY252Cf") read_measure(_key, _val, nuc.FY252Cf);
434 else if(_key ==
"cFY235U") read_measure(_key, _val, nuc.cFY235U);
435 else if(_key ==
"cFY238U") read_measure(_key, _val, nuc.cFY238U);
436 else if(_key ==
"cFY239Pu") read_measure(_key, _val, nuc.cFY239Pu);
437 else if(_key ==
"cFY241Pu") read_measure(_key, _val, nuc.cFY241Pu);
438 else if(_key ==
"cFY252Cf") read_measure(_key, _val, nuc.cFY252Cf);
440 glog <<
error << key <<
": unkown key: " << _key <<
" type: "<< _item.value().type_name() <<
do_endl;
441 cout << _val << endl;
445 else if(key ==
"quadrupoleDeformation") read_measure(key, val, nuc.quadrupoleDeformation);
446 else if(key ==
"thermalNeutronCapture")
continue;
447 else if(key ==
"thermalNeutronFission")
continue;
448 else if(key ==
"discovery")
continue;
451 cout<<
"value: " << endl;
Interface to the sqlite database.
tkdb_builder(tkdatabase *_database, const char *_table_name)
Representaiton of a sqlite data table.
Decoding of the NUDAT isotope properties.
int fill_database(const char *_json_filename, const char *_gs_filename, int _only_charge=0, int _only_mass=0)
virtual ~tkisotope_builder() override
tkisotope_builder(tkdatabase *_database, const char *_table_name="ISOTOPE")
std::string with usefull tricks from TString (ROOT) and KVString (KaliVeda) and more....
static const char * form(const char *_format,...)
std::vector< tkstring > tokenize(const tkstring &_delim=" ") const
Create a vector of string separated by at least one delimiter.
tkstring & remove_all(const tkstring &_s1)
bool contains(const char *_pat, ECaseCompare _cmp=kExact) const
tkstring & append(const tkstring &_st)
tkstring & replace_all(const tkstring &_s1, const tkstring &_s2)
double atof() const
Converts a string to double value.
tklog & error_v(tklog &log)
tklog & error(tklog &log)
tklog & do_endl(tklog &log)
tklog & warning(tklog &log)
data structure used to fill a tkmeasure object from the sqlite database