37#include "tkisotope_builder.h"
77 fTable = &fDataBase->new_table(fTableName);
79 fTable->add_column(
"isotope_id",
"INT PRIMARY KEY NOT NULL");
80 fTable->add_column(
"element_id",
"INT NOT NULL");
81 fTable->add_column(
"mass",
"INT");
85 fTable->add_column(
"isotope_year_discovered",
"INT");
87 add_measure(
"mass_excess",
false);
88 add_measure(
"electric_quadrupole",
false);
89 add_measure(
"magnetic_dipole",
false);
90 add_measure(
"radius",
false);
94 add_measure(
"abundance",
false);
95 add_measure(
"quadrupoleDeformation",
false);
97 add_measure(
"FY235U",
false);
98 add_measure(
"FY238U",
false);
99 add_measure(
"FY239Pu",
false);
100 add_measure(
"FY241Pu",
false);
101 add_measure(
"FY252Cf",
false);
103 add_measure(
"cFY235U",
false);
104 add_measure(
"cFY238U",
false);
105 add_measure(
"cFY239Pu",
false);
106 add_measure(
"cFY241Pu",
false);
107 add_measure(
"cFY252Cf",
false);
109 fTable->add_column(
"decay_modes",
"TEXT");
113 fTable->add_column(
"spin",
"REAL");
114 fTable->add_column(
"parity",
"INT");
115 fTable->add_column(
"spin_parity",
"TEXT");
117 add_measure(
"lifetime",
false);
119 fTable->add_constraint(
"FOREIGN KEY (element_id) REFERENCES ELEMENT (element_id)");
120 fTable->write_to_database();
122 glog <<
info <<
"Creating '" << _table_name <<
"' table" <<
do_endl;
127void tkisotope_builder::fill_isotope(
const json_nucleus &_json_nuc)
133 (*fTable)[
"isotope_id"].set_value(fIsotopeIdx);
134 (*fTable)[
"element_id"].set_value(_json_nuc.Z+1);
135 (*fTable)[
"mass"].set_value(_json_nuc.A);
136 (*fTable)[
"isotope_year_discovered"].set_value(_json_nuc.year);
138 fill_measure(
"mass_excess",_json_nuc.mass_excess,
false);
139 fill_measure(
"abundance",_json_nuc.abundance,
false);
140 fill_measure(
"quadrupoleDeformation",_json_nuc.quadrupoleDeformation,
false);
142 fill_measure(
"FY235U",_json_nuc.FY235U,
false);
143 fill_measure(
"FY238U",_json_nuc.FY235U,
false);
144 fill_measure(
"FY239Pu",_json_nuc.FY239Pu,
false);
145 fill_measure(
"FY241Pu",_json_nuc.FY239Pu,
false);
146 fill_measure(
"FY252Cf",_json_nuc.FY252Cf,
false);
148 fill_measure(
"cFY235U",_json_nuc.cFY235U,
false);
149 fill_measure(
"cFY238U",_json_nuc.cFY235U,
false);
150 fill_measure(
"cFY239Pu",_json_nuc.cFY239Pu,
false);
151 fill_measure(
"cFY241Pu",_json_nuc.cFY239Pu,
false);
152 fill_measure(
"cFY252Cf",_json_nuc.cFY252Cf,
false);
154 fill_measure(
"electric_quadrupole",_json_nuc.electric_quadrupole,
false);
155 fill_measure(
"magnetic_dipole",_json_nuc.magnetic_dipole,
false);
156 fill_measure(
"radius",_json_nuc.radius,
false);
159 if(_json_nuc.Z==0 && _json_nuc.N ==1) {
161 lifetime.
value = 613.9;
165 fill_measure(
"lifetime",lifetime,
false);
169 for(
auto &dec: _json_nuc.decay_modes) decays.
append(
tkstring::form(
"[%s;%g]",dec.first.data(),dec.second));
170 (*fTable)[
"decay_modes"].set_value(decays.data());
177 glog.set_class(
"db_isotope_builder");
178 glog.set_method(
tkstring::form(
"fill_database('%s','%s')",_json_filename,_gs_filename));
180 tkdb_table &fTable = (*fDataBase)[fTableName.data()];
182 tkstring message =
"Building '" + fTable.get_name() +
"' table";
184 std::ifstream ifs(_json_filename);
191 json jf = json::parse(ifs);
193 auto &nuclides = jf.at(
"nuclides");
194 int NNucs = nuclides.size();
197 map<int, map<int, json_nucleus>> nuclei;
200 for(
auto &nuc: nuclides) {
201 json_nucleus json_nuc = read_nucleus(nuc);
203 bool do_push = ((_only_charge==0) && (_only_mass==0));
204 if((_only_charge == json_nuc.Z) && (_only_mass == 0)) do_push =
true;
205 if((_only_charge == json_nuc.Z) && (_only_mass == json_nuc.A)) do_push =
true;
206 if((_only_charge == 0) && (_only_mass == json_nuc.A)) do_push =
true;
209 nuclei[json_nuc.Z][json_nuc.A] = json_nuc;
212 glog.progress_bar(NNucs,inuc,message.data());
217 fstream file (_gs_filename, ios::in);
221 if(!getline(file,line))
return 1;
224 std::map<int,tkn::tkstring> gs_columns;
225 for(
const auto &cname : line.
tokenize(
",")) gs_columns[ic++] = cname;
228 while(getline(file, line))
230 std::map<tkn::tkstring, tkn::tkstring> values;
234 for(
auto val : line.
tokenize(
",")) {val.remove_all(
" "); values[gs_columns[ic]] = val; ic++;}
237 if(!nread.
contains(
tkstring::form(
"(%d,%d)",values[
"z"].atoi(),values[
"n"].atoi()+values[
"z"].atoi())))
continue;
238 auto& nuc = nuclei[values[
"z"].atoi()][values[
"n"].atoi()+values[
"z"].atoi()];
239 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};
240 if(!values[
"radius"].is_empty())nuc.radius = {values[
"radius"].atof(),values[
"unc_r"].atof(),-1.,-1.,
"fm",
"",
true};
241 if(!values[
"electric_quadrupole"].is_empty()) nuc.electric_quadrupole = {values[
"electric_quadrupole"].atof(),values[
"unc_eq"].atof(),-1.,-1.,
"barn",
"",
true};
242 if(!values[
"magnetic_dipole"].is_empty()) nuc.magnetic_dipole = {values[
"magnetic_dipole"].atof(),values[
"unc_md"].atof(),-1.,-1.,
"mun",
"",
true};
243 if(!values[
"discovery"].is_empty()) nuc.year = values[
"discovery"].atoi();
247 fDataBase->exec_sql(
"BEGIN TRANSACTION");
250 for(
auto &z: nuclei) {
251 for(
auto &a: z.second) {
254 fill_isotope(a.second);
256 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));
257 glog.progress_bar(NNucs,inuc,message.data());
262 fDataBase->exec_sql(
"END TRANSACTION");
264 fDataBase->exec_sql(
"CREATE INDEX element_index ON isotope(element_id)");
265 fDataBase->exec_sql(
"CREATE INDEX mass_index ON isotope(mass)");
275 auto to_number = [](
const json &value) {
276 if(value.is_string())
return value.get<
tkstring>().atof();
277 if(value.is_number())
return value.get<
double>();
280 bool value_set =
false;
281 for(
auto &_item: entry.items()) {
282 const auto &_key = _item.key();
283 const auto &_val = _item.value();
284 if(_key ==
"formats")
continue;
285 if(_key ==
"uncertainty") {
286 if(_val.is_object()) {
287 const auto type = _val.value(
"type",
"");
288 if(type ==
"symmetric") _data.
err = to_number(_val.at(
"value"));
289 else if(type ==
"range") {
290 if(_val.contains(
"upperLimit") && _val.contains(
"lowerLimit")) {
291 const double upper = to_number(_val.at(
"upperLimit"));
292 const double lower = to_number(_val.at(
"lowerLimit"));
293 if(!value_set) _data.
value = 0.5 * (upper + lower);
300 _data.
err = to_number(_val);
303 else if(_key ==
"value") {
304 _data.
value = to_number(_val);
307 else if(_key ==
"unit") _data.
unit = _val.get<tkstring>();
308 else if(_key ==
"evaluatorInput")
continue;
309 else if(_key ==
"isSystematics" && (_val ==
"true" || (_val.is_boolean() && _val.get<
bool>()))) _data.
info.
append(
";ERR=SY");
311 glog <<
error << key <<
": unkown key: " << _key <<
" type: "<< _item.value().type_name() <<
do_endl;
312 cout << _val << endl;
317 if(entry.contains(
"formats") && entry.at(
"formats").contains(
"STD")) {
318 tkstring format = entry.at(
"formats").at(
"STD").get<tkstring>();
321 if(tokens.size()==2) {
322 _data.
err = tokens.back().
atof();
329tkisotope_builder::json_nucleus tkisotope_builder::read_nucleus(json &entry) {
332 for(
auto &item: entry.items())
334 auto &key = item.key();
335 auto &val = item.value();
336 if(key ==
"name") nuc.name = val;
337 else if(key ==
"z") nuc.Z = val;
338 else if(key ==
"n") nuc.N = val;
339 else if(key ==
"a") nuc.A = val;
340 else if(key ==
"bindingEnergy")
continue;
341 else if(key ==
"bindingEnergyLDMFit")
continue;
342 else if(key ==
"levels") {
344 auto is_ground_state = [](
const json &level) {
345 if(!level.contains(
"energy"))
return false;
346 const auto &energy = level.at(
"energy");
347 if(!energy.is_object() || !energy.contains(
"value"))
return false;
348 const auto &energy_val = energy.at(
"value");
349 if(energy_val.is_string())
return energy_val.get<tkstring>().atof() == 0.0;
350 if(energy_val.is_number())
return energy_val.get<
double>() == 0.0;
353 const json *level_ptr =
nullptr;
354 const auto it = std::find_if(val.begin(), val.end(), is_ground_state);
355 bool picked_ground = (it != val.end());
356 if(picked_ground) level_ptr = &(*it);
357 else if(!val.empty()) level_ptr = &val.front();
358 if(!level_ptr)
continue;
359 for(
auto &_item: level_ptr->items()) {
360 const auto &_key = _item.key();
361 const auto &_val = _item.value();
362 if(_key ==
"decayModes") {
363 if(_val.is_object() && (_val.contains(
"observed") || _val.contains(
"predicted"))) {
364 if(_val.contains(
"observed")) {
365 for(
const auto &mode : _val.at(
"observed")) {
366 tkstring type = mode.value(
"mode",
"");
367 tkstring ratio =
"-1";
368 if(mode.contains(
"value")) {
369 if(mode.at(
"value").is_string()) ratio = mode.at(
"value").get<tkstring>();
370 else if(mode.at(
"value").is_number()) ratio =
tkstring::form(
"%g", mode.at(
"value").get<
double>());
372 nuc.decay_modes.emplace_back(type, ratio.
atof());
375 if(_val.contains(
"predicted")) {
376 for(
const auto &mode : _val.at(
"predicted")) {
377 tkstring type = mode.value(
"mode",
"");
378 tkstring ratio =
"-1";
379 nuc.decay_modes.emplace_back(type, ratio.
atof());
383 for(
auto &mode: _val.items()) {
384 if(mode.value().size()==3) {
385 tkstring type = mode.value().at(
"name");
386 tkstring symbol = mode.value().at(
"symbol");
393 else ratio = mode.value().at(
"value");
394 nuc.decay_modes.emplace_back(type,ratio.
atof());
397 tkstring type = mode.value().at(
"name");
399 tkstring symbol =
"=";
400 tkstring ratio =
"-1";
401 nuc.decay_modes.emplace_back(type,ratio.
atof());
406 else if(_key ==
"energy") {
407 if(_val.empty())
continue;
408 if(_val.size()<2)
continue;
410 const auto &energy_val = _val.at(
"value");
411 if(energy_val.is_string()) ener = energy_val.get<tkstring>().atof();
412 else if(energy_val.is_number()) ener = energy_val.get<
double>();
413 if(ener != 0. && picked_ground) {
414 glog <<
error << nuc.name <<
": level is not ground state ! " << _val <<
do_endl;
417 else if(_key ==
"massExcess") read_measure(_key, _val, nuc.mass_excess);
418 else if(_key ==
"abundance") {
419 read_measure(_key, _val, nuc.abundance,
true);
420 nuc.abundance.unit =
"%";
423 else if(_key ==
"halflife" || _key ==
"spinAndParity" || _key ==
"spinParity")
continue;
425 glog <<
error <<
"levels: unkown key: " << _key <<
" type: "<< _item.value().type_name() <<
do_endl;
426 cout << _val << endl;
430 else if(key ==
"pairingGap")
continue;
431 else if(key ==
"qValues")
continue;
432 else if(key ==
"separationEnergies")
continue;
433 else if(key ==
"webLinks")
continue;
434 else if(key ==
"BE4DBE2")
continue;
435 else if(key ==
"excitedStateEnergies") {
436 for(
auto &_item: val.items()) {
437 const auto &_key = _item.key();
438 const auto &_val = _item.value();
439 if(_key ==
"firstExcitedStateEnergy")
continue;
440 if(_key ==
"firstTwoPlusEnergy")
continue;
441 if(_key ==
"firstFourPlusEnergy")
continue;
442 if(_key ==
"firstFourPlusOverFirstTwoPlusEnergy")
continue;
443 if(_key ==
"firstThreeMinusEnergy")
continue;
444 glog <<
error << key <<
": unkown key: " << _key <<
" type: "<< _item.value().type_name() <<
do_endl;
445 cout << _val << endl;
448 else if(key ==
"fissionYields") {
449 for(
auto &_item: val.items()) {
450 const auto &_key = _item.key();
451 const auto &_val = _item.value();
452 if(_key ==
"FY235U") read_measure(_key, _val, nuc.FY235U);
453 else if(_key ==
"FY238U") read_measure(_key, _val, nuc.FY238U);
454 else if(_key ==
"FY239Pu") read_measure(_key, _val, nuc.FY239Pu);
455 else if(_key ==
"FY241Pu") read_measure(_key, _val, nuc.FY241Pu);
456 else if(_key ==
"FY252Cf") read_measure(_key, _val, nuc.FY252Cf);
457 else if(_key ==
"cFY235U") read_measure(_key, _val, nuc.cFY235U);
458 else if(_key ==
"cFY238U") read_measure(_key, _val, nuc.cFY238U);
459 else if(_key ==
"cFY239Pu") read_measure(_key, _val, nuc.cFY239Pu);
460 else if(_key ==
"cFY241Pu") read_measure(_key, _val, nuc.cFY241Pu);
461 else if(_key ==
"cFY252Cf") read_measure(_key, _val, nuc.cFY252Cf);
463 glog <<
error << key <<
": unkown key: " << _key <<
" type: "<< _item.value().type_name() <<
do_endl;
464 cout << _val << endl;
468 else if(key ==
"quadrupoleDeformation") read_measure(key, val, nuc.quadrupoleDeformation);
469 else if(key ==
"thermalNeutronCapture")
continue;
470 else if(key ==
"thermalNeutronFission")
continue;
471 else if(key ==
"discovery")
continue;
474 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