37#include <boost/filesystem.hpp>
38#include <boost/algorithm/string.hpp>
79 std::string err =
"<data_path> content is missing!";
84 std::string err =
"<rge_fln_pre> content is missing!";
89 std::string err =
"no implantation energies present!";
115 if (!strcmp(str,
"trim_sp")) {
117 }
else if (!strcmp(str,
"data_path") &&
isTrimSp) {
119 }
else if (!strcmp(str,
"rge_fln_pre") &&
isTrimSp) {
121 }
else if (!strcmp(str,
"energy") &&
isTrimSp) {
123 }
else if (!strcmp(str,
"energy_vect") &&
isTrimSp) {
125 if (attributes ==
nullptr) {
127 msg =
"Found energy_list without attributes";
131 if (attributes->GetEntries() != 3) {
133 msg =
"energy_list: expect 3 attributes (start, stop, step), found " + std::to_string(attributes->GetEntries());
140 int start=-1, stop=-1, step=-1, ival;
141 TIter next(attributes);
142 while ((attr = (TXMLAttr*) next())) {
144 strncpy(sval, attr->GetValue(),
sizeof(sval));
146 ival = std::stoi(sval);
147 }
catch(std::invalid_argument& e) {
149 msg =
"The found energy_list attribute '" + std::string(sval) +
"' which is not a number";
152 }
catch(std::out_of_range& e) {
154 msg =
"The found energy_list attribute '" + std::string(sval) +
"' which is out-of-range.";
159 msg =
"The found energy_list attribute '" + std::string(sval) +
"' which generates an error.";
163 if (!strcmp(attr->GetName(),
"start")) {
165 }
else if (!strcmp(attr->GetName(),
"stop")) {
167 }
else if (!strcmp(attr->GetName(),
"step")) {
172 if ((start == -1) || (stop == -1) || (step == -1)) {
174 msg =
"Found energy_list with missing attributes. Needed start, stop and step.";
179 if ((start > stop)) {
181 msg =
"Found energy_list with start > stop. Not allowed in the context.";
187 msg =
"Found energy_list with step < 0. Not allowed in the context.";
196 }
while (ival <= stop);
213 if (!strcmp(str,
"trim_sp")) {
239 std::string msg(
""), sstr(str);
251 ival = std::stoi(str, &pos);
252 }
catch(std::invalid_argument& e) {
254 msg =
"The found energy '" + sstr +
"' which is not a number";
256 }
catch(std::out_of_range& e) {
258 msg =
"The found energy '" + sstr +
"' which is out-of-range.";
262 msg =
"The found energy '" + sstr +
"' which generates an error.";
265 if (pos != sstr.length()) {
267 msg =
"The found energy '" + sstr +
"' which is not an integer";
304 std::cerr << std::endl <<
"PXmlRgeHandler **WARNING** " << str;
305 std::cerr << std::endl;
321 std::cerr << std::endl <<
"PXmlRgeHandler **ERROR** " << str;
322 std::cerr << std::endl;
337 std::cerr << std::endl <<
"PXmlRgeHandler **FATAL ERROR** " << str;
338 std::cerr << std::endl;
382 std::cerr << std::endl;
383 std::cerr <<
"**ERROR** NO xml file name provided." << std::endl;
384 std::cerr << std::endl;
390 if (!boost::filesystem::exists(fln)) {
391 std::cerr << std::endl;
392 std::cerr <<
"**ERROR** xml file named: " << fln <<
" does not exist." << std::endl;
393 std::cerr << std::endl;
399 std::unique_ptr<PXmlRgeHandler> xmlRge = std::make_unique<PXmlRgeHandler>();
400 if (xmlRge ==
nullptr) {
401 std::cerr << std::endl;
402 std::cerr <<
"**ERROR** couldn't invoke PXmlRgeHandler." << std::endl;
403 std::cerr << std::endl;
409 std::unique_ptr<TSAXParser> saxParser = std::make_unique<TSAXParser>();
410 if (saxParser ==
nullptr) {
411 std::cerr << std::endl;
412 std::cerr <<
"**ERROR** couldn't invoke TSAXParser." << std::endl;
413 std::cerr << std::endl;
417 saxParser->SetStopOnError();
420 saxParser->ConnectToHandler(
"PXmlRgeHandler", xmlRge.get());
421 int status = saxParser->ParseFile(fln.c_str());
423 std::cerr << std::endl;
424 std::cerr <<
"**ERROR** parsing the xml-file: " << fln <<
"." << std::endl;
425 std::cerr << std::endl;
429 if (xmlRge->IsValid())
438 const PIntVector energy = xmlRge->GetTrimSpDataVectorList();
439 for (
int i=0; i<energy.size(); i++) {
441 rgeFln = xmlRge->GetTrimSpDataPath();
442 if (rgeFln[rgeFln.size()-1] !=
'/')
444 rgeFln += xmlRge->GetTrimSpFlnPre();
445 rgeFln += std::to_string(energy[i]);
447 if (!boost::filesystem::exists(rgeFln)) {
449 std::cerr << std::endl;
450 std::cerr <<
"**ERROR** rge-file: " << rgeFln <<
" not found." << std::endl;
451 std::cerr << std::endl;
455 dataSet.
energy = energy[i];
456 dataSet.
depth.clear();
460 std::cerr << std::endl;
461 std::cerr <<
"**ERROR** read error in rge-file: " << rgeFln <<
" not found." << std::endl;
462 std::cerr << std::endl;
468 for (
int j=0; j<dataSet.
amplitude.size(); j++)
476 for (
int j=0; j<dataSet.
nn.size(); j++) {
478 zz = dataSet.
depth[j];
480 for (
int j=0; j<dataSet.
nn.size(); j++) {
484 fData.push_back(dataSet);
508 std::ifstream fin(fln);
512 std::string line, msg;
513 std::vector<std::string> tok;
518 while (fin.good() &&
fValid) {
519 std::getline(fin, line);
521 boost::algorithm::trim(line);
524 if (!std::isdigit(line[0]))
527 boost::algorithm::split(tok, line, boost::algorithm::is_any_of(
" \t"), boost::algorithm::token_compress_on);
528 if (tok.size() != 2) {
529 std::cerr << std::endl;
530 std::cerr <<
"**ERROR** in rge-file: " << fln <<
", unexpected number of tokens (" << tok.size() <<
")." << std::endl;
531 std::cerr << std::endl;
537 zz = std::stod(tok[0], &pos);
538 }
catch(std::invalid_argument& e) {
540 msg =
"The found depth '" + tok[0] +
"' which is not a number";
541 std::cerr << std::endl;
542 std::cerr <<
"**ERROR** in rge-file: " << fln <<
": lineNo: " << lineNo << std::endl;
543 std::cerr <<
" " << msg << std::endl;
544 std::cerr << std::endl;
545 }
catch(std::out_of_range& e) {
547 msg =
"The found depth '" + tok[0] +
"' which is out-of-range.";
548 std::cerr << std::endl;
549 std::cerr <<
"**ERROR** in rge-file: " << fln <<
": lineNo: " << lineNo << std::endl;
550 std::cerr <<
" " << msg << std::endl;
551 std::cerr << std::endl;
554 msg =
"The found depth '" + tok[0] +
"' which generates an error.";
555 std::cerr << std::endl;
556 std::cerr <<
"**ERROR** in rge-file: " << fln <<
": lineNo: " << lineNo << std::endl;
557 std::cerr <<
" " << msg << std::endl;
558 std::cerr << std::endl;
560 if (pos != tok[0].length()) {
562 msg =
"The found depth '" + tok[0] +
"' which is not an number.";
563 std::cerr << std::endl;
564 std::cerr <<
"**ERROR** in rge-file: " << fln <<
": lineNo: " << lineNo << std::endl;
565 std::cerr <<
" " << msg << std::endl;
566 std::cerr << std::endl;
570 nn = std::stod(tok[1], &pos);
571 }
catch(std::invalid_argument& e) {
573 msg =
"The found #particles '" + tok[1] +
"' which is not a number";
574 std::cerr << std::endl;
575 std::cerr <<
"**ERROR** in rge-file: " << fln <<
": lineNo: " << lineNo << std::endl;
576 std::cerr <<
" " << msg << std::endl;
577 std::cerr << std::endl;
578 }
catch(std::out_of_range& e) {
580 msg =
"The found #particles '" + tok[1] +
"' which is out-of-range.";
581 std::cerr << std::endl;
582 std::cerr <<
"**ERROR** in rge-file: " << fln <<
": lineNo: " << lineNo << std::endl;
583 std::cerr <<
" " << msg << std::endl;
584 std::cerr << std::endl;
587 msg =
"The found #particles '" + tok[1] +
"' which generates an error.";
588 std::cerr << std::endl;
589 std::cerr <<
"**ERROR** in rge-file: " << fln <<
": lineNo: " << lineNo << std::endl;
590 std::cerr <<
" " << msg << std::endl;
591 std::cerr << std::endl;
593 if (pos != tok[1].length()) {
595 msg =
"The found #particles '" + tok[1] +
"' which is not an integer.";
596 std::cerr << std::endl;
597 std::cerr <<
"**ERROR** in rge-file: " << fln <<
": lineNo: " << lineNo << std::endl;
598 std::cerr <<
" " << msg << std::endl;
599 std::cerr << std::endl;
601 data.
depth.push_back(zz/10.0);
625 for (
int i=0; i<
fData.size(); i++) {
626 if (fabs(
fData[i].energy-energy)*0.001 < 0.9){
652 if ((idx < 0) || (idx >=
fData.size()))
655 return fData[idx].depth[
fData[idx].depth.size()-1];
674 for (
int i=0; i<
fData.size(); i++) {
675 if (fabs(
fData[i].energy-energy)*0.001 < 0.90) {
683 return Get_n(idx, z);
704 if ((idx < 0) || (idx >=
fData.size()))
707 if ((z < 0.0) || (z >
GetZmax(idx)))
711 for (
int i=0; i<
fData[idx].depth.size(); i++) {
712 if (z <=
fData[idx].depth[i]) {
722 nn =
fData[idx].nn[pos] +
724 (z-
fData[idx].depth[pos])/(
fData[idx].depth[pos+1]-
fData[idx].depth[pos]);
745 for (
int i=0; i<
fData.size(); i++) {
746 if (fabs(
fData[i].energy-energy)*0.001 < 0.90) {
std::vector< Int_t > PIntVector
ClassImp(PRgeHandler) PRgeHandler
Constructor that loads TrimSP range distribution data.
ClassImpQ(PXmlRgeHandler) void PXmlRgeHandler
SAX callback invoked at the start of XML document parsing.
Manager for TrimSP range distribution data.
virtual Double_t Get_n(const Double_t energy, const Double_t z)
Returns normalized particle distribution at given energy and depth.
PRgeHandler(std::string fln="")
Constructor that loads TrimSP data from XML configuration.
virtual bool ReadRgeFile(const std::string fln, PRgeData &data)
Reads a single RGE file and populates a PRgeData structure.
bool fValid
Validity flag (true if all RGE files loaded successfully)
virtual Double_t GetZmax(const Double_t energy)
Returns maximum penetration depth for a given energy.
virtual Int_t GetEnergyIndex(const Double_t energy)
Finds the data set index for a given energy.
PRgeDataList fData
Collection of RGE data sets (one per energy)
XML SAX parser handler for TrimSP configuration files.
bool isTrimSp
True when inside <trim_sp> element.
std::string fTrimSpFlnPre
RGE filename prefix (e.g., "LCCO_E" for LCCO_E1000.rge)
virtual void OnCdataBlock(const char *str, Int_t len)
Called for CDATA blocks (SLOT)
virtual void OnEndElement(const char *str)
Called when XML end tag is encountered (SLOT)
virtual void OnComment(const char *str)
Called for XML comments (SLOT)
std::string fTrimSpDataPath
Directory path to RGE files.
virtual void OnStartElement(const char *str, const TList *attributes)
Called when XML start tag is encountered (SLOT)
virtual void OnCharacters(const char *str)
Called for element content between tags (SLOT)
virtual void OnStartDocument()
Called at start of XML document parsing (SLOT)
PIntVector fTrimSpDataEnergyList
List of implantation energies in eV.
virtual void OnFatalError(const char *str)
Called when parser encounters a fatal error (SLOT)
bool fIsValid
Validity flag (false if parsing errors occur)
virtual void OnEndDocument()
Called at end of XML document parsing, performs validation (SLOT)
virtual void OnWarning(const char *str)
Called when parser emits a warning (SLOT)
virtual void OnError(const char *str)
Called when parser encounters an error (SLOT)
EKeyWords fKey
Current parsing context/state.
Data structure for a single TrimSP range distribution at a given energy.
PDoubleVector amplitude
Number of particles at each depth (raw counts from TrimSP)
Double_t noOfParticles
Total number of particles (sum of amplitudes)
PDoubleVector nn
Normalized particle density where ∫nn(z)dz = 1.
Double_t energy
Implantation energy in eV.
PDoubleVector depth
Depth values in nanometers (nm)