7#include "PAHEmissionModel.h"
10#define MYSQLPP_SSQLS_NO_STATICS
12#include "Parameters.h"
13#include "SpectralFitter.h"
20 std::set_new_handler(
nullptr);
22 time_t t = std::time(
nullptr);
24 struct tm *tm_s = std::localtime(&t);
28 std::strftime(str_t,
sizeof(str_t),
"%Y%m%d-%X - EXCEPTION: ", tm_s);
30 std::cerr << str_t <<
"Memory allocation failed";
42int main(
const int argc,
const char *argv[],
char ** ) {
44 std::set_new_handler(new_handler);
50 parameters.parse(argc, argv);
53 std::cerr << e.what() << std::endl;
62 pahdb.connect(parameters.getDatabase(), parameters.getHost(),
63 parameters.getUsername(), parameters.getPassword(),
64 parameters.getPort(), parameters.isCompress(),
65 parameters.getTimeout(), parameters.getSocket());
67 pahdb.setTable(parameters.getTable());
69 pahdb.setProgress(10.0);
72 std::cerr << e.what() << std::endl;
77 std::vector<std::vector<std::pair<double, double>>> transitions;
79 std::vector<std::vector<double>> spectra;
81 std::vector<double> grid;
83 std::vector<double> temperatures;
85 std::tuple<std::vector<double>, std::vector<double>, std::vector<double>>
94 if (parameters.getTool() == Parameters::Arg::CompareExperimentWithTheory) {
96 transitions = pahdb.getExperimentalAndTheoreticalTransitionsFromId(
97 parameters.getIds().at(0));
100 if (parameters.getTool() == Parameters::Arg::SpectralFit) {
102 FileInput fileinput(parameters.getInputFilename());
104 inputdata = fileinput.readFileFromDisk();
106 pahemissionmodel.setGrid(std::get<0>(inputdata));
108 std::array<double, 2> inputlimits;
110 inputlimits[0] = *max_element(std::get<0>(inputdata).begin(),
111 std::get<0>(inputdata).end());
113 inputlimits[1] = *min_element(std::get<0>(inputdata).begin(),
114 std::get<0>(inputdata).end());
116 if (parameters.getUnits() == Parameters::Arg::Wavelength) {
118 PAHEmissionModel::convertFromFrequencyToWavelength(inputlimits);
121 parameters.setPlotLimits(inputlimits);
123 spectralfitter.setSpectrum(std::get<1>(inputdata));
125 spectralfitter.setUncertainties(std::get<2>(inputdata));
129 pahemissionmodel.makeGrid(parameters.getPlotLimitsAsFrequencies().at(0),
130 parameters.getPlotLimitsAsFrequencies().at(1),
134 grid = pahemissionmodel.getGrid();
136 if (parameters.getTool() != Parameters::Arg::TemperatureStack) {
138 pahemissionmodel.setTransitions(
139 pahdb.getTransitionsFromIds(parameters.getIds()));
142 transitions = pahdb.getTransitionsFromId(parameters.getIds().at(0));
144 transitions = std::vector<std::vector<std::pair<double, double>>>(
145 parameters.getTemperaturesInKelvin().size(), transitions.at(0));
147 pahemissionmodel.setTransitions(transitions);
150 if (parameters.getTable() == PAHdb::Database::Experiment &&
151 (parameters.getModel() == Parameters::Arg::Temperature ||
152 parameters.getModel() == Parameters::Arg::Cascade)) {
153 std::vector<sql_properties> prop = pahdb.getPropertiesByIDs(
154 parameters.getIds());
156 std::vector<int> charges;
157 charges.reserve(parameters.getIds().size());
158 std::vector<int> carbons;
159 carbons.reserve(parameters.getIds().size());
160 for (
const auto &properties : prop) {
162 charges.push_back(properties.charge);
163 carbons.push_back(properties.n_c);
166 pahemissionmodel.useApproximate(charges, carbons);
169 switch (parameters.getModel()) {
171 case Parameters::Arg::FixedTemperature:
173 if (parameters.getTool() == Parameters::Arg::TemperatureStack) {
175 pahemissionmodel.applyBlackbodyWithTemperatureForEach(
176 parameters.getTemperaturesInKelvin());
179 pahemissionmodel.applyBlackbodyWithTemperature(
180 parameters.getTemperatureInKelvin());
185 case Parameters::Arg::Temperature:
187 pahemissionmodel.applyTemperatureWithEnergy(parameters.getEnergyInCGS(),
192 case Parameters::Arg::Cascade:
194 pahemissionmodel.applyCascadeWithEnergy(parameters.getEnergyInCGS(),
199 case Parameters::Arg::ZeroKelvin:
205 if (parameters.getShift() != 0.0) {
207 pahemissionmodel.shiftTransitions(parameters.getShift());
210 switch (parameters.getProfile()) {
212 case Parameters::Arg::Gaussian:
214 pahemissionmodel.getSpectraAndConvolveWithGaussianOfFHWM(
215 spectra, parameters.getFWHM());
218 case Parameters::Arg::Drude:
220 pahemissionmodel.getSpectraAndConvolveWithDrudeOfFHWM(
221 spectra, parameters.getFWHM());
224 case Parameters::Arg::Lorentzian:
227 pahemissionmodel.getSpectraAndConvolveWithLorentianOfFHWM(
228 spectra, parameters.getFWHM());
235 std::cerr << e.what() << std::endl;
239 pahdb.setError(e.what());
242 std::cerr << e.what() << std::endl;
250 pahdb.setProgress(60.0);
253 std::cerr << e.what() << std::endl;
258 std::vector<double> small;
260 std::vector<double> large;
262 std::vector<double> anion;
264 std::vector<double> neutral;
266 std::vector<double> cation;
268 if (parameters.getTool() == Parameters::Arg::SpectralFit) {
270 spectralfitter.setPool(spectra);
272 spectralfitter.fitSpectrum();
274 std::vector<unsigned int> indices = spectralfitter.getNonZeroIndices();
276 std::vector<int> ids;
278 for (
const auto index : indices) {
280 ids.push_back(parameters.getIds().at(index));
283 std::vector<sql_properties> prop =
284 pahdb.getPropertiesByIDs(ids);
286 small = std::vector<double>(grid.size(), 0.0);
288 large = std::vector<double>(grid.size(), 0.0);
290 anion = std::vector<double>(grid.size(), 0.0);
292 neutral = std::vector<double>(grid.size(), 0.0);
294 cation = std::vector<double>(grid.size(), 0.0);
298 for (
const auto &properties : prop) {
302 if (properties.n_c > 50) {
304 for (
auto &l : large) {
306 l += spectralfitter.getWeights().at(indices.at(j)) *
307 spectra.at(indices.at(j)).at(k++);
311 for (
auto &s : small) {
313 s += spectralfitter.getWeights().at(indices.at(j)) *
314 spectra.at(indices.at(j)).at(k++);
320 if (properties.charge < 0) {
322 for (
auto &a : anion) {
324 a += spectralfitter.getWeights().at(indices.at(j)) *
325 spectra.at(indices.at(j)).at(k++);
327 }
else if (properties.charge == 0) {
329 for (
auto &n : neutral) {
331 n += spectralfitter.getWeights().at(indices.at(j)) *
332 spectra.at(indices.at(j)).at(k++);
336 for (
auto &c : cation) {
338 c += spectralfitter.getWeights().at(indices.at(j)) *
339 spectra.at(indices.at(j)).at(k++);
349 pahdb.setProgress(80.0);
352 std::cerr << e.what() << std::endl;
359 canvas.setSize(parameters.getPlotSize());
361 canvas.setColor(
"ffffff");
363 canvas.setDefaultCharacterHeight(parameters.getPlotSize().at(1) * 2.0 /
370 plot.setXLimits(parameters.getPlotLimits());
372 plot.setDrawHorizontalFineGrid();
374 plot.setDrawVerticalFineGrid();
376 plot.getHorizontalGrid().setColor(
"dedede");
378 plot.getHorizontalGrid().setLineStyle(Plot::Style::Dashed);
380 plot.getVerticalGrid() = plot.getHorizontalGrid();
382 plot.getYAxis().at(0).setWriteLabelsParallel();
384 plot.getYAxis().at(0).setStyle(Axis::Style::WritePowerInFrame);
392 switch (parameters.getUnits()) {
394 case Parameters::Arg::Wavelength:
396 xtitle =
"#fiwavelength [micron]";
398 xtitle2 =
"#fifrequency [cm#u-1#d]";
400 if (parameters.getTool() != Parameters::Arg::CompareExperimentWithTheory) {
402 PAHEmissionModel::convertFromFrequencyToWavelength(grid);
405 PAHEmissionModel::convertFromFrequencyToWavelength(transitions);
409 case Parameters::Arg::Frequency:
412 xtitle =
"#fifrequency [cm#u-1#d]";
414 xtitle2 =
"#fiwavelength [micron]";
417 if (parameters.getTool() == Parameters::Arg::CompareExperimentWithTheory) {
419 ytitle =
"#fiintegrated cross-section [#fnx#fi10#u5#d cm/mol]";
420 }
else if (parameters.getModel() == Parameters::Arg::ZeroKelvin) {
422 ytitle =
"#ficross-section [#fnx#fi10#u5#d cm#u2#d/mol]";
423 }
else if (parameters.getModel() == Parameters::Arg::FixedTemperature ||
424 parameters.getModel() == Parameters::Arg::Temperature) {
426 ytitle =
"#fispectral radiance [erg/s/cm#u-1#d/PAH]";
427 }
else if (parameters.getModel() == Parameters::Arg::Cascade) {
429 ytitle =
"#firadiant energy [erg/cm#u-1#d/PAH]";
432 std::vector<Plot> plots;
444 point.setSymbol(256);
448 text.setJustification(Text::RightJustification);
450 text.setColor(
"0000ff");
452 std::vector<std::string> formulae;
456 std::vector<PAHGeometry> geometries;
458 geometries.reserve(2);
460 std::vector<double> sum;
462 std::ostringstream ostr;
464 std::array<double, 2> margins;
466 std::array<double, 2> newmargins;
470 std::array<int, 2> canvassize;
472 std::vector<bool> available;
474 available.reserve(3);
478 std::array<const char *, 3> annotations = {
"Laboratory",
"Harmonic Theory",
479 "Anharmonic Theory"};
481 switch (parameters.getTool()) {
483 case Parameters::Arg::Stack:
484 case Parameters::Arg::TemperatureStack:
486 canvassize[0] = canvas.getSize().at(0);
488 canvassize[1] = canvas.getSize().at(1) +
489 (spectra.size() - 1) * parameters.getPlotSize().at(1) *
490 (plot.getYMargins().at(1) - plot.getYMargins().at(0));
492 canvas.setSize(canvassize);
494 margins[0] = plot.getYMargins().at(0) * parameters.getPlotSize().at(1) /
495 canvas.getSize().at(1);
497 margins[1] = 1.0 - ((1.0 - plot.getYMargins().at(1)) *
498 parameters.getPlotSize().at(1)) /
499 canvas.getSize().at(1);
501 panels.setYMargins(margins);
503 panels.setLayout(1, spectra.size());
505 geometries = pahdb.getGeometriesFromIds(parameters.getIds());
507 std::for_each(geometries.begin(), geometries.end(),
508 std::mem_fn(&PAHGeometry::diagonalize));
510 for (
const auto &spectrum : spectra) {
512 plot.setAdvance(
false);
516 plot.setDrawHorizontalFineGrid();
518 plot.setDrawVerticalFineGrid();
520 plot.getXAxis().at(0).setDrawConventionalAxis(
false);
522 plot.getXAxis().at(0).setDrawUnconventionalAxis(
false);
524 plot.getXAxis().at(0).setDrawConventionalLabels(
false);
526 plot.getYAxis().at(0).setDrawConventionalAxis(
false);
528 plot.getYAxis().at(0).setDrawUnconventionalAxis(
false);
530 plot.getYAxis().at(0).setDrawConventionalLabels(
false);
533 MinMax::min_max(spectrum, MinMax::Nice | MinMax::MaxExtraRoom));
535 plots.push_back(plot);
539 plot.setDrawHorizontalFineGrid(
false);
541 plot.setDrawVerticalFineGrid(
false);
545 if (parameters.getTool() == Parameters::Arg::Stack) {
547 line.setColor(
"cccccc");
549 line.setLineWidth(5);
553 for (
const auto &bonds : geometries.at(i).getBonds()) {
555 for (
const auto &bond : bonds) {
557 line.setStartCoordinates(
558 (plot.getXLimits().at(1) + plot.getXLimits().at(0)) / 2.0 +
559 geometries.at(i)[j].getX() *
560 (plot.getXLimits().at(1) - plot.getXLimits().at(0)) /
561 (28.0 * parameters.getPlotSize().at(0) /
562 parameters.getPlotSize().at(1)),
563 (plot.getYLimits().at(1) + plot.getYLimits().at(0)) / 2.0 +
564 geometries.at(i)[j].getY() *
565 (plot.getYLimits().at(1) - plot.getYLimits().at(0)) /
567 geometries.at(i)[j].getZ());
569 line.setEndCoordinates(
570 (plot.getXLimits().at(1) + plot.getXLimits().at(0)) / 2.0 +
571 geometries.at(i)[bond].getX() *
572 (plot.getXLimits().at(1) - plot.getXLimits().at(0)) /
573 (28.0 * parameters.getPlotSize().at(0) /
574 parameters.getPlotSize().at(1)),
575 (plot.getYLimits().at(1) + plot.getYLimits().at(0)) / 2.0 +
576 geometries.at(i)[bond].getY() *
577 (plot.getYLimits().at(1) - plot.getYLimits().at(0)) /
579 geometries.at(i)[j].getZ());
587 for (
const auto &atom : geometries.at(i)) {
589 point.setCoordinates(
590 (plot.getXLimits().at(1) + plot.getXLimits().at(0)) / 2.0 +
592 (plot.getXLimits().at(1) - plot.getXLimits().at(0)) /
593 (28.0 * parameters.getPlotSize().at(0) /
594 parameters.getPlotSize().at(1)),
595 (plot.getYLimits().at(1) + plot.getYLimits().at(0)) / 2.0 +
597 (plot.getYLimits().at(1) - plot.getYLimits().at(0)) /
601 point.setColor(atom.getCPKColor());
603 point.setSize(atom.getSize() / 70.0);
608 plots.push_back(plot);
615 formulae = pahdb.getFormulaeFromIds(parameters.getIds());
617 if (parameters.getTool() != Parameters::Arg::TemperatureStack) {
619 text.setText(Text::formatChemicalFormula(formulae.at(i)));
621 text.setCoordinates(0.95, 0.85, 0.0, Text::CoordinateSystem::NORMAL);
625 plots.push_back(plot);
632 if ((parameters.getModel() != Parameters::Arg::ZeroKelvin &&
633 parameters.getModel() != Parameters::Arg::FixedTemperature) ||
634 parameters.getTool() == Parameters::Arg::TemperatureStack) {
638 ostr << static_cast<int>(
639 parameters.getTool() == Parameters::Arg::TemperatureStack
640 ? parameters.getTemperaturesInKelvin().at(i)
641 : temperatures.at(i))
644 text.setText(ostr.str());
646 text.setCoordinates(0.95, 0.75, 0.0, Text::CoordinateSystem::NORMAL);
650 plots.push_back(plot);
655 plot.getXAxis().at(0).setDrawConventionalAxis();
657 plot.getXAxis().at(0).setDrawUnconventionalAxis();
659 plot.getYAxis().at(0).setDrawConventionalAxis();
661 plot.getYAxis().at(0).setDrawUnconventionalAxis();
663 plot.getYAxis().at(0).setDrawConventionalLabels();
667 curve.setXAndY(grid, spectra.at(i++));
671 plot.setAdvance(
true);
673 plots.push_back(plot);
678 plots.front().getXAxis().at(0).setDrawConventionalLabels();
680 plots.front().getXAxis().at(0).setTitle(xtitle);
682 plots.back().getXAxis().at(0).setDrawUnconventionalAxis(
false);
684 plots.back().getXAxis().emplace_back();
686 plots.back().getXAxis().at(1).setDrawConventionalLabels(
false);
690 plots.back().getXAxis().at(1).setReciprocalLabelFormatter();
692 plots.back().getXAxis().at(1).setDrawConventionalAxis(
false);
694 plots.back().getXAxis().at(1).setDrawUnconventionalLabels();
696 plots.back().getXAxis().at(1).setTitle(xtitle2);
702 text.setColor(
"000000");
704 text.setText(ytitle);
706 text.setJustification(Text::CenterJustification);
714 panels.getYMargins().at(0) +
715 (panels.getYMargins().at(1) - panels.getYMargins().at(0)) / 2.0,
721 case Parameters::Arg::CompareExperimentWithTheory:
723 for (
const auto &t : transitions) {
725 available.emplace_back(t.size());
728 npanels = std::count(available.begin(), available.end(),
true);
730 canvassize[0] = canvas.getSize().at(0);
732 canvassize[1] = canvas.getSize().at(1) +
733 (npanels - 1) * parameters.getPlotSize().at(1) *
734 (plot.getYMargins().at(1) - plot.getYMargins().at(0));
736 canvas.setSize(canvassize);
738 margins[0] = plot.getYMargins().at(0) * parameters.getPlotSize().at(1) /
739 canvas.getSize().at(1);
741 margins[1] = 1.0 - ((1.0 - plot.getYMargins().at(1)) *
742 parameters.getPlotSize().at(1)) /
743 canvas.getSize().at(1);
747 plot.setAdvance(
false);
749 plot.getXAxis().at(0).setDrawConventionalAxis(
false);
751 plot.getXAxis().at(0).setDrawUnconventionalAxis(
false);
753 plot.getXAxis().at(0).setDrawConventionalLabels(
false);
755 plot.getYAxis().at(0).setDrawConventionalAxis(
false);
757 plot.getYAxis().at(0).setDrawUnconventionalAxis(
false);
759 plot.getYAxis().at(0).setDrawConventionalLabels(
false);
762 MinMax::min_max(transitions, MinMax::Nice | MinMax::MaxExtraRoom));
764 newmargins[0] = margins[0];
766 newmargins[1] = margins[0] + (margins[1] - margins[0]) / npanels;
768 plot.setYMargins(newmargins);
770 plots.push_back(plot);
774 newmargins[0] = newmargins[1];
776 newmargins[1] = newmargins[1] + (margins[1] - margins[0]) / npanels;
778 plot.setYMargins(newmargins);
780 plots.push_back(plot);
786 newmargins[0] = newmargins[1];
788 newmargins[1] = newmargins[1] + (margins[1] - margins[0]) / npanels;
790 plot.setYMargins(newmargins);
792 plots.push_back(plot);
799 geometries = pahdb.getGeometriesFromIds(parameters.getIds());
801 std::for_each(geometries.begin(), geometries.end(),
802 std::mem_fn(&PAHGeometry::diagonalize));
804 plot.setDrawHorizontalFineGrid(
false);
806 plot.setDrawVerticalFineGrid(
false);
808 plot.setYMargins(margins);
810 line.setColor(
"cccccc");
812 line.setLineWidth(5);
814 for (
const auto &bonds : geometries.at(0).getBonds()) {
816 for (
const auto bond : bonds) {
818 line.setStartCoordinates(
819 (plot.getXLimits().at(1) + plot.getXLimits().at(0)) / 2.0 +
820 geometries.at(0)[i].getX() *
821 (plot.getXLimits().at(1) - plot.getXLimits().at(0)) / 28.0,
822 (plot.getYLimits().at(1) + plot.getYLimits().at(0)) / 2.0 +
823 canvas.getAspectRatio() * geometries.at(0)[i].getY() *
824 (plot.getYLimits().at(1) - plot.getYLimits().at(0)) / 28.0,
825 geometries.at(0)[i].getZ());
827 line.setEndCoordinates(
828 (plot.getXLimits().at(1) + plot.getXLimits().at(0)) / 2.0 +
829 geometries.at(0)[bond].getX() *
830 (plot.getXLimits().at(1) - plot.getXLimits().at(0)) / 28.0,
831 (plot.getYLimits().at(1) + plot.getYLimits().at(0)) / 2.0 +
832 canvas.getAspectRatio() * geometries.at(0)[bond].getY() *
833 (plot.getYLimits().at(1) - plot.getYLimits().at(0)) / 28.0,
834 geometries.at(0)[bond].getZ());
844 for (
const auto &atom : geometries.at(0)) {
846 point.setCoordinates(
847 (plot.getXLimits().at(1) + plot.getXLimits().at(0)) / 2.0 +
849 (plot.getXLimits().at(1) - plot.getXLimits().at(0)) / 28.0,
850 (plot.getYLimits().at(1) + plot.getYLimits().at(0)) / 2.0 +
851 canvas.getAspectRatio() * atom.getY() *
852 (plot.getYLimits().at(1) - plot.getYLimits().at(0)) / 28.0,
855 point.setColor(atom.getCPKColor());
857 point.setSize(atom.getSize() / 40.0);
864 formulae = pahdb.getFormulaeFromIds(parameters.getIds());
866 text.setColor(
"0000ff");
870 text.setJustification(Text::RightJustification);
872 text.setText(Text::formatChemicalFormula(formulae.at(0)));
874 text.setCoordinates(0.95, 0.95, 0.0, Text::CoordinateSystem::NORMAL);
878 plots.push_back(plot);
882 plot.getXAxis().at(0).setTitle(xtitle);
884 plot.getXAxis().at(0).setDrawConventionalAxis();
888 plot.getXAxis().emplace_back();
890 plot.getXAxis().at(1).setDrawConventionalLabels(
false);
893 plot.getXAxis().at(0).setDrawConventionalLabels();
895 plot.getYAxis().at(0).setDrawConventionalAxis();
897 plot.getYAxis().at(0).setDrawUnconventionalAxis();
899 plot.getYAxis().at(0).setDrawConventionalLabels();
901 newmargins[0] = margins[0];
903 newmargins[1] = margins[0] + (margins[1] - margins[0]) / npanels;
905 plot.setYMargins(newmargins);
907 line.setLineWidth(4);
909 line.setColor(
"ff0000");
911 if (!available.at(i)) {
920 text.setJustification(Text::CenterJustification);
922 text.setText(annotations.at(i));
924 text.setCoordinates(0.5, 0.75, 0.0, Text::CoordinateSystem::NORMAL);
930 for (
const auto &transition : transitions.at(i++)) {
932 line.setStartCoordinates(transition.first, 0.0, 0.0);
934 line.setEndCoordinates(transition.first, transition.second, 0.0);
939 plots.push_back(plot);
943 newmargins[0] = newmargins[1];
945 newmargins[1] = newmargins[1] + (margins[1] - margins[0]) / npanels;
947 plot.setYMargins(newmargins);
951 plot.getXAxis().at(0).setTitle(
"");
953 plot.getXAxis().at(0).setDrawConventionalLabels(
false);
958 plot.getXAxis().emplace_back();
962 plot.getXAxis().at(1).setReciprocalLabelFormatter();
964 plot.getXAxis().at(0).setDrawUnconventionalAxis(
false);
966 plot.getXAxis().at(1).setDrawConventionalAxis(
false);
968 plot.getXAxis().at(1).setDrawConventionalLabels(
false);
970 plot.getXAxis().at(1).setDrawUnconventionalAxis();
972 plot.getXAxis().at(1).setDrawUnconventionalLabels();
974 plot.getXAxis().at(1).setTitle(xtitle2);
976 plot.getXAxis().at(0).setTitle(
"");
978 plot.getXAxis().at(0).setDrawZeroLine();
980 plot.getXAxis().at(0).setDrawConventionalLabels(
false);
983 if (!available.at(i)) {
990 text.setText(annotations.at(i));
992 text.setCoordinates(0.5, 0.75, 0.0, Text::CoordinateSystem::NORMAL);
998 for (
const auto &transition : transitions.at(i++)) {
1000 line.setStartCoordinates(transition.first, 0.0, 0.0);
1002 line.setEndCoordinates(transition.first, transition.second, 0.0);
1007 plots.push_back(plot);
1013 newmargins[0] = newmargins[1];
1015 newmargins[1] = newmargins[1] + (margins[1] - margins[0]) / npanels;
1017 plot.setYMargins(newmargins);
1021 plot.getXAxis().at(1).setReciprocalLabelFormatter();
1023 plot.getXAxis().at(0).setDrawUnconventionalAxis(
false);
1025 plot.getXAxis().at(1).setDrawConventionalAxis(
false);
1027 plot.getXAxis().at(1).setDrawConventionalLabels(
false);
1029 plot.getXAxis().at(1).setDrawUnconventionalAxis();
1031 plot.getXAxis().at(1).setDrawUnconventionalLabels();
1033 plot.getXAxis().at(1).setTitle(xtitle2);
1035 plot.getXAxis().at(0).setTitle(
"");
1037 plot.getXAxis().at(0).setDrawZeroLine();
1039 plot.getXAxis().at(0).setDrawConventionalLabels(
false);
1043 text.setText(annotations.at(i));
1045 text.setCoordinates(0.5, 0.75, 0.0, Text::CoordinateSystem::NORMAL);
1051 for (
const auto &transition : transitions.at(i)) {
1053 line.setStartCoordinates(transition.first, 0.0, 0.0);
1055 line.setEndCoordinates(transition.first, transition.second, 0.0);
1060 plots.push_back(plot);
1065 text.setColor(
"000000");
1067 text.setText(ytitle);
1069 text.setJustification(Text::CenterJustification);
1071 text.setAngle(90.0);
1075 text.setCoordinates(0.0723,
1076 margins[0] + (margins[1] - margins[0]) / npanels, 0.0);
1081 case Parameters::Arg::SpectralFit:
1085 curve.setXAndY(grid, std::get<1>(inputdata));
1087 if (std::get<2>(inputdata).size() == std::get<1>(inputdata).size()) {
1089 curve.setYErr(std::get<2>(inputdata));
1098 curve.setFill(
false);
1100 curve.setColor(
"dedede");
1102 sum = std::vector<double>(spectra.at(0).size());
1104 for (
auto &spectrum : spectra) {
1108 if (spectralfitter.getWeights().at(i) == 0.0) {
1115 for (
auto &s : spectrum) {
1117 s *= spectralfitter.getWeights().at(i);
1122 curve.setXAndY(grid, spectrum);
1129 curve.setXAndY(grid, sum);
1131 curve.setColor(
"ff0000");
1133 curve.setLineWidth(2);
1137 plot.setYLimits(MinMax::min_max(sum, MinMax::Nice));
1139 text.setJustification(Text::LeftJustification);
1141 text.setColor(
"ff0000");
1143 text.setText(
"total fit");
1145 text.setCoordinates(0.85, 0.90, 0.0, Text::CoordinateSystem::NORMAL);
1149 text.setColor(
"00ff00");
1151 text.setText(
"N#dC#u>50");
1153 text.setCoordinates(0.85, 0.83, 0.0, Text::CoordinateSystem::NORMAL);
1157 text.setColor(
"0000ff");
1159 text.setText(
"N#dC#u<50");
1161 text.setCoordinates(0.85, 0.76, 0.0, Text::CoordinateSystem::NORMAL);
1165 text.setColor(
"fff00f");
1167 text.setText(
"anion");
1169 text.setCoordinates(0.85, 0.69, 0.0, Text::CoordinateSystem::NORMAL);
1173 text.setColor(
"ff00ff");
1175 text.setText(
"neutral");
1177 text.setCoordinates(0.85, 0.62, 0.0, Text::CoordinateSystem::NORMAL);
1181 text.setColor(
"00ffff");
1183 text.setText(
"cation");
1185 text.setCoordinates(0.85, 0.55, 0.0, Text::CoordinateSystem::NORMAL);
1189 curve.setXAndY(grid, large);
1191 curve.setColor(
"00ff00");
1193 curve.setLineWidth(1);
1197 curve.setXAndY(grid, small);
1199 curve.setColor(
"0000ff");
1203 curve.setXAndY(grid, anion);
1205 curve.setColor(
"fff00f");
1209 curve.setXAndY(grid, neutral);
1211 curve.setColor(
"ff00ff");
1215 curve.setXAndY(grid, cation);
1217 curve.setColor(
"00ffff");
1221 plot.getXAxis().at(0).setTitle(xtitle);
1223 plot.getXAxis().emplace_back();
1227 plot.getXAxis().at(1).setReciprocalLabelFormatter();
1229 plot.getXAxis().at(0).setDrawUnconventionalAxis(
false);
1231 plot.getXAxis().at(1).setDrawConventionalAxis(
false);
1233 plot.getXAxis().at(1).setDrawConventionalLabels(
false);
1235 plot.getXAxis().at(1).setDrawUnconventionalAxis();
1237 plot.getXAxis().at(1).setDrawUnconventionalLabels();
1239 plot.getXAxis().at(1).setTitle(xtitle2);
1241 plot.getYAxis().at(0).setTitle(ytitle);
1243 plots.push_back(plot);
1249 ostr <<
"Euclidean distance norm: " << spectralfitter.getNorm();
1251 if (std::get<2>(inputdata).size() == std::get<1>(inputdata).size()) {
1252 ostr <<
" (NNLC; used provided uncertainties)";
1257 text.setColor(
"000000");
1259 text.setText(ostr.str());
1261 text.setCoordinates(0.25, 0.8, 0.0);
1266 case Parameters::Arg::CoAdd:
1269 sum = std::vector<double>(spectra.at(0).size());
1271 for (
const auto &spectrum : spectra) {
1275 for (
auto s : spectrum) {
1277 sum.at(j++) += s * parameters.getWeights().at(i);
1283 curve.setXAndY(grid, sum);
1287 plot.setYLimits(MinMax::min_max(sum, MinMax::Nice));
1289 plot.getXAxis().at(0).setTitle(xtitle);
1291 plot.getXAxis().emplace_back();
1295 plot.getXAxis().at(1).setReciprocalLabelFormatter();
1297 plot.getXAxis().at(0).setDrawUnconventionalAxis(
false);
1299 plot.getXAxis().at(1).setDrawConventionalAxis(
false);
1301 plot.getXAxis().at(1).setDrawConventionalLabels(
false);
1303 plot.getXAxis().at(1).setDrawUnconventionalAxis();
1305 plot.getXAxis().at(1).setDrawUnconventionalLabels();
1307 plot.getXAxis().at(1).setTitle(xtitle2);
1309 plot.getYAxis().at(0).setTitle(ytitle);
1311 plots.push_back(plot);
1318 std::string f(parameters.getOutputFilename());
1322 spectra.insert(spectra.begin(), grid);
1324 time_t t = time(
nullptr);
1326 std::vector<std::string> header{
"NASA Ames PAH IR Spectroscopic Database",
1327 std::string(
"Date: ") + ctime(&t),
1328 "Version : " PROGRAM_VERSION,
1329 "Build: " PROGRAM_BUILD,
1330 std::string(
"First column: ") + xtitle,
1331 std::string(
"Other columns: ") + ytitle};
1333 if (parameters.getTool() == Parameters::Arg::SpectralFit) {
1335 header.insert(header.end(), {
"First row: UIDs",
"Second row: weights"});
1337 std::ostringstream uids;
1339 uids << std::right << std::setw(12) << 0 <<
'\t';
1341 std::vector<sql_properties> prop = pahdb.getPropertiesByIDs(
1342 parameters.getIds());
1344 for (
const auto &properties : prop) {
1346 uids << std::right << std::setw(12) << properties.uid <<
'\t';
1349 header.insert(header.end(), {uids.str(),
"First row: weights"});
1351 spectra.at(0).insert(spectra.at(0).begin(), 0);
1353 for (
size_t i = 1; i < spectra.size(); i++) {
1355 spectra.at(i).insert(spectra.at(i).begin(),
1356 spectralfitter.getWeights().at(i - 1));
1360 fileoutput.writeTableHeaderToDisk(header);
1362 fileoutput.writeTableToDisk(spectra);
1364 if (parameters.isX11()) {
1366 canvas.paintOnScreen();
1369 if (parameters.isPNG()) {
1371 canvas.paintOnPNG(parameters.getOutputFilename());
1374 if (parameters.isJPEG()) {
1376 canvas.paintOnJPEG(parameters.getOutputFilename());
1379 if (parameters.isPostscript()) {
1380 canvas.paintOnPostscript(parameters.getOutputFilename());
1385 pahdb.setProgress(100.0);
1388 std::cerr << e.what() << std::endl;