TkN 2.4
Toolkit for Nuclei
Loading...
Searching...
No Matches
tklevel_scheme.cpp
1/********************************************************************************
2 * Copyright (c) : Université de Lyon 1, CNRS/IN2P3, UMR5822, *
3 * IP2I, F-69622 Villeurbanne Cedex, France *
4 * Normandie Université, ENSICAEN, UNICAEN, CNRS/IN2P3, *
5 * LPC Caen, F-14000 Caen, France *
6 * Contibutor(s) : *
7 * Jérémie Dudouet jeremie.dudouet@cnrs.fr [2020] *
8 * Diego Gruyer diego.gruyer@cnrs.fr [2020] *
9 * *
10 * Licensed under the MIT License <http://opensource.org/licenses/MIT>. *
11 * SPDX-License-Identifier: MIT *
12 ********************************************************************************/
13
14#ifdef HAS_DEBUG
15#include <algorithm>
16#include <chrono>
17#endif
18
19#include "tkdb_table.h"
20#include "tklevel_scheme.h"
21#include "tkstring.h"
22#include "tklog.h"
23#include "tkdatabase.h"
24#include "tkmanager.h"
25
26namespace tkn {
44}
45
46using namespace tkn;
47
48tklevel_scheme::tklevel_scheme(const tkstring &_nuc, int _zz, int _aa):fnucleus(_nuc), fA(_aa), fZ(_zz)
49{
50 if(fA<0||fZ<0) return;
51 init();
52}
53
71std::vector<shared_ptr<tklevel>> tklevel_scheme::get_levels(const std::function<bool (shared_ptr<tklevel>)> &_selection)
72{
73 vector<shared_ptr<tklevel>> res;
74 const auto &levels = get_levels();
75 std::copy_if(levels.begin(), levels.end(), std::back_inserter(res),
76 [&_selection](const auto &lvl) { return _selection(lvl); });
77 return res;
78}
79
94std::vector<shared_ptr<tkdecay>> tklevel_scheme::get_decays(const std::function<bool (shared_ptr<tkdecay>)> &_selection)
96 vector<shared_ptr<tkdecay>> res;
97 const auto &decays = get_decays();
98 std::copy_if(decays.begin(), decays.end(), std::back_inserter(res),
99 [&_selection](const auto &dec) { return _selection(dec); });
100 return res;
101}
102
103
118| | |
119|---|---|
120| tab | print data as sorted in a tabular view |
121| yrast | only confirmed yrast levels will be printed |
122| yrastt | only confirmed and tentative yrast levels will be printed |
123| com | print comments |
124*/
125void tklevel_scheme::print(const tkstring &_data, const tkstring &_option)
126{
127 if(_data.is_empty()) {
128 glog << info << " Level scheme of " << fnucleus << do_endl;
129 glog << info << " Options : 'dataset', 'level', 'decay'" << do_endl;
130 }
131 if(_data.contains("dataset")){
132 glog << info << "Available datasets are : " << do_endl;
133 for(auto &dts : fmap_of_dataset) glog << info << dts.second->get_name() << " (" << dts.first << ")" << do_endl;
134 glog << comment << "Current dataset is '" << get_dataset()->get_name() << "'" << " (" << get_dataset()->get_id() << ")" << do_endl;
135 }
136 if(_data.contains("level")||_data.contains("decay")){
137 fmap_of_dataset[fdatasetid]->print(_data, _option);
138 }
139 if(_data == "*") {
140 int _current_data_set = fdatasetid;
141 for(auto &dataset: fmap_of_dataset) {
142 glog << info << "dataset : " << dataset.second->get_name() << do_endl;
143 select_dataset(dataset.first);
144 dataset.second->print("leveldecay");
145 }
146 // to select back the current dataset
147 select_dataset(_current_data_set);
148 }
149}
150
155bool tklevel_scheme::select_dataset(const tkstring &_dataset_name)
156{
157 if(fmap_of_dataset_name_id.count(_dataset_name)==0) {
158 glog << warning << "dataset '" << _dataset_name << "' do not exist for " << fnucleus << do_endl;
159 print("dataset");
160 return false;
161 }
162 fdatasetid = fmap_of_dataset_name_id[_dataset_name];
163 return select_dataset(fdatasetid);
164}
165
170bool tklevel_scheme::select_dataset(int _dataset_id)
171{
172 if(fmap_of_dataset.count(_dataset_id)==0) {
173 glog << warning << "dataset with id '" << _dataset_id << "' do not exist for " << fnucleus << do_endl;
174 print("dataset");
175 return false;
176 }
177
178 fdatasetid = _dataset_id;
179 fmap_of_dataset[fdatasetid]->load_dataset();
180 return true;
181}
182
195shared_ptr<tklevel> tklevel_scheme::get_level(const tkstring &_name, bool _exact)
196{
197 // get a specific level [spin][parity][rank] (ex: 0+1 for the first 0+ state)
198 string spin;
199 int rank;
200
201 const char* sep = "";
202 if(_name.contains("+")) {sep = "+";}
203 else if(_name.contains("-")) {sep = "-";}
204
205 auto array = _name.tokenize(sep);
206 if(array.size()!=2) {
207 glog << error << " <nuclear_level_scheme::get_level_energy()> invalid argument '" << _name << "'. Syntax: '[spin][parity][rank]'." << do_endl;
208 return nullptr;
209 }
210
211 spin = array.at(0);
212 rank = array.at(1).atoi();
213
214 int idx = 0;
215 for(const auto &lvlp : get_levels([](auto lvl) {return (lvl->get_spin_parity()!=nullptr);})) {
216 auto jpistr = lvlp->get_spin_parity()->get_jpi_str();
217 bool ok=false;
218 if(!_exact) {
219 if(jpistr.equal_to(tkstring::form("%s%s",spin.data(),sep)) ||
220 jpistr.equal_to(tkstring::form("(%s%s)",spin.data(),sep)) ||
221 jpistr.equal_to(tkstring::form("(%s)%s",spin.data(),sep)) ||
222 jpistr.equal_to(tkstring::form("%s(%s)",spin.data(),sep))) {
223 ok = true;
224 }
225 }
226 else if(jpistr.equal_to(tkstring::form("%s%s",spin.data(),sep))) {
227 ok = true;
228 }
229 if(ok) {
230 idx++;
231 if(idx==rank) return lvlp;
232 }
233 }
234 return nullptr;
235}
236
242 * if offset is set to *, all offset values will be considered.
243 * if offset contains "dec", only levels that have known decays will be considered
244 */
245shared_ptr<tklevel> tklevel_scheme::get_level(double _energy, tkstring _offset)
246{
247 shared_ptr<tklevel> clostest_lev;
248 double best_ediff=1e6;
249 for(const auto &lev: get_levels()) {
250 if(!_offset.is_empty() && !_offset.contains("*")) {
251 if(_offset != lev->get_offset_bandhead()) continue;
252 }
253 if(_offset.is_empty() && !lev->get_offset_bandhead().is_empty()) continue;
254 if(_offset.contains("dec") && lev->get_decays_down().size()==0) continue;
255 double ediff = abs(lev->get_energy(tkunit_manager::units_keys::keV,true)-_energy);
256 if(ediff<best_ediff) {
257 best_ediff=ediff;
258 clostest_lev = lev;
259 }
260 }
261 return clostest_lev;
262}
263
264void tklevel_scheme::init()
265{
266 gdatabase->begin("DISTINCT dataset.dataset_id, dataset.dataset_name","level INNER JOIN dataset on level.dataset_id=dataset.dataset_id INNER JOIN isotope on level.isotope_id=isotope.isotope_id INNER JOIN element on isotope.element_id=element.element_id",tkstring::form("element.charge=%d AND isotope.mass=%d",fZ,fA), tkstring::form("read_dataset_%s",fnucleus.data()));
267
268 while(gdatabase->next(tkstring::form("read_dataset_%s",fnucleus.data()))) {
269 tkdb_table& datasets = (*gdatabase)["DATASET"];
270 fmap_of_dataset_name_id[datasets["dataset_name"].get_value()] = datasets["dataset_id"].get_value().atoi();
271 fmap_of_dataset[datasets["dataset_id"].get_value().atoi()] = make_shared<tkdataset>(tkdataset(fnucleus,fZ,fA,datasets["dataset_name"].get_value(),datasets["dataset_id"].get_value().atoi()));
272 }
273 tkstring default_dataset = fnucleus.data();
274 default_dataset += " : ADOPTED LEVELS, GAMMAS";
275 gdebug << "looking for dataset : " << default_dataset << do_endl;
276 bool found = (fmap_of_dataset_name_id.count(default_dataset)>0);
277 gdebug << (found?"":"not ") << "found " << (found?fmap_of_dataset_name_id[default_dataset.data()]:-1) << do_endl;
278
279 if(found) select_dataset(fmap_of_dataset_name_id[default_dataset.data()]);
280 else{
281 for(const auto &dts : fmap_of_dataset) {
282 glog << warning << tkstring::form("%5s",fnucleus.data()) << " -- no 'ADOPTED LEVELS' dataset : '" << dts.second->get_name() << "' used instead." << do_endl;
283 select_dataset(dts.first);
284 break;
285 }
286 }
287 if(fmap_of_dataset.empty()) {
288 tkstring datasetname = "EMPTY";
289 fdatasetid = 0;
290 fmap_of_dataset_name_id[datasetname] = fdatasetid;
291 fmap_of_dataset[fdatasetid] = make_shared<tkdataset>(tkdataset(fnucleus,fZ,fA,datasetname,fdatasetid));
293
294 floaded = true;
295}
296
297void tkdataset::check_yrast(shared_ptr<tklevel> _lvl)
298{
299 // check Yrast
300 if(_lvl->get_spin_parity()->get_spin().is_known()) {
301 int TwoJ = (int)(_lvl->get_spin_parity()->get_spin().get_value()*2+0.5);
302 if(!fyrastmap_exact.count(TwoJ)) {
303 fyrastmap_exact[TwoJ] = _lvl;
304 _lvl->fisYrast_exact = true;
305 // cout<<"exact yrast: 2J:"<<TwoJ<<" "<<lvl->get_spin_parity_str()<<" "<<lvl->get_energy()<<endl;
306 }
307 if(!fyrastmap_uncertain.count(TwoJ)) {
308 fyrastmap_uncertain[TwoJ] = _lvl;
309 _lvl->fisYrast_uncertain = true;
310 // cout<<"uncertain yrast: 2J:"<<TwoJ<<" "<<lvl->get_spin_parity_str()<<" "<<lvl->get_energy()<<endl;
311 }
312 }
313 else if(!_lvl->get_spin_parity_str().is_empty() && !_lvl->get_spin_parity_str().contains(",")) {
314 tkstring tmp = _lvl->get_spin_parity_str().copy().remove_all("(").remove_all(")").remove_all("+").remove_all("-");
315 int TwoJ;
316 if(tmp.contains("/2")) TwoJ = tmp.remove_all("/2").atoi();
317 else TwoJ = tmp.atoi()*2;
318 if(!fyrastmap_uncertain.count(TwoJ)) {
319 fyrastmap_uncertain[TwoJ] = _lvl;
320 _lvl->fisYrast_uncertain = true;
321 // cout<<"uncertain yrast: 2J:"<<TwoJ<<" "<<lvl->get_spin_parity_str()<<" "<<lvl->get_energy()<<endl;
322 }
323 }
324}
325
326void tkdataset::load_dataset()
327{
328 if(floaded) return;
329
330#ifdef HAS_DEBUG
331 auto t_0 = std::chrono::high_resolution_clock::now();
332 gdebug << "loading levels for dataset '" << fname << "' of " << fnucleus << do_endl;
333#endif
334
335 gdatabase->begin("DISTINCT level.*","level",tkstring::form("dataset_id=%d",fid));
336
337 while(gdatabase->next()) {
338 tkdb_table *levels = &(*gdatabase)["LEVEL"];
339 tkdb_column *col = &(*levels)["level_id"];
340 int id = col->get_value().atoi();
341
342 gmanager->set_max_level_id(id);
343
344 tkdb_table::measure_data_struct energy_struc;
345 levels->read_measure(energy_struc, "level_energy");
346
347 shared_ptr<tklevel> lvl = make_shared<tklevel>(id,energy_struc);
348 lvl->fbelongs_to_nucleus = fnucleus;
349
350 double spin = -1.;
351 int parity = -1.;
352 tkstring spin_parity_str = "";
353
354 col = &(*levels)["level_spin_parity"];
355 if(!col->is_empty()) spin_parity_str = col->get_value();
356 col = &(*levels)["level_spin"];
357 if(!col->is_empty()) spin = col->get_value().atof();
358 col = &(*levels)["level_parity"];
359 if(!col->is_empty()) parity = col->get_value().atoi();
360
361 if(!spin_parity_str.is_empty()) lvl->set_jpi(spin,parity,spin_parity_str);
362
363 tkdb_table::measure_data_struct lifetime_struc;
364 levels->read_measure(lifetime_struc, "level_lifetime");
365 if(lifetime_struc.filled) lvl->set_lifetime(lifetime_struc);
366
367 col = &(*levels)["level_comment"];
368 if(!col->is_empty()) lvl->set_comment(col->get_value());
369 col = &(*levels)["level_uncertain"];
370 if(!col->is_empty()) lvl->set_uncertain_level(col->get_value());
371
372 flevels.push_back(lvl);
373
374 check_yrast(lvl);
375 }
376 for(const auto &lvl: flevels) {
377 fmapoflevels[lvl->get_id()] = lvl;
378 }
379
380#ifdef HAS_DEBUG
381 auto t_1 = std::chrono::high_resolution_clock::now();
382 gdebug << "loading decays for dataset '" << fname << "' of " << fnucleus << do_endl;
383#endif
384
385 gdatabase->begin("DISTINCT decay.*","decay INNER JOIN level on decay.level_from_id=level.level_id ",tkstring::form("dataset_id=%d",fid));
386
387 while(gdatabase->next()) {
388 int dectype=-1;
389 int level_from = -1.;
390 int level_to = -1.;
391
392 tkdb_table *decay = &(*gdatabase)["DECAY"];
393 tkdb_column *col = &(*decay)["decay_id"];
394 int id = col->get_value().atoi();
395
396 gmanager->set_max_decay_id(id);
397
398 col = &(*decay)["decay_type"];
399 if(!col->is_empty()) dectype = col->get_value().atoi();
400 col = &(*decay)["level_from_id"];
401 if(!col->is_empty()) level_from = col->get_value().atoi();
402 col = &(*decay)["level_to_id"];
403 if(!col->is_empty()) level_to = col->get_value().atoi();
404
405 shared_ptr<tkdecay> dec = nullptr;
406
407 tkdb_table::measure_data_struct energy_struc;
408 decay->read_measure(energy_struc, "decay_energy");
409
410 if(dectype == tkdecay::kgamma) {
411 dec = make_shared<tkgammadecay>(id, level_from, level_to, energy_struc);
412 shared_ptr<tkgammadecay> gamma = dynamic_pointer_cast<tkgammadecay>(dec);
413
414 tkdb_table::measure_data_struct relative_intensity_struc;
415 decay->read_measure(relative_intensity_struc, "decay_relative_intensity");
416 if(relative_intensity_struc.filled) gamma->set_relative_intensity(relative_intensity_struc);
417
418 col = &(*decay)["decay_multipolarity"];
419 if(!col->is_empty()) gamma->set_multipolarity(col->get_value());
420
421 tkdb_table::measure_data_struct mixing_ratio_struc;
422 decay->read_measure(mixing_ratio_struc, "decay_mixing_ratio");
423 if(mixing_ratio_struc.filled) gamma->set_mixing_ratio(mixing_ratio_struc);
424
425 tkdb_table::measure_data_struct conv_coeff_struc;
426 decay->read_measure(conv_coeff_struc, "decay_conv_coeff");
427 if(conv_coeff_struc.filled) gamma->set_conv_coeff(conv_coeff_struc);
428
429 // transition probabilities
430 tkdb_table::measure_data_struct transprob_struc;
431 decay->read_measure(transprob_struc, "decay_BE");
432 if(transprob_struc.filled) gamma->set_transition_probability(transprob_struc);
433 transprob_struc.clear();
434 decay->read_measure(transprob_struc, "decay_BEW");
435 if(transprob_struc.filled) gamma->set_transition_probability(transprob_struc);
436 transprob_struc.clear();
437 decay->read_measure(transprob_struc, "decay_BM");
438 if(transprob_struc.filled) gamma->set_transition_probability(transprob_struc);
439 transprob_struc.clear();
440 decay->read_measure(transprob_struc, "decay_BMW");
441 if(transprob_struc.filled) gamma->set_transition_probability(transprob_struc);
442 }
443 else continue;
444
445 col = &(*decay)["decay_comment"];
446 if(!col->is_empty()) dec->set_comment(col->get_value());
447 col = &(*decay)["decay_uncertain"];
448 if(!col->is_empty()) dec->set_uncertain_decay(col->get_value());
449
450 fdecays.push_back(dec);
451 fdecays.back()->set_levels(fmapoflevels.at(level_from),fmapoflevels.at(level_to));
452 }
453 for(auto &dec: fdecays) {
454 fmapoflevels.at(dec->get_level_from_id())->add_decay_down(dec);
455 fmapoflevels.at(dec->get_level_to_id())->add_decay_up(dec);
456 }
457
458
459#ifdef HAS_DEBUG
460 auto t_2 = std::chrono::high_resolution_clock::now();
461
462 auto dt01 = std::chrono::duration<double, std::milli>(t_1-t_0).count() * 0.001; // open db time
463 auto dt12 = std::chrono::duration<double, std::milli>(t_2-t_1).count() * 0.001; // first read loop with views
464
465 gdebug << std::fixed << std::setprecision(4) << "time level: "
466 << dt01
467 << " s" << do_endl;
468
469 gdebug << std::fixed << std::setprecision(4) << "time decays: "
470 <<dt12
471 << " s" << do_endl;
472#endif
473
474 floaded = true;
475}
476
481void tkdataset::print(const tkstring &_data, const tkstring &_option)
482{
483 if(_data.contains("level") && _data.contains("decay")) {
484 glog << info << "dataset '" << fname << "' contains " << flevels.size() << " levels" << do_endl;
485 glog << info << "dataset '" << fname << "' contains " << fdecays.size() << " decays" << do_endl;
486 for(auto &lev : flevels) {
487 if(_option.contains("yrastt") && !lev->is_yrast(true)) continue;
488 else if(_option.contains("yrast") && !_option.contains("yrastt") && !lev->is_yrast()) continue;
489 lev->print(_option);
490 for(auto &dec : lev->get_decays_down()) {
491 cout<<setw(13)<<""<<"-> ";dec->print("quiet;levto");
492 }
493 }
494 }
495 else if(_data.contains("level")) {
496 if(_option.contains("tab")){
497 std::cout << std::setw(15) << left << "symbol" << std::setw(15) << "levelid"
498 << std::setw(15) << left << "energy (keV)"
499 << std::setw(15) << left << "energy error"
500 << std::setw(15) << left << "spin parity"
501 << std::setw(15) << left << "t1/2"
502 << std::setw(15) << left << "t1/2 error"
503 << std::setw(15) << left << "t1/2 unit" << std::endl;}
504 else glog << info << "dataset '" << fname << "' contains " << flevels.size() << " levels:" << do_endl;
505 for(auto &lev : flevels) {
506 if(_option.contains("yrastt") && !lev->is_yrast(true)) continue;
507 else if(_option.contains("yrast") && !_option.contains("yrastt") && !lev->is_yrast()) continue;
508 if(_option.contains("tab")) std::cout << std::setw(15)<< left << fnucleus;
509 lev->print(_option);
510 }
511 }
512 else if(_data.contains("decay")) {
513 if(_option.contains("tab")) 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;
514 else glog << info << "dataset '" << fname << "' contains " << fdecays.size() << " decays:" << do_endl;
515 for(auto &dec : fdecays) {
516 if(_option.contains("tab")) std::cout << std::setw(15) << left << fnucleus;
517 dec->print(_option);
518 }
519 }
520}
521
522shared_ptr<tklevel> tkdataset::add_level(double _ener, double _unc, tkstring _unit, tkstring _jpistr)
523{
524 tkspin spin;
525 tkparity parity;
526 double spin_val = -1.;
527 int parity_val = -1.;
528
529 tkdb_table::measure_data_struct lvl_properties{_ener,_unc,0,0,_unit};
530 shared_ptr<tklevel> lvl = make_shared<tklevel>(gmanager->get_new_level_id(),lvl_properties);
531
532 spin.set(_jpistr);parity.set(_jpistr);
533 if(spin.is_known()) spin_val = spin.get_value();
534 if(parity.is_known()) parity_val = (parity.is_parity(tkparity::eparity::kParityMinus));
535
536 lvl->set_jpi(spin_val,parity_val,_jpistr);
537
538 // needs to generate a unique id for the level
539 lvl->fbelongs_to_nucleus = fnucleus;
540
541 // find the good position in the vector to be sorted by energy
542 auto it = std::lower_bound(flevels.begin(), flevels.end(), lvl,
543 [](const std::shared_ptr<tklevel>& a, const std::shared_ptr<tklevel>& b) {
544 return a->get_energy() < b->get_energy();
545 });
546 flevels.insert(it, lvl);
547
548 check_yrast(lvl);
549 fmapoflevels[lvl->get_id()] = lvl;
550
551 return lvl;
552}
553
554shared_ptr<tkgammadecay> tkdataset::add_gamma_decay(shared_ptr<tklevel> _lvlfrom, shared_ptr<tklevel> _lvlto, double _ener, double _unc)
555{
556 if(_ener==0.) _ener = _lvlfrom->get_energy() - _lvlto->get_energy();
557
558 tkdb_table::measure_data_struct energy_struc{_ener,_unc,0.,0.,"keV"};
559
560 shared_ptr<tkgammadecay> decay = make_shared<tkgammadecay>(gmanager->get_new_decay_id(), _lvlfrom->get_id(), _lvlto->get_id(), energy_struc);
561 decay->set_levels(_lvlfrom,_lvlto);
562 fdecays.push_back(decay);
563 _lvlfrom->add_decay_down(decay);
564 _lvlto->add_decay_up(decay);
565
566 return decay;
567}
568
570#ifdef HAS_ROOT
571ClassImp(tklevel_scheme);
572#endif
Stores information on a specific dataset.
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
friend class tklevel_scheme
tkstring get_value() const
Definition tkdb_column.h:38
Representaiton of a sqlite data table.
Definition tkdb_table.h:29
void read_measure(measure_data_struct &_struct, const tkstring &_col_base_name)
tklevel_scheme(const tkstring &_nuc, int _zz, int _aa)
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
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
const std::vector< shared_ptr< tkdecay > > & get_decays()
get the vector containing all the decays
virtual bool is_parity(tkparity::eparity _parity)
test the parity value
virtual void set(const tkstring &_st)
define the parity from a string
bool is_known() const
to get some information about this data
Definition tkproperty.h:68
double get_value()
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....
Definition tkstring.h:31
static const char * form(const char *_format,...)
Definition tkstring.cpp:408
std::vector< tkstring > tokenize(const tkstring &_delim=" ") const
Create a vector of string separated by at least one delimiter.
Definition tkstring.cpp:231
bool is_empty() const
Definition tkstring.h:140
tkstring & remove_all(const tkstring &_s1)
Definition tkstring.h:192
int atoi() const
Converts a string to integer value.
Definition tkstring.cpp:152
bool contains(const char *_pat, ECaseCompare _cmp=kExact) const
Definition tkstring.h:174
double atof() const
Converts a string to double value.
Definition tkstring.cpp:168
Definition tklog.cpp:16
tklog & info(tklog &log)
Definition tklog.h:313
tklog & error(tklog &log)
Definition tklog.h:344
tklog & do_endl(tklog &log)
Definition tklog.h:212
tklog & warning(tklog &log)
Definition tklog.h:331
tklog & comment(tklog &log)
Definition tklog.h:319