19#include "tkdb_table.h"
20#include "tklevel_scheme.h"
23#include "tkdatabase.h"
50 if (fA < 0 || fZ < 0)
return;
51 init(_load_default_dataset);
73 vector<shared_ptr<tklevel>> res;
75 std::copy_if(levels.begin(), levels.end(), std::back_inserter(res),
76 [&_selection](
const auto &lvl) { return _selection(lvl); });
96 vector<shared_ptr<tkdecay>> res;
98 std::copy_if(decays.begin(), decays.end(), std::back_inserter(res),
99 [&_selection](
const auto &dec) { return _selection(dec); });
127 glog <<
info <<
" Level scheme of " << fnucleus <<
do_endl;
128 glog <<
info <<
" Options : 'dataset', 'level', 'decay'" <<
do_endl;
131 auto print_group = [&](
const tkstring &source_label) {
132 bool header_printed =
false;
133 for (
auto &dts : fmap_of_dataset) {
134 if (dts.second->get_source() != source_label)
continue;
135 if (!header_printed) {
136 glog <<
info <<
"--- " << source_label <<
" ---" <<
do_endl;
137 header_printed =
true;
139 glog <<
info << dts.second->get_name() <<
" (" << dts.first <<
")";
140 if (dts.second->has_date()) glog <<
" [" << dts.second->get_date() <<
"]";
142 if (_option.
contains(
"com") && dts.second->has_comment()) {
143 const size_t comment_prefix_size = 13;
144 const size_t content_col = comment_prefix_size + 2;
149 print_group(
"ENSDF");
150 print_group(
"XUNDL");
154 fmap_of_dataset[fdatasetid]->print(_data, _option);
157 int _current_data_set = fdatasetid;
158 for (
auto &dataset : fmap_of_dataset) {
159 glog <<
info <<
"dataset : " << dataset.second->get_name() <<
do_endl;
161 dataset.second->print(
"leveldecay");
174 if (fmap_of_dataset_name_id.count(_dataset_name) == 0) {
175 glog <<
warning <<
"dataset '" << _dataset_name <<
"' do not exist for " << fnucleus <<
do_endl;
179 fdatasetid = fmap_of_dataset_name_id[_dataset_name];
189 if (fmap_of_dataset.count(_dataset_id) == 0) {
190 glog <<
warning <<
"dataset with id '" << _dataset_id <<
"' do not exist for " << fnucleus <<
do_endl;
195 fdatasetid = _dataset_id;
196 fmap_of_dataset[fdatasetid]->load_dataset();
218 const char *sep =
"";
226 if (array.size() != 2) {
227 glog <<
error <<
" <nuclear_level_scheme::get_level_energy()> invalid argument '" << _name <<
"'. Syntax: '[spin][parity][rank]'." <<
do_endl;
232 rank = array.at(1).atoi();
235 for (
const auto &lvlp :
get_levels([](
auto lvl) {
return (lvl->get_spin_parity() !=
nullptr); })) {
236 auto jpistr = lvlp->get_spin_parity()->get_jpi_str();
245 }
else if (jpistr.equal_to(
tkstring::form(
"%s%s", spin.data(), sep))) {
250 if (idx == rank)
return lvlp;
266 const bool require_decay = _offset.
contains(
"dec");
268 shared_ptr<tklevel> clostest_lev;
269 double best_ediff = 1e6;
272 if (_offset != lev->get_offset_bandhead())
continue;
274 if (_offset.
is_empty() && !lev->get_offset_bandhead().is_empty())
continue;
275 if (require_decay && lev->get_decays_down().empty())
continue;
277 if (ediff < best_ediff) {
287 const auto name = fnucleus +
" : ADOPTED LEVELS, GAMMAS";
288 const auto id = fmap_of_dataset_name_id.find(name);
289 if (
id == fmap_of_dataset_name_id.end())
return nullptr;
290 const auto dataset = fmap_of_dataset.at(id->second);
291 dataset->load_dataset();
292 for (
const auto &level : dataset->get_levels()) {
293 if (!level->is_energy_offset() && level->get_energy() == 0.)
return level;
298void tklevel_scheme::init(
bool _load_default_dataset)
300 gdatabase->begin(
"dataset.dataset_id, dataset.dataset_name, dataset.dataset_comment, dataset.dataset_date, dataset.dataset_source",
301 "dataset INNER JOIN isotope on dataset.isotope_id=isotope.isotope_id INNER JOIN element on isotope.element_id=element.element_id",
302 tkstring::form(
"element.charge=%d AND isotope.mass=%d AND EXISTS (SELECT 1 FROM level WHERE level.dataset_id=dataset.dataset_id)", fZ, fA),
305 while (gdatabase->next(
tkstring::form(
"read_dataset_%s", fnucleus.data()))) {
306 tkdb_table &datasets = (*gdatabase)[
"DATASET"];
307 int ds_id = datasets[
"dataset_id"].get_value().atoi();
308 fmap_of_dataset_name_id[datasets[
"dataset_name"].get_value()] = ds_id;
309 auto ds = make_shared<tkdataset>(
tkdataset(fnucleus, fZ, fA, datasets[
"dataset_name"].get_value(), ds_id));
310 if (!datasets[
"dataset_comment"].is_empty()) ds->fdataset_comment = datasets[
"dataset_comment"].get_value();
311 if (!datasets[
"dataset_date"].is_empty()) ds->fdataset_date = datasets[
"dataset_date"].get_value();
312 if (!datasets[
"dataset_source"].is_empty()) ds->fdataset_source = datasets[
"dataset_source"].get_value();
313 fmap_of_dataset[ds_id] = ds;
315 tkstring default_dataset = fnucleus.data();
316 default_dataset +=
" : ADOPTED LEVELS, GAMMAS";
317 gdebug <<
"looking for dataset : " << default_dataset <<
do_endl;
318 bool found = (fmap_of_dataset_name_id.count(default_dataset) > 0);
319 gdebug << (found ?
"" :
"not ") <<
"found " << (found ? fmap_of_dataset_name_id[default_dataset.data()] : -1) <<
do_endl;
322 fdatasetid = fmap_of_dataset_name_id[default_dataset.data()];
325 for (
const auto &dts : fmap_of_dataset) {
326 glog <<
warning <<
tkstring::form(
"%5s", fnucleus.data()) <<
" -- no 'ADOPTED LEVELS' dataset : '" << dts.second->get_name() <<
"' used instead." <<
do_endl;
327 fdatasetid = dts.first;
332 if (fmap_of_dataset.empty()) {
333 tkstring datasetname =
"EMPTY";
335 fmap_of_dataset_name_id[datasetname] = fdatasetid;
336 fmap_of_dataset[fdatasetid] = make_shared<tkdataset>(tkdataset(fnucleus, fZ, fA, datasetname, fdatasetid));
342void tkdataset::check_yrast(shared_ptr<tklevel> _lvl)
345 if (_lvl->get_spin_parity()->get_spin().is_known()) {
346 int TwoJ = (int)(_lvl->get_spin_parity()->get_spin().get_value() * 2 + 0.5);
347 if (!fyrastmap_exact.count(TwoJ)) {
348 fyrastmap_exact[TwoJ] = _lvl;
349 _lvl->fisYrast_exact =
true;
352 if (!fyrastmap_uncertain.count(TwoJ)) {
353 fyrastmap_uncertain[TwoJ] = _lvl;
354 _lvl->fisYrast_uncertain =
true;
357 }
else if (!_lvl->get_spin_parity_str().is_empty() && !_lvl->get_spin_parity_str().contains(
",")) {
358 tkstring tmp = _lvl->get_spin_parity_str().copy().remove_all(
"(").remove_all(
")").remove_all(
"+").remove_all(
"-");
363 TwoJ = tmp.
atoi() * 2;
364 if (!fyrastmap_uncertain.count(TwoJ)) {
365 fyrastmap_uncertain[TwoJ] = _lvl;
366 _lvl->fisYrast_uncertain =
true;
372void tkdataset::load_dataset()
377 auto t_0 = std::chrono::high_resolution_clock::now();
378 gdebug <<
"loading levels for dataset '" << fname <<
"' of " << fnucleus <<
do_endl;
381 gdatabase->begin(
"level.*",
"level",
tkstring::form(
"dataset_id=%d", fid));
383 tkdb_table *levels = &(*gdatabase)[
"LEVEL"];
386 const auto magnetic_dipole_columns =
388 const auto electric_quadrupole_columns =
391 while (gdatabase->next()) {
392 tkdb_column *col = &(*levels)[
"level_id"];
395 gmanager->set_max_level_id(
id);
397 tkdb_table::measure_data_struct energy_struc;
400 shared_ptr<tklevel> lvl = make_shared<tklevel>(
id, energy_struc);
401 lvl->fbelongs_to_nucleus = fnucleus;
405 tkstring spin_parity_str =
"";
407 col = &(*levels)[
"level_spin_parity"];
409 col = &(*levels)[
"level_spin"];
411 col = &(*levels)[
"level_parity"];
414 if (!spin_parity_str.
is_empty()) lvl->set_jpi(spin, parity, spin_parity_str);
416 tkdb_table::measure_data_struct lifetime_struc;
418 if (lifetime_struc.
filled) lvl->set_lifetime(lifetime_struc);
420 tkdb_table::measure_data_struct magnetic_dipole_struc;
421 levels->
read_measure(magnetic_dipole_struc, magnetic_dipole_columns);
422 if (magnetic_dipole_struc.
filled) lvl->set_magnetic_dipole(magnetic_dipole_struc);
424 tkdb_table::measure_data_struct electric_quadrupole_struc;
425 levels->
read_measure(electric_quadrupole_struc, electric_quadrupole_columns);
426 if (electric_quadrupole_struc.
filled) lvl->set_electric_quadrupole(electric_quadrupole_struc);
428 col = &(*levels)[
"level_comment"];
430 col = &(*levels)[
"level_uncertain"];
433 flevels.push_back(lvl);
437 for (
const auto &lvl : flevels) {
438 fmapoflevels[lvl->get_id()] = lvl;
442 auto t_1 = std::chrono::high_resolution_clock::now();
443 gdebug <<
"loading decays for dataset '" << fname <<
"' of " << fnucleus <<
do_endl;
446 gdatabase->begin(
"decay.*",
"decay INNER JOIN level on decay.level_from_id=level.level_id ",
tkstring::form(
"dataset_id=%d", fid));
448 while (gdatabase->next()) {
450 int level_from = -1.;
453 tkdb_table *decay = &(*gdatabase)[
"DECAY"];
454 tkdb_column *col = &(*decay)[
"decay_id"];
457 gmanager->set_max_decay_id(
id);
459 col = &(*decay)[
"decay_type"];
461 col = &(*decay)[
"level_from_id"];
463 col = &(*decay)[
"level_to_id"];
466 shared_ptr<tkdecay> dec =
nullptr;
468 tkdb_table::measure_data_struct energy_struc;
472 dec = make_shared<tkgammadecay>(
id, level_from, level_to, energy_struc);
473 shared_ptr<tkgammadecay> gamma = dynamic_pointer_cast<tkgammadecay>(dec);
475 tkdb_table::measure_data_struct relative_intensity_struc;
476 decay->
read_measure(relative_intensity_struc,
"decay_relative_intensity");
477 if (relative_intensity_struc.
filled) gamma->set_relative_intensity(relative_intensity_struc);
479 col = &(*decay)[
"decay_multipolarity"];
482 tkdb_table::measure_data_struct mixing_ratio_struc;
483 decay->
read_measure(mixing_ratio_struc,
"decay_mixing_ratio");
484 if (mixing_ratio_struc.
filled) gamma->set_mixing_ratio(mixing_ratio_struc);
486 tkdb_table::measure_data_struct conv_coeff_struc;
487 decay->
read_measure(conv_coeff_struc,
"decay_conv_coeff");
488 if (conv_coeff_struc.
filled) gamma->set_conv_coeff(conv_coeff_struc);
491 tkdb_table::measure_data_struct transprob_struc;
493 if (transprob_struc.
filled) gamma->set_transition_probability(transprob_struc);
494 transprob_struc.
clear();
496 if (transprob_struc.
filled) gamma->set_transition_probability(transprob_struc);
497 transprob_struc.
clear();
499 if (transprob_struc.
filled) gamma->set_transition_probability(transprob_struc);
500 transprob_struc.
clear();
502 if (transprob_struc.
filled) gamma->set_transition_probability(transprob_struc);
506 col = &(*decay)[
"decay_comment"];
508 col = &(*decay)[
"decay_uncertain"];
511 fdecays.push_back(dec);
512 fdecays.back()->set_levels(fmapoflevels.at(level_from), fmapoflevels.at(level_to));
514 for (
auto &dec : fdecays) {
515 fmapoflevels.at(dec->get_level_from_id())->add_decay_down(dec);
516 fmapoflevels.at(dec->get_level_to_id())->add_decay_up(dec);
520 auto t_2 = std::chrono::high_resolution_clock::now();
522 auto dt01 = std::chrono::duration<double, std::milli>(t_1 - t_0).count() * 0.001;
523 auto dt12 = std::chrono::duration<double, std::milli>(t_2 - t_1).count() * 0.001;
525 gdebug << std::fixed << std::setprecision(4) <<
"time level: "
529 gdebug << std::fixed << std::setprecision(4) <<
"time decays: "
544 glog <<
info <<
"dataset '" << fname <<
"' contains " << flevels.size() <<
" levels" <<
do_endl;
545 glog <<
info <<
"dataset '" << fname <<
"' contains " << fdecays.size() <<
" decays" <<
do_endl;
546 bool first_level_printed =
false;
547 for (
auto &lev : flevels) {
548 if (_option.
contains(
"yrastt") && !lev->is_yrast(
true))
550 else if (_option.
contains(
"yrast") && !_option.
contains(
"yrastt") && !lev->is_yrast())
552 if (first_level_printed) cout << std::endl;
553 first_level_printed =
true;
555 for (
auto &dec : lev->get_decays_down()) {
556 tkstring decay_option =
"quiet;levto";
557 if (_option.
contains(
"com")) decay_option +=
";com";
558 cout << setw(13) <<
"" <<
"-> ";
559 dec->print(decay_option);
562 }
else if (_data.
contains(
"level")) {
564 std::cout << std::setw(15) << left <<
"symbol" << std::setw(15) <<
"levelid"
565 << std::setw(15) << left <<
"energy (keV)"
566 << std::setw(15) << left <<
"energy error"
567 << std::setw(15) << left <<
"spin parity"
568 << std::setw(15) << left <<
"t1/2"
569 << std::setw(15) << left <<
"t1/2 error"
570 << std::setw(15) << left <<
"t1/2 unit" << std::endl;
572 glog <<
info <<
"dataset '" << fname <<
"' contains " << flevels.size() <<
" levels:" <<
do_endl;
573 for (
auto &lev : flevels) {
574 if (_option.
contains(
"yrastt") && !lev->is_yrast(
true))
576 else if (_option.
contains(
"yrast") && !_option.
contains(
"yrastt") && !lev->is_yrast())
578 if (_option.
contains(
"tab")) std::cout << std::setw(15) << left << fnucleus;
581 }
else if (_data.
contains(
"decay")) {
583 std::cout << std::setw(15) << left <<
"symbol" << std::setw(15) << left <<
"decayid" << std::setw(15) << left <<
"energy (keV)" << std::setw(15) << left <<
"energy error (keV)" << std::endl;
585 glog <<
info <<
"dataset '" << fname <<
"' contains " << fdecays.size() <<
" decays:" <<
do_endl;
586 for (
auto &dec : fdecays) {
587 if (_option.
contains(
"tab")) std::cout << std::setw(15) << left << fnucleus;
609 double spin_val = -1.;
610 int parity_val = -1.;
613 shared_ptr<tklevel> lvl = make_shared<tklevel>(gmanager->get_new_level_id(), lvl_properties);
620 lvl->set_jpi(spin_val, parity_val, _jpistr);
623 lvl->fbelongs_to_nucleus = fnucleus;
626 auto it = std::lower_bound(flevels.begin(), flevels.end(), lvl,
627 [](
const std::shared_ptr<tklevel> &a,
const std::shared_ptr<tklevel> &b) {
628 return a->get_energy() < b->get_energy();
630 flevels.insert(it, lvl);
633 fmapoflevels[lvl->get_id()] = lvl;
656 if (_ener == 0.) _ener = _lvlfrom->get_energy() - _lvlto->get_energy();
660 shared_ptr<tkgammadecay> decay = make_shared<tkgammadecay>(gmanager->get_new_decay_id(), _lvlfrom->get_id(), _lvlto->get_id(), energy_struc);
661 decay->set_levels(_lvlfrom, _lvlto);
662 fdecays.push_back(decay);
663 _lvlfrom->add_decay_down(decay);
664 _lvlto->add_decay_up(decay);
Represents a dataset of nuclear levels and decays for a given nucleus.
shared_ptr< tklevel > add_level(double _ener, double _unc, tkstring _unit, tkstring _jpistr)
manually add a new level to the dataset
shared_ptr< tkgammadecay > add_gamma_decay(shared_ptr< tklevel > _lvlfrom, shared_ptr< tklevel > _lvlto, double _ener=0., double _unc=0.)
add a new decay between two levels to the dataset
tkstring get_value() const
Representaiton of a sqlite data table.
void read_measure(measure_data_struct &_struct, const tkstring &_col_base_name)
measure_columns get_measure_columns(const tkstring &_col_base_name)
Manages the available datasets for a given nucleus.
void print(const tkstring &_data="", const tkstring &_option="")
print the level scheme information
const std::vector< shared_ptr< tklevel > > & get_levels()
get the vector containing all the levels
shared_ptr< tklevel > get_ground_state()
bool select_dataset(const tkstring &_dataset_name)
select a dataset using its name
const shared_ptr< tkdataset > & get_dataset()
returns the current dataset
shared_ptr< tklevel > get_level(const tkstring &_name, bool _exact=true)
get the level corresponding to the given name
tklevel_scheme(const tkstring &_nuc, int _zz, int _aa, bool _load_default_dataset=true)
const std::vector< shared_ptr< tkdecay > > & get_decays()
get the vector containing all the decays
Nuclear excited state parity.
virtual void set(const tkstring &_st)
define the parity from a string
virtual bool is_parity(tkparity::eparity _parity) const
test the parity value
bool is_known() const
to get some information about this data
Nuclear excited state spin.
double get_value() const
To get the spin as a double.
void set(int n, int d=1)
define the spin value
std::string with usefull tricks from TString (ROOT) and KVString (KaliVeda) and more....
tkstring strip_all_extra_white_space() const
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)
int atoi() const
Converts a string to integer value.
bool contains(const char *_pat, ECaseCompare _cmp=kExact) const
double atof() const
Converts a string to double value.
std::string wrap_text(const tkstring &_text, size_t _first_content_col, size_t _continuation_col, size_t _max_line_width=80)
tklog & error(tklog &log)
tklog & do_endl(tklog &log)
tklog & warning(tklog &log)
tklog & comment(tklog &log)
data structure used to fill a tkmeasure object from the sqlite database