SedSat3 1.1.6
Sediment Source Apportionment Tool - Advanced statistical methods for environmental pollution research
Loading...
Searching...
No Matches
conductor.cpp
Go to the documentation of this file.
1#include "conductor.h"
2#include "analysishost.h"
3#include "progressreporter.h"
4#include "results.h"
5#include "contribution.h"
6#include "resultitem.h"
7#include "testmcmc.h"
8#include "rangeset.h"
9
10
12 : data(nullptr),
13 host(host)
14{
15}
16
17bool Conductor::Execute(const string &command, map<string,string> arguments)
18{
19 results.clear();
21 return false;
22
23 if (command == "GA")
24 {
25 return ExecuteGA(arguments);
26 }
27 if (command == "GA (fixed elemental contribution)")
28 {
29 return ExecuteGA_FixedProfile(arguments);
30 }
31 if (command == "GA (disregarding targets)")
32 {
33 return ExecuteGA_NoTargets(arguments);
34 }
35 if (command == "Levenberg-Marquardt")
36 {
37 return ExecuteLevenbergMarquardt(arguments);
38 }
39 if (command == "Levenberg-Marquardt-Batch")
40 {
41 return ExecuteLevenbergMarquardtBatch(arguments);
42 }
43 if (command == "OM-Size Correct")
44 {
45 return ExecuteOMSizeCorrect(arguments);
46 }
47 if (command == "MLR")
48 {
49 return ExecuteMLR(arguments);
50 }
51 if (command == "CovMat")
52 {
53 return ExecuteCovarianceMatrix(arguments);
54 }
55 if (command == "CorMat")
56 {
57 return ExecuteCorrelationMatrix(arguments);
58 }
59 if (command == "DFA")
60 {
61 return ExecuteDFA(arguments);
62 }
63
64 if (command == "DFAOnevsRest")
65 {
66 return ExecuteDFAOnevsRest(arguments);
67 }
68 if (command == "DFAM")
69 {
70 return ExecuteDFAM(arguments);
71 }
72 if (command == "SDFA")
73 {
74 return ExecuteSDFA(arguments);
75 }
76
77 if (command == "SDFAM")
78 {
79 return ExecuteSDFAM(arguments);
80 }
81
82 if (command == "SDFAOnevsRest")
83 {
84 return ExecuteSDFAOnevsRest(arguments);
85 }
86
87 if (command == "KS")
88 {
89 return ExecuteKolmogorovSmirnov(arguments);
90 }
91 if (command == "KS-individual")
92 {
93 return ExecuteKolmogorovSmirnovIndividual(arguments);
94 }
95 if (command == "CMB Bayesian")
96 {
97 return ExecuteCMBBayesian(arguments);
98 }
99 if (command == "CMB Bayesian-Batch")
100 {
101 return ExecuteCMBBayesianBatch(arguments);
102 }
103 if (command == "Test CMB Bayesian")
104 {
105 return ExecuteTestCMBBayesian(arguments);
106 }
107
108 if (command == "DF")
109 {
110 return ExecuteDistributionFitting(arguments);
111 }
112
113 if (command == "Bracketing Analysis")
114 {
115 return ExecuteBracketingAnalysis(arguments);
116 }
117 if (command == "Bracketing Analysis Batch")
118 {
119 return ExecuteBracketingAnalysisBatch(arguments);
120 }
121 if (command == "BoxCox")
122 {
123 return ExecuteBoxCox(arguments);
124 }
125
126 if (command == "Outlier")
127 {
128 return ExecuteOutlierAnalysis(arguments);
129 }
130
131 if (command == "EDP")
132 {
133 return ExecuteEDP(arguments);
134 }
135
136 if (command == "EDPM")
137 {
138 return ExecuteEDPM(arguments);
139 }
140 if (command == "ANOVA")
141 {
142 return ExecuteANOVA(arguments);
143 }
144
145 if (command == "Error_Analysis")
146 {
147 return ExecuteErrorAnalysis(arguments);
148 }
149
150 if (command == "Source_Verify")
151 {
152 return ExecuteSourceVerify(arguments);
153 }
154
155 if (command == "AutoSelect")
156 {
157 return ExecuteAutoSelect(arguments);
158 }
159 Data()->AddtoToolsUsed(command);
160 return true;
161}
162
164{
165 if (_data==nullptr)
166 _data = Data();
167 vector<string> NegativeCheckResults =_data->NegativeValueCheck();
168
169 if (NegativeCheckResults.size()>0)
170 {
171 QString message;
172 for (unsigned int i=0; i<NegativeCheckResults.size(); i++)
173 {
174 message += QString::fromStdString(NegativeCheckResults[i]+"\n");
175 }
176 host->ShowWarning(message.toStdString());
177 return false;
178 }
179 return true;
180
181}
182
183bool Conductor::CheckNegativeElements(map<string,vector<string>> negative_elements)
184{
185 QString message;
186 for (map<string,vector<string>>::iterator it = negative_elements.begin(); it!=negative_elements.end(); it++)
187 {
188 if (it->second.size()>0)
189 { message += "For target sample '" + QString::fromStdString(it->first) + ":\n";
190 for (unsigned int i=0; i<it->second.size(); i++)
191 {
192 message += QString::fromStdString("\t" + it->second[i]) + "\n";
193 }
194 }
195
196 }
197
198 if (message!="")
199 { host->ShowWarning(message.toStdString());
200 return false;
201 }
202
203 return true;
204}
205
206bool Conductor::ExecuteGA(const std::map<std::string, std::string>& arguments)
207{
209
210 bool organic_size_correction;
211 if (arguments.at("Apply size and organic matter correction") == "true")
212 {
213 organic_size_correction = true;
214 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
215 {
216 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
217 return false;
218 }
219 }
220 else
221 {
222 organic_size_correction = false;
223 }
224
225 SourceSinkData corrected_data = Data()->CreateCorrectedDataset(
226 arguments.at("Sample"),
227 organic_size_correction,
228 Data()->GetElementInformation()
229 );
230
231 rtw->Start();
232 corrected_data.InitializeParametersAndObservations(arguments.at("Sample"));
233
234 if (!CheckNegativeElements(&corrected_data))
235 return false;
236
237 GA = std::make_unique<CGA<SourceSinkData>>(&corrected_data);
238 GA->filenames.pathname = workingfolder.toStdString() + "/";
239 GA->SetRunTimeWindow(rtw);
240 GA->SetProperties(arguments);
241 GA->InitiatePopulation();
242 GA->optimize();
243
244 results.SetName("GA " + arguments.at("Sample"));
245
246 ResultItem result_contribution = GA->Model_out.GetContribution();
247 result_contribution.SetShowTable(true);
248 result_contribution.SetType(result_type::contribution);
249 result_contribution.SetShowGraph(true);
250 results.Append(result_contribution);
251
252 ResultItem result_modeled_vs_measured = GA->Model_out.GetObservedvsModeledElementalProfile();
253 result_modeled_vs_measured.SetShowGraph(true);
254 result_modeled_vs_measured.SetShowTable(true);
255 results.Append(result_modeled_vs_measured);
256
257 ResultItem result_modeled_vs_measured_isotope = GA->Model_out.GetObservedvsModeledElementalProfile_Isotope();
258 result_modeled_vs_measured_isotope.SetShowGraph(true);
259 result_modeled_vs_measured_isotope.SetShowTable(true);
260 results.Append(result_modeled_vs_measured_isotope);
261
262 ResultItem result_calculated_means = GA->Model_out.GetCalculatedElementMeans();
263 result_calculated_means.SetShowTable(true);
264 result_calculated_means.SetShowGraph(false);
265 results.Append(result_calculated_means);
266
267 ResultItem result_estimated_means = GA->Model_out.GetEstimatedElementMean();
268 result_estimated_means.SetShowTable(true);
269 result_estimated_means.SetShowGraph(false);
270 results.Append(result_estimated_means);
271
272 ResultItem result_calculated_mu = GA->Model_out.GetCalculatedElementMu();
273 result_calculated_mu.SetShowTable(true);
274 result_calculated_mu.SetShowGraph(false);
275 results.Append(result_calculated_mu);
276
277 ResultItem result_estimated_mu = GA->Model_out.GetEstimatedElementMu();
278 result_estimated_mu.SetShowTable(true);
279 result_estimated_mu.SetShowGraph(false);
280 results.Append(result_estimated_mu);
281
282 ResultItem result_calculated_sigma = GA->Model_out.GetCalculatedElementSigma();
283 result_calculated_sigma.SetShowTable(true);
284 result_calculated_sigma.SetShowGraph(false);
285 results.Append(result_calculated_sigma);
286
287 ResultItem result_estimated_sigma = GA->Model_out.GetEstimatedElementSigma();
288 result_estimated_sigma.SetShowTable(true);
289 result_estimated_sigma.SetShowGraph(false);
290 results.Append(result_estimated_sigma);
291
292 return true;
293}
294
295
296bool Conductor::ExecuteGA_FixedProfile(const std::map<std::string, std::string>& arguments)
297{
299 rtw->SetTitle("Fitness", 0);
300 rtw->SetYAxisTitle("Fitness", 0);
301
302 bool organic_size_correction;
303 if (arguments.at("Apply size and organic matter correction") == "true")
304 {
305 organic_size_correction = true;
306 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
307 {
308 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
309 return false;
310 }
311 }
312 else
313 {
314 organic_size_correction = false;
315 }
316
317 SourceSinkData corrected_data = Data()->CreateCorrectedDataset(
318 arguments.at("Sample"),
319 organic_size_correction,
320 Data()->GetElementInformation()
321 );
322
323 if (!CheckNegativeElements(&corrected_data))
324 return false;
325
326 rtw->Start();
328 arguments.at("Sample"),
330 );
332
333 GA = std::make_unique<CGA<SourceSinkData>>(&corrected_data);
334 GA->filenames.pathname = workingfolder.toStdString() + "/";
335 GA->SetRunTimeWindow(rtw);
336 GA->SetProperties(arguments);
337 GA->InitiatePopulation();
338 GA->optimize();
339
340 results.SetName("GA (fixed profile) " + arguments.at("Sample"));
341
342 ResultItem result_contribution = GA->Model_out.GetContribution();
343 results.Append(result_contribution);
344
345 ResultItem result_modeled_vs_measured = GA->Model_out.GetObservedvsModeledElementalProfile(parameter_mode::direct);
346 results.Append(result_modeled_vs_measured);
347
348 ResultItem result_modeled_vs_measured_isotope = GA->Model_out.GetObservedvsModeledElementalProfile_Isotope(parameter_mode::direct);
349 results.Append(result_modeled_vs_measured_isotope);
350
351 return true;
352}
353
354bool Conductor::ExecuteGA_NoTargets(const std::map<std::string, std::string>& arguments)
355{
357 rtw->Start();
358
360 arguments.at("Sample"),
362 );
364
365 GA = std::make_unique<CGA<SourceSinkData>>(Data());
366 GA->filenames.pathname = workingfolder.toStdString() + "/";
367 GA->SetRunTimeWindow(rtw);
368 GA->SetProperties(arguments);
369 GA->InitiatePopulation();
370 GA->optimize();
371
372 results.SetName("GA (no targets) " + arguments.at("Sample"));
373
374 ResultItem result_calculated_means = GA->Model_out.GetCalculatedElementMeans();
375 results.Append(result_calculated_means);
376
377 ResultItem result_estimated_means = GA->Model_out.GetEstimatedElementMean();
378 results.Append(result_estimated_means);
379
380 ResultItem result_calculated_stds = GA->Model_out.GetCalculatedElementSigma();
381 results.Append(result_calculated_stds);
382
383 ResultItem result_estimated_stds = GA->Model_out.GetEstimatedElementSigma();
384 results.Append(result_estimated_stds);
385
386 return true;
387}
388
389bool Conductor::ExecuteLevenbergMarquardt(const std::map<std::string, std::string>& arguments)
390{
392
393 bool organic_size_correction;
394 if (arguments.at("Apply size and organic matter correction") == "true")
395 {
396 organic_size_correction = true;
397 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
398 {
399 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
400 return false;
401 }
402 }
403 else
404 {
405 organic_size_correction = false;
406 }
407
408 rtw->Start();
409
410 SourceSinkData corrected_data = Data()->CreateCorrectedDataset(
411 arguments.at("Sample"),
412 organic_size_correction,
413 Data()->GetElementInformation()
414 );
415
416 if (!CheckNegativeElements(&corrected_data))
417 return false;
418
419 corrected_data.InitializeParametersAndObservations(arguments.at("Sample"));
420 corrected_data.SetProgressReporter(rtw);
421
422 if (arguments.at("Softmax transformation") == "true")
423 {
425 }
426 else
427 {
429 }
430
431 results.SetName("LM " + arguments.at("Sample"));
432
433 ResultItem result_contribution = corrected_data.GetContribution();
434 result_contribution.SetShowTable(true);
435 results.Append(result_contribution);
436
437 ResultItem result_modeled = corrected_data.GetPredictedElementalProfile(parameter_mode::direct);
438 result_modeled.SetShowTable(true);
439 results.Append(result_modeled);
440
441 ResultItem result_modeled_vs_measured = corrected_data.GetObservedvsModeledElementalProfile();
442 result_modeled_vs_measured.SetShowTable(true);
443 results.Append(result_modeled_vs_measured);
444
445 ResultItem result_modeled_vs_measured_isotope = corrected_data.GetObservedvsModeledElementalProfile_Isotope(parameter_mode::direct);
446 result_modeled_vs_measured_isotope.SetShowTable(true);
447 results.Append(result_modeled_vs_measured_isotope);
448
449 return true;
450}
451
452bool Conductor::ExecuteLevenbergMarquardtBatch(const std::map<std::string, std::string>& arguments)
453{
455
456 bool organic_size_correction;
457 if (arguments.at("Apply size and organic matter correction") == "true")
458 {
459 organic_size_correction = true;
460 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
461 {
462 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
463 return false;
464 }
465 }
466 else
467 {
468 organic_size_correction = false;
469 }
470
471 rtw->Start();
472
474
475 CMBTimeSeriesSet* contributions;
476 std::map<std::string, std::vector<std::string>> negative_elements;
477
478 if (arguments.at("Softmax transformation") == "true")
479 {
480 contributions = new CMBTimeSeriesSet(Data()->LM_Batch(
482 organic_size_correction,
483 negative_elements
484 ));
485 }
486 else
487 {
488 contributions = new CMBTimeSeriesSet(Data()->LM_Batch(
490 organic_size_correction,
491 negative_elements
492 ));
493 }
494
495 if (negative_elements.size() > 0)
496 {
497 CheckNegativeElements(negative_elements);
498 }
499
500 results.SetName("LM-Batch");
501
502 contributions->GetOptions().X_suffix = "";
503 contributions->GetOptions().Y_suffix = "";
504 contributions->SetOption(options_key::single_column_x, true);
505
506 ResultItem contributions_result_item;
507 contributions_result_item.SetName("Levenberg-Marquardt-Batch");
508 contributions_result_item.SetResult(contributions);
509 contributions_result_item.SetType(result_type::stacked_bar_chart);
510 contributions_result_item.SetShowAsString(true);
511 contributions_result_item.SetShowTable(true);
512 contributions_result_item.SetShowGraph(true);
513 contributions_result_item.SetYLimit(_range::high, 1);
514 contributions_result_item.SetXAxisMode(xaxis_mode::counter);
515 contributions_result_item.setYAxisTitle("Contribution");
516 contributions_result_item.setXAxisTitle("Sample");
517 contributions_result_item.SetYLimit(_range::low, 0);
518
519 results.Append(contributions_result_item);
520
521 return true;
522}
523
524bool Conductor::ExecuteOMSizeCorrect(const std::map<std::string, std::string>& arguments)
525{
526 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
527 bool exclude_elements = (arguments.at("Use only selected elements") == "true");
528
529 Data()->SetSelectedTargetSample(arguments.at("Sample"));
530
532 exclude_samples,
533 exclude_elements,
534 true,
535 arguments.at("Sample")
536 );
537
538 std::vector<ResultItem> result_items = transformed_data.GetSourceProfiles();
539
540 results.SetName("Corrected Elemental Profiles for Target" + arguments.at("Sample"));
541
542 for (size_t i = 0; i < result_items.size(); i++)
543 {
544 results.Append(result_items[i]);
545 }
546
547 return true;
548}
549
550bool Conductor::ExecuteMLR(const std::map<std::string, std::string>& arguments)
551{
552 if (arguments.at("Organic Matter constituent") == "" &&
553 arguments.at("Particle Size constituent") == "")
554 {
555 host->ShowWarning("At least one of Organic Matter constituent and "
556 "Particle Size constituent must be selected");
557 return false;
558 }
559
560 results.SetName("MLR_vs_OM&Size ");
561
562 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
563
565 exclude_samples,
566 false,
567 false
568 );
569
570 double p_value_threshold = QString::fromStdString(arguments.at("P-value threshold")).toDouble();
571
572 if (arguments.at("Equation") == "Linear")
573 {
574 transformed_data.PerformRegressionVsOMAndSize(
575 arguments.at("Organic Matter constituent"),
576 arguments.at("Particle Size constituent"),
578 p_value_threshold
579 );
580 }
581 else
582 {
583 transformed_data.PerformRegressionVsOMAndSize(
584 arguments.at("Organic Matter constituent"),
585 arguments.at("Particle Size constituent"),
587 p_value_threshold
588 );
589 }
590
592 arguments.at("Organic Matter constituent"),
593 arguments.at("Particle Size constituent")
594 );
595
596 for (std::map<std::string, Elemental_Profile_Set>::iterator it = Data()->begin();
597 it != Data()->end();
598 ++it)
599 {
600 if (it->first != Data()->GetTargetGroup())
601 {
602 it->second.SetRegressionModels(transformed_data[it->first].GetRegressionModels());
603 }
604 }
605
606 std::vector<ResultItem> regression_results = transformed_data.GetMLRResults();
607
608 for (size_t i = 0; i < regression_results.size(); i++)
609 {
610 results.Append(regression_results[i]);
611 }
612
613 return true;
614}
615
616bool Conductor::ExecuteCovarianceMatrix(const std::map<std::string, std::string>& arguments)
617{
618 results.SetName("Covariance Matrix for " + arguments.at("Source/Target group"));
619
620 ResultItem covariance_matrix_item;
621 covariance_matrix_item.SetName("Covariance Matrix for " + arguments.at("Source/Target group"));
622 covariance_matrix_item.SetShowTable(true);
623 covariance_matrix_item.SetType(result_type::matrix);
624 covariance_matrix_item.SetShowGraph(false);
625
626 CMBMatrix* covariance_matrix = new CMBMatrix(
627 Data()->at(arguments.at("Source/Target group")).CalculateCovarianceMatrix()
628 );
629
630 covariance_matrix_item.SetResult(covariance_matrix);
631 results.Append(covariance_matrix_item);
632
633 return true;
634}
635
636
637bool Conductor::ExecuteCorrelationMatrix(const std::map<std::string, std::string>& arguments)
638{
639 results.SetName("Correlation Matrix for " + arguments.at("Source/Target group"));
640
641 ResultItem correlation_matrix_item;
642 correlation_matrix_item.SetName("Correlation Matrix");
643 correlation_matrix_item.SetShowTable(true);
644 correlation_matrix_item.setTableTitle("Correlation Matrix for source group '" +
645 arguments.at("Source/Target group") + "'");
646 correlation_matrix_item.SetType(result_type::matrix);
647 correlation_matrix_item.SetShowGraph(false);
648
649 double threshold = QString::fromStdString(arguments.at("Threshold")).toDouble();
650 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
651 bool exclude_elements = (arguments.at("Use only selected elements") == "true");
652
654 exclude_samples,
655 exclude_elements,
656 false
657 );
658
659 if (arguments.at("OM and Size Correct based on target sample") != "")
660 {
661 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
662 {
663 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
664 return false;
665 }
666 transformed_data = transformed_data.CreateCorrectedDataset(
667 arguments.at("OM and Size Correct based on target sample"),
668 true,
669 Data()->GetElementInformation()
670 );
671 }
672
673 CMBMatrix* correlation_matrix = new CMBMatrix(
674 transformed_data.at(arguments.at("Source/Target group")).CalculateCorrelationMatrix()
675 );
676
677 correlation_matrix->SetLimit(_range::high, threshold);
678 correlation_matrix->SetLimit(_range::low, -threshold);
679
680 correlation_matrix_item.SetResult(correlation_matrix);
681 results.Append(correlation_matrix_item);
682
683 return true;
684}
685
686bool Conductor::ExecuteDFA(const std::map<std::string, std::string>& arguments)
687{
688 if (arguments.at("Source/Target group I") == arguments.at("Source/Target group II"))
689 {
690 host->ShowWarning("The selected sources must be different");
691 return false;
692 }
693
695 rtw->Start();
696
697 results.SetName("DFA between " + arguments.at("Source/Target group I") +
698 "&" + arguments.at("Source/Target group II"));
699
700 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
701 bool exclude_elements = (arguments.at("Use only selected elements") == "true");
702
703 SourceSinkData transformed_data = *Data();
704
705 if (arguments.at("OM and Size Correct based on target sample") != "")
706 {
707 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
708 {
709 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
710 return false;
711 }
712 transformed_data = transformed_data.CreateCorrectedDataset(
713 arguments.at("OM and Size Correct based on target sample"),
714 true,
715 Data()->GetElementInformation()
716 );
717 }
718
719 transformed_data = transformed_data.CreateCorrectedAndFilteredDataset(
720 exclude_samples,
721 exclude_elements,
722 false
723 );
724
725 transformed_data.SetProgressReporter(rtw);
726
727 if (arguments.at("Box-cox transformation") == "true")
728 {
729 transformed_data = transformed_data.BoxCoxTransformed(true);
730 }
731
732 DFA_result dfa_result = transformed_data.DiscriminantFunctionAnalysis(
733 arguments.at("Source/Target group I"),
734 arguments.at("Source/Target group II")
735 );
736
737 if (dfa_result.eigen_vectors.size() == 0)
738 {
739 host->ShowWarning("Singular matrix in within group scatter matrix!\n");
740 return false;
741 }
742
743 // Chi-squared P-Value result
744 CMBVector* p_value = new CMBVector(dfa_result.p_values);
745 ResultItem dfa_p_value;
746 dfa_p_value.SetName("Chi-squared P-Value");
747 dfa_p_value.SetType(result_type::vector);
748 dfa_p_value.SetShowTable(true);
749 dfa_p_value.SetShowGraph(false);
750 dfa_p_value.SetResult(p_value);
751 results.Append(dfa_p_value);
752
753 // F-test P-Value result
754 CMBVector* f_test_p_value = new CMBVector(dfa_result.F_test_P_value);
755 ResultItem dfa_f_test_p_value;
756 dfa_f_test_p_value.SetName("F-test P-Value");
757 dfa_f_test_p_value.SetType(result_type::vector);
758 dfa_f_test_p_value.SetShowTable(true);
759 dfa_f_test_p_value.SetShowGraph(false);
760 dfa_f_test_p_value.SetResult(f_test_p_value);
761 results.Append(dfa_f_test_p_value);
762
763 // Projected Elemental Profiles result
764 ResultItem dfa_projected;
765 dfa_projected.SetName("Projected Elemental Profiles");
767 dfa_projected.SetShowTable(true);
768 dfa_projected.SetShowGraph(true);
769 dfa_projected.SetYAxisMode(yaxis_mode::normal);
770 CMBVectorSet* projected = new CMBVectorSet(dfa_result.projected);
771 dfa_projected.SetResult(projected);
772 results.Append(dfa_projected);
773
774 // Eigen vector result
775 ResultItem dfa_eigen_vector;
776 dfa_eigen_vector.SetName("Eigen vector");
777 dfa_eigen_vector.SetType(result_type::vector);
778 dfa_eigen_vector.SetShowTable(true);
779 dfa_eigen_vector.SetShowGraph(true);
780 dfa_eigen_vector.SetYAxisMode(yaxis_mode::normal);
781 CMBVector* eigen_vector = new CMBVector(dfa_result.eigen_vectors.begin()->second);
782 dfa_eigen_vector.SetResult(eigen_vector);
783 results.Append(dfa_eigen_vector);
784
785 rtw->SetProgress(1);
786
787 return true;
788}
789
790bool Conductor::ExecuteDFAOnevsRest(const std::map<std::string, std::string>& arguments)
791{
793 rtw->Start();
794
795 results.SetName("DFA between " + arguments.at("Source group") + "& the rest");
796
797 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
798 bool exclude_elements = (arguments.at("Use only selected elements") == "true");
799
800 SourceSinkData transformed_data = *Data();
801
802 if (arguments.at("OM and Size Correct based on target sample") != "")
803 {
804 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
805 {
806 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
807 return false;
808 }
809 transformed_data = transformed_data.CreateCorrectedDataset(
810 arguments.at("OM and Size Correct based on target sample"),
811 true,
812 Data()->GetElementInformation()
813 );
814 }
815
816 transformed_data = transformed_data.CreateCorrectedAndFilteredDataset(
817 exclude_samples,
818 exclude_elements,
819 false
820 );
821
822 transformed_data.SetProgressReporter(rtw);
823
824 if (arguments.at("Box-cox transformation") == "true")
825 {
826 transformed_data = transformed_data.BoxCoxTransformed(true);
827 }
828
829 DFA_result dfa_result = transformed_data.DiscriminantFunctionAnalysis(
830 arguments.at("Source group")
831 );
832
833 if (dfa_result.eigen_vectors.size() == 0)
834 {
835 host->ShowWarning("Singular matrix in within group scatter matrix!\n");
836 return false;
837 }
838
839 // Chi-squared P-Value result
840 CMBVector* p_value = new CMBVector(dfa_result.p_values);
841 ResultItem dfa_p_value;
842 dfa_p_value.SetName("Chi-squared P-Value");
843 dfa_p_value.SetType(result_type::vector);
844 dfa_p_value.SetShowTable(true);
845 dfa_p_value.SetShowGraph(false);
846 dfa_p_value.SetResult(p_value);
847 results.Append(dfa_p_value);
848
849 // F-test P-Value result
850 CMBVector* f_test_p_value = new CMBVector(dfa_result.F_test_P_value);
851 ResultItem dfa_f_test_p_value;
852 dfa_f_test_p_value.SetName("F-test P-Value");
853 dfa_f_test_p_value.SetType(result_type::vector);
854 dfa_f_test_p_value.SetShowTable(true);
855 dfa_f_test_p_value.SetShowGraph(false);
856 dfa_f_test_p_value.SetResult(f_test_p_value);
857 results.Append(dfa_f_test_p_value);
858
859 // Projected Elemental Profiles result
860 ResultItem dfa_projected;
861 dfa_projected.SetName("Projected Elemental Profiles");
863 dfa_projected.SetShowTable(true);
864 dfa_projected.SetShowGraph(true);
865 dfa_projected.SetYAxisMode(yaxis_mode::normal);
866 CMBVectorSet* projected = new CMBVectorSet(dfa_result.projected);
867 dfa_projected.SetResult(projected);
868 results.Append(dfa_projected);
869
870 // Eigen vector result
871 ResultItem dfa_eigen_vector;
872 dfa_eigen_vector.SetName("Eigen vector");
873 dfa_eigen_vector.SetType(result_type::vector);
874 dfa_eigen_vector.SetShowTable(true);
875 dfa_eigen_vector.SetShowGraph(true);
876 dfa_eigen_vector.SetYAxisMode(yaxis_mode::normal);
877 CMBVector* eigen_vector = new CMBVector(dfa_result.eigen_vectors.begin()->second);
878 dfa_eigen_vector.SetResult(eigen_vector);
879 results.Append(dfa_eigen_vector);
880
881 rtw->SetProgress(1);
882
883 return true;
884}
885
886bool Conductor::ExecuteDFAM(const std::map<std::string, std::string>& arguments)
887{
889 rtw->Start();
890
891 results.SetName("Multi-way DFA analysis");
892
893 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
894 bool exclude_elements = (arguments.at("Use only selected elements") == "true");
895
896 SourceSinkData transformed_data = *Data();
897
898 if (arguments.at("OM and Size Correct based on target sample") != "")
899 {
900 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
901 {
902 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
903 return false;
904 }
905 transformed_data = transformed_data.CreateCorrectedDataset(
906 arguments.at("OM and Size Correct based on target sample"),
907 true,
908 Data()->GetElementInformation()
909 );
910 }
911
912 transformed_data = transformed_data.CreateCorrectedAndFilteredDataset(
913 exclude_samples,
914 exclude_elements,
915 false
916 );
917
918 if (!CheckNegativeElements(&transformed_data))
919 return false;
920
921 transformed_data.SetProgressReporter(rtw);
922
923 if (arguments.at("Box-cox transformation") == "true")
924 {
925 transformed_data = transformed_data.BoxCoxTransformed(true);
926 }
927
928 DFA_result dfa_result = transformed_data.DiscriminantFunctionAnalysis();
929
930 if (dfa_result.eigen_vectors.size() == 0)
931 {
932 host->ShowWarning("Singular matrix in within group scatter matrix!\n");
933 return false;
934 }
935
936 // Chi-squared P-Value result
937 CMBVector* p_value = new CMBVector(dfa_result.p_values);
938 ResultItem dfa_p_value;
939 dfa_p_value.SetName("Chi-squared P-Value");
940 dfa_p_value.SetType(result_type::vector);
941 dfa_p_value.SetShowTable(true);
942 dfa_p_value.SetShowGraph(false);
943 dfa_p_value.SetResult(p_value);
944 results.Append(dfa_p_value);
945
946 // F-test P-Value result
947 CMBVector* f_test_p_value = new CMBVector(dfa_result.F_test_P_value);
948 ResultItem dfa_f_test_p_value;
949 dfa_f_test_p_value.SetName("F-test P-Value");
950 dfa_f_test_p_value.SetType(result_type::vector);
951 dfa_f_test_p_value.SetShowTable(true);
952 dfa_f_test_p_value.SetShowGraph(false);
953 dfa_f_test_p_value.SetResult(f_test_p_value);
954 results.Append(dfa_f_test_p_value);
955
956 // Multiway Projected Elemental Profiles result
957 ResultItem dfa_projected;
958 dfa_projected.SetName("Multiway Projected Elemental Profiles");
960 dfa_projected.SetShowTable(true);
961 dfa_projected.SetShowGraph(true);
962 dfa_projected.SetYAxisMode(yaxis_mode::normal);
963 CMBVectorSetSet* projected = new CMBVectorSetSet(dfa_result.multi_projected);
964 dfa_projected.SetResult(projected);
965 results.Append(dfa_projected);
966
967 // Eigen vectors result (multiple vectors for multiway)
968 ResultItem dfa_eigen_vectors;
969 dfa_eigen_vectors.SetName("Eigen vector");
970 dfa_eigen_vectors.SetType(result_type::vectorset);
971 dfa_eigen_vectors.SetShowTable(true);
972 dfa_eigen_vectors.SetShowGraph(true);
973 dfa_eigen_vectors.SetYAxisMode(yaxis_mode::normal);
974 CMBVectorSet* eigen_vectors = new CMBVectorSet(dfa_result.eigen_vectors);
975 dfa_eigen_vectors.SetResult(eigen_vectors);
976 results.Append(dfa_eigen_vectors);
977
978 rtw->SetProgress(1);
979
980 return true;
981}
982
983bool Conductor::ExecuteSDFA(const std::map<std::string, std::string>& arguments)
984{
985 if (arguments.at("Source/Target group I") == arguments.at("Source/Target group II"))
986 {
987 host->ShowWarning("The selected sources must be different");
988 return false;
989 }
990
992 rtw->Start();
993
994 results.SetName("Stepwise DFA between " + arguments.at("Source/Target group I") +
995 "&" + arguments.at("Source/Target group II"));
996
997 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
998 bool exclude_elements = (arguments.at("Use only selected elements") == "true");
999
1000 SourceSinkData transformed_data;
1001
1002 if (arguments.at("OM and Size Correct based on target sample") != "")
1003 {
1004 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
1005 {
1006 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
1007 return false;
1008 }
1009 transformed_data = Data()->CreateCorrectedDataset(
1010 arguments.at("OM and Size Correct based on target sample"),
1011 true,
1012 Data()->GetElementInformation()
1013 ).CreateCorrectedAndFilteredDataset(exclude_samples, exclude_elements, false);
1014 }
1015 else
1016 {
1017 transformed_data = Data()->CreateCorrectedAndFilteredDataset(
1018 exclude_samples,
1019 exclude_elements,
1020 false
1021 );
1022 }
1023
1024 if (!CheckNegativeElements(&transformed_data))
1025 return false;
1026
1027 if (arguments.at("Box-cox transformation") == "true")
1028 {
1029 transformed_data = transformed_data.BoxCoxTransformed(true);
1030 }
1031
1032 transformed_data.SetProgressReporter(rtw);
1033
1034 std::vector<CMBVector> sdfa_results = transformed_data.StepwiseDiscriminantFunctionAnalysis(
1035 arguments.at("Source/Target group I"),
1036 arguments.at("Source/Target group II")
1037 );
1038
1039 if (sdfa_results[0].size() == 0)
1040 {
1041 host->ShowWarning("Singular matrix in within group scatter matrix!\n");
1042 return false;
1043 }
1044
1045 // Chi-squared P-Values result
1046 CMBVector* p_vector = new CMBVector(sdfa_results[0]);
1047 ResultItem sdfa_p_values;
1048 sdfa_p_values.SetName("Chi-squared P-Values");
1049 sdfa_p_values.SetType(result_type::vector);
1050 sdfa_p_values.SetShowTable(true);
1051 sdfa_p_values.SetAbsoluteValue(true);
1052 sdfa_p_values.SetYAxisMode(yaxis_mode::log);
1053 sdfa_p_values.SetYLimit(_range::high, 1);
1054 sdfa_p_values.SetResult(p_vector);
1055 results.Append(sdfa_p_values);
1056
1057 // Wilks' Lambda result
1058 CMBVector* wilks_lambda_vector = new CMBVector(sdfa_results[1]);
1059 ResultItem sdfa_wilks_lambda;
1060 sdfa_wilks_lambda.SetName("Wilks' Lambda");
1061 sdfa_wilks_lambda.SetType(result_type::vector);
1062 sdfa_wilks_lambda.SetShowTable(true);
1063 sdfa_wilks_lambda.SetAbsoluteValue(true);
1064 sdfa_wilks_lambda.SetYAxisMode(yaxis_mode::log);
1065 sdfa_wilks_lambda.SetYLimit(_range::high, 1);
1066 sdfa_wilks_lambda.SetResult(wilks_lambda_vector);
1067 results.Append(sdfa_wilks_lambda);
1068
1069 // F-test P-Value result
1070 CMBVector* f_test_p_value = new CMBVector(sdfa_results[2]);
1071 ResultItem sdfa_f_test_p_value;
1072 sdfa_f_test_p_value.SetName("F-test P-Value");
1073 sdfa_f_test_p_value.SetType(result_type::vector);
1074 sdfa_f_test_p_value.SetShowTable(true);
1075 sdfa_f_test_p_value.SetAbsoluteValue(true);
1076 sdfa_f_test_p_value.SetYAxisMode(yaxis_mode::log);
1077 sdfa_f_test_p_value.SetYLimit(_range::high, 1);
1078 sdfa_f_test_p_value.SetResult(f_test_p_value);
1079 results.Append(sdfa_f_test_p_value);
1080
1081 return true;
1082}
1083
1084bool Conductor::ExecuteSDFAM(const std::map<std::string, std::string>& arguments)
1085{
1087 rtw->Start();
1088
1089 results.SetName("Multiway Stepwise DFA");
1090
1091 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
1092 bool exclude_elements = (arguments.at("Use only selected elements") == "true");
1093
1094 SourceSinkData transformed_data;
1095
1096 if (arguments.at("OM and Size Correct based on target sample") != "")
1097 {
1098 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
1099 {
1100 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
1101 return false;
1102 }
1103 transformed_data = Data()->CreateCorrectedDataset(
1104 arguments.at("OM and Size Correct based on target sample"),
1105 true,
1106 Data()->GetElementInformation()
1107 ).CreateCorrectedAndFilteredDataset(exclude_samples, exclude_elements, false);
1108 }
1109 else
1110 {
1111 transformed_data = Data()->CreateCorrectedAndFilteredDataset(
1112 exclude_samples,
1113 exclude_elements,
1114 false
1115 );
1116 }
1117
1118 if (!CheckNegativeElements(&transformed_data))
1119 return false;
1120
1121 if (arguments.at("Box-cox transformation") == "true")
1122 {
1123 transformed_data = transformed_data.BoxCoxTransformed(true);
1124 }
1125
1126 transformed_data.SetProgressReporter(rtw);
1127
1128 std::vector<CMBVector> sdfa_results = transformed_data.StepwiseDiscriminantFunctionAnalysis();
1129
1130 if (sdfa_results[0].size() == 0)
1131 {
1132 host->ShowWarning("Singular matrix in within group scatter matrix!\n");
1133 return false;
1134 }
1135
1136 // Chi-squared P-Values result
1137 CMBVector* p_vector = new CMBVector(sdfa_results[0]);
1138 ResultItem sdfa_p_values;
1139 sdfa_p_values.SetName("Chi-squared P-Values");
1140 sdfa_p_values.SetType(result_type::vector);
1141 sdfa_p_values.SetShowTable(true);
1142 sdfa_p_values.SetAbsoluteValue(true);
1143 sdfa_p_values.SetYAxisMode(yaxis_mode::log);
1144 sdfa_p_values.SetYLimit(_range::high, 1);
1145 sdfa_p_values.SetResult(p_vector);
1146 results.Append(sdfa_p_values);
1147
1148 // Selected elements result
1149 ResultItem sdfa_selected;
1150 sdfa_selected.SetName("Elements to be Selected");
1151 sdfa_selected.SetType(result_type::vector);
1152 sdfa_selected.SetShowTable(true);
1153 sdfa_selected.SetAbsoluteValue(true);
1154 sdfa_selected.SetYAxisMode(yaxis_mode::log);
1155 sdfa_selected.SetYLimit(_range::high, 1);
1156
1157 CMBVector* p_vector_selected = new CMBVector();
1158 std::vector<std::string> selected = p_vector->ExtractUpToMinimum().Labels();
1159
1160 if (arguments.at("Modify the included elements based on the results") == "true")
1161 {
1163 }
1164
1165 for (size_t i = 0; i < selected.size(); i++)
1166 {
1167 p_vector_selected->append(selected[i], p_vector->valueAt(i));
1168 }
1169
1170 sdfa_selected.SetResult(p_vector_selected);
1171 results.Append(sdfa_selected);
1172
1173 // Wilks' Lambda result
1174 CMBVector* wilks_lambda_vector = new CMBVector(sdfa_results[1]);
1175 ResultItem sdfa_wilks_lambda;
1176 sdfa_wilks_lambda.SetName("Wilks' Lambda");
1177 sdfa_wilks_lambda.SetType(result_type::vector);
1178 sdfa_wilks_lambda.SetShowTable(true);
1179 sdfa_wilks_lambda.SetAbsoluteValue(true);
1180 sdfa_wilks_lambda.SetYAxisMode(yaxis_mode::log);
1181 sdfa_wilks_lambda.SetYLimit(_range::high, 1);
1182 sdfa_wilks_lambda.SetResult(wilks_lambda_vector);
1183 results.Append(sdfa_wilks_lambda);
1184
1185 // F-test P-Value result
1186 CMBVector* f_test_p_value = new CMBVector(sdfa_results[2]);
1187 ResultItem sdfa_f_test_p_value;
1188 sdfa_f_test_p_value.SetName("F-test P-Value");
1189 sdfa_f_test_p_value.SetType(result_type::vector);
1190 sdfa_f_test_p_value.SetShowTable(true);
1191 sdfa_f_test_p_value.SetAbsoluteValue(true);
1192 sdfa_f_test_p_value.SetYAxisMode(yaxis_mode::log);
1193 sdfa_f_test_p_value.SetYLimit(_range::high, 1);
1194 sdfa_f_test_p_value.SetResult(f_test_p_value);
1195 results.Append(sdfa_f_test_p_value);
1196
1197 return true;
1198}
1199
1200bool Conductor::ExecuteSDFAOnevsRest(const std::map<std::string, std::string>& arguments)
1201{
1203 rtw->Start();
1204
1205 results.SetName("Stepwise DFA between " + arguments.at("Source group") + "& the rest");
1206
1207 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
1208 bool exclude_elements = (arguments.at("Use only selected elements") == "true");
1209
1210 SourceSinkData transformed_data;
1211
1212 if (arguments.at("OM and Size Correct based on target sample") != "")
1213 {
1214 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
1215 {
1216 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
1217 return false;
1218 }
1219 transformed_data = Data()->CreateCorrectedDataset(
1220 arguments.at("OM and Size Correct based on target sample"),
1221 true,
1222 Data()->GetElementInformation()
1223 ).CreateCorrectedAndFilteredDataset(exclude_samples, exclude_elements, false);
1224 }
1225 else
1226 {
1227 transformed_data = Data()->CreateCorrectedAndFilteredDataset(
1228 exclude_samples,
1229 exclude_elements,
1230 false
1231 );
1232 }
1233
1234 if (!CheckNegativeElements(&transformed_data))
1235 return false;
1236
1237 if (arguments.at("Box-cox transformation") == "true")
1238 {
1239 transformed_data = transformed_data.BoxCoxTransformed(true);
1240 }
1241
1242 transformed_data.SetProgressReporter(rtw);
1243
1244 std::vector<CMBVector> sdfa_results = transformed_data.StepwiseDiscriminantFunctionAnalysis(
1245 arguments.at("Source group")
1246 );
1247
1248 if (sdfa_results[0].size() == 0)
1249 {
1250 host->ShowWarning("Singular matrix in within group scatter matrix!\n");
1251 return false;
1252 }
1253
1254 // Chi-squared P-Values result
1255 CMBVector* p_vector = new CMBVector(sdfa_results[0]);
1256 ResultItem sdfa_p_values;
1257 sdfa_p_values.SetName("Chi-squared P-Values");
1258 sdfa_p_values.SetType(result_type::vector);
1259 sdfa_p_values.SetShowTable(true);
1260 sdfa_p_values.SetAbsoluteValue(true);
1261 sdfa_p_values.SetYAxisMode(yaxis_mode::log);
1262 sdfa_p_values.SetYLimit(_range::high, 1);
1263 sdfa_p_values.SetResult(p_vector);
1264 results.Append(sdfa_p_values);
1265
1266 // Wilks' Lambda result
1267 CMBVector* wilks_lambda_vector = new CMBVector(sdfa_results[1]);
1268 ResultItem sdfa_wilks_lambda;
1269 sdfa_wilks_lambda.SetName("Wilks' Lambda");
1270 sdfa_wilks_lambda.SetType(result_type::vector);
1271 sdfa_wilks_lambda.SetShowTable(true);
1272 sdfa_wilks_lambda.SetAbsoluteValue(true);
1273 sdfa_wilks_lambda.SetYAxisMode(yaxis_mode::log);
1274 sdfa_wilks_lambda.SetYLimit(_range::high, 1);
1275 sdfa_wilks_lambda.SetResult(wilks_lambda_vector);
1276 results.Append(sdfa_wilks_lambda);
1277
1278 // F-test P-Value result
1279 CMBVector* f_test_p_value = new CMBVector(sdfa_results[2]);
1280 ResultItem sdfa_f_test_p_value;
1281 sdfa_f_test_p_value.SetName("F-test P-Value");
1282 sdfa_f_test_p_value.SetType(result_type::vector);
1283 sdfa_f_test_p_value.SetShowTable(true);
1284 sdfa_f_test_p_value.SetAbsoluteValue(true);
1285 sdfa_f_test_p_value.SetYAxisMode(yaxis_mode::log);
1286 sdfa_f_test_p_value.SetYLimit(_range::high, 1);
1287 sdfa_f_test_p_value.SetResult(f_test_p_value);
1288 results.Append(sdfa_f_test_p_value);
1289
1290 return true;
1291}
1292
1293bool Conductor::ExecuteKolmogorovSmirnov(const std::map<std::string, std::string>& arguments)
1294{
1295 results.SetName("Kolmogorov–Smirnov statististics for " + arguments.at("Source/Target group"));
1296
1297 ResultItem ks_item;
1298 ks_item.SetName("Kolmogorov–Smirnov statististics for " + arguments.at("Source/Target group"));
1301
1302 distribution_type dist;
1303 if (arguments.at("Distribution") == "Normal")
1304 {
1306 }
1307 else if (arguments.at("Distribution") == "Lognormal")
1308 {
1310 }
1311
1312 CMBVector* ks_output = new CMBVector(
1313 Data()->at(arguments.at("Source/Target group")).CalculateKolmogorovSmirnovStatistics(dist)
1314 );
1315
1316 ks_item.SetShowTable(true);
1317 ks_item.SetResult(ks_output);
1318 results.Append(ks_item);
1319
1320 return true;
1321}
1322
1323bool Conductor::ExecuteKolmogorovSmirnovIndividual(const std::map<std::string, std::string>& arguments)
1324{
1325 results.SetName("Kolmogorov–Smirnov statististics for constituent " +
1326 arguments.at("Constituent") + " in group " +
1327 arguments.at("Source/Target group"));
1328
1329 ResultItem ks_item;
1330 ks_item.SetName("Kolmogorov–Smirnov statististics for constituent " +
1331 arguments.at("Constituent") + " in group " +
1332 arguments.at("Source/Target group"));
1334
1335 distribution_type dist;
1336 if (arguments.at("Distribution") == "Normal")
1337 {
1339 }
1340 else if (arguments.at("Distribution") == "Lognormal")
1341 {
1343 }
1344
1345 CMBTimeSeriesSet* ks_output = new CMBTimeSeriesSet(
1346 Data()->at(arguments.at("Source/Target group"))
1347 .GetElementDistribution(arguments.at("Constituent"))
1348 ->CreateCDFComparison(dist)
1349 );
1350
1351 ks_item.SetResult(ks_output);
1352 ks_item.SetShowTable(false);
1353 results.Append(ks_item);
1354
1355 return true;
1356}
1357
1358bool Conductor::ExecuteCMBBayesianBatch(const std::map<std::string, std::string>& arguments)
1359{
1360 if (arguments.at("Apply size and organic matter correction") == "true")
1361 {
1362 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
1363 {
1364 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
1365 return false;
1366 }
1367 }
1368
1369 // Initialize MCMC object
1370 MCMC = std::make_unique<CMCMC<SourceSinkData>>();
1371
1372 // Create progress window with 3 charts for monitoring (with batch mode enabled)
1373 ScopedProgressReporter rtw(host, 3, true);
1374 rtw->SetTitle("Acceptance Rate", 0);
1375 rtw->SetTitle("Purturbation Factor", 1);
1376 rtw->SetTitle("Log posterior value", 2);
1377 rtw->SetYAxisTitle("Acceptance Rate", 0);
1378 rtw->SetYAxisTitle("Purturbation Factor", 1);
1379 rtw->SetYAxisTitle("Log posterior value", 2);
1380 rtw->Start();
1381
1382 // Execute batch MCMC sampling
1383 std::vector<std::string> failed_writes;
1384 CMBMatrix* contributions = new CMBMatrix(
1385 Data()->MCMC_Batch(
1386 arguments,
1387 MCMC.get(),
1388 rtw,
1389 workingfolder.toStdString(),
1390 &failed_writes
1391 )
1392 );
1393
1394 if (!failed_writes.empty())
1395 {
1396 std::string message = "Some per-sample result files could not be written:\n";
1397 for (const std::string& failure : failed_writes)
1398 message += failure + "\n";
1399 host->ShowWarning(message);
1400 }
1401
1402 results.SetName("CMB Bayesian-Batch");
1403
1404 // Create result item for contribution range matrix
1405 ResultItem contribution_matrix_item;
1406 contribution_matrix_item.SetName("Contribution Range Matrix");
1407 contribution_matrix_item.SetType(result_type::matrix);
1408 contribution_matrix_item.SetYAxisMode(yaxis_mode::normal);
1409 contribution_matrix_item.SetResult(contributions);
1410 contribution_matrix_item.SetShowTable(true);
1411 results.Append(contribution_matrix_item);
1412
1413 rtw->SetProgress(1);
1414
1415 return true;
1416}
1417
1418bool Conductor::ExecuteTestCMBBayesian(const std::map<std::string, std::string>& arguments)
1419{
1420 results.SetName("MCMC results for testing MCMC'");
1421
1422 // Create MCMC samples result item
1426 mcmc_samples.SetName("MCMC samples for testing MCMC'");
1427
1429
1430 // Initialize MCMC for testing with TestMCMC model
1431 CMCMC<TestMCMC>* mcmc_for_testing = new CMCMC<TestMCMC>();
1432 TestMCMC testing_model;
1433 mcmc_for_testing->Model = &testing_model;
1434
1435 // Create progress window with 3 charts
1437 rtw->SetTitle("Acceptance Rate", 0);
1438 rtw->SetTitle("Purturbation Factor", 1);
1439 rtw->SetTitle("Log posterior value", 2);
1440 rtw->SetYAxisTitle("Acceptance Rate", 0);
1441 rtw->SetYAxisTitle("Purturbation Factor", 1);
1442 rtw->SetYAxisTitle("Log posterior value", 2);
1443 rtw->Start();
1444
1445 // Set up parameter bounds for test model
1446 std::vector<double> mins;
1447 std::vector<double> maxs;
1448 mins.push_back(0.1);
1449 mins.push_back(1);
1450 maxs.push_back(1.0);
1451 maxs.push_back(10);
1452
1453 testing_model.InitializeParametersObservations(mins, maxs);
1454
1455 // Configure MCMC parameters
1456 mcmc_for_testing->SetProperty("number_of_samples", arguments.at("Number of samples"));
1457 mcmc_for_testing->SetProperty("number_of_chains", arguments.at("Number of chains"));
1458 mcmc_for_testing->SetProperty("number_of_burnout_samples", arguments.at("Samples to be discarded (burnout)"));
1459
1460 mcmc_for_testing->initialize(samples, true);
1461
1462 // Determine output folder path
1463 std::string folder_path;
1464 if (!QString::fromStdString(arguments.at("samples_file_name")).contains("/"))
1465 {
1466 folder_path = workingfolder.toStdString() + "/";
1467 }
1468
1469 // Execute MCMC sampling
1470 mcmc_for_testing->step(
1471 QString::fromStdString(arguments.at("Number of chains")).toInt(),
1472 QString::fromStdString(arguments.at("Number of samples")).toInt(),
1473 folder_path + arguments.at("samples_file_name"),
1474 samples,
1475 rtw
1476 );
1477
1478 mcmc_samples.SetResult(samples);
1480
1481 // Generate posterior distributions from samples
1482 ResultItem distribution_result_item;
1483 CMBTimeSeriesSet* dists = new CMBTimeSeriesSet();
1484 *dists = samples->distribution(
1485 100,
1486 QString::fromStdString(arguments.at("Samples to be discarded (burnout)")).toInt()
1487 );
1488
1489 distribution_result_item.SetName("Posterior Distributions");
1490 distribution_result_item.SetShowAsString(false);
1491 distribution_result_item.SetType(result_type::distribution);
1492 distribution_result_item.SetResult(dists);
1493 results.Append(distribution_result_item);
1494
1495 // Clean up (TestMCMC uses raw pointer)
1496 delete mcmc_for_testing;
1497
1498 return true;
1499}
1500
1501bool Conductor::ExecuteDistributionFitting(const std::map<std::string, std::string>& arguments)
1502{
1503 results.SetName("Distribution fitting results for '" + arguments.at("Constituent") +
1504 "' in '" + arguments.at("Source/Target group"));
1505
1506 // Prepare result items for PDF and CDF
1507 ResultItem distribution_item;
1508 distribution_item.SetName("Fitted PDF for '" + arguments.at("Constituent") +
1509 "' in '" + arguments.at("Source/Target group"));
1510 distribution_item.SetShowAsString(false);
1512 distribution_item.SetYAxisMode(yaxis_mode::normal);
1513 distribution_item.setXAxisTitle("Value");
1514 distribution_item.setYAxisTitle("PDF");
1515
1516 ResultItem cumulative_distribution_item;
1517 cumulative_distribution_item.SetName("Fitted CDF for '" + arguments.at("Constituent") +
1518 "' in '" + arguments.at("Source/Target group"));
1519 cumulative_distribution_item.SetShowAsString(false);
1520 cumulative_distribution_item.SetType(result_type::timeseries_set_first_symbol);
1521 cumulative_distribution_item.SetYAxisMode(yaxis_mode::normal);
1522 cumulative_distribution_item.setXAxisTitle("Value");
1523 cumulative_distribution_item.setYAxisTitle("CDF");
1524
1525 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
1526
1527 SourceSinkData transformed_data;
1528
1529 if (arguments.at("OM and Size Correct based on target sample") != "")
1530 {
1531 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
1532 {
1533 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
1534 return false;
1535 }
1536 transformed_data = Data()->CreateCorrectedDataset(
1537 arguments.at("OM and Size Correct based on target sample"),
1538 true,
1539 Data()->GetElementInformation()
1540 ).CreateCorrectedAndFilteredDataset(exclude_samples, false, false);
1541 }
1542 else
1543 {
1544 transformed_data = Data()->CreateCorrectedAndFilteredDataset(exclude_samples, false, false);
1545 }
1546
1547 if (!CheckNegativeElements(&transformed_data))
1548 return false;
1549
1550 if (arguments.at("Box-cox transformation") == "true")
1551 {
1552 transformed_data = transformed_data.BoxCoxTransformed(true);
1553 }
1554
1555 // Fit normal distribution
1556 CMBTimeSeriesSet fitted_normal = transformed_data.at(arguments.at("Source/Target group"))
1557 .GetElementDistribution(arguments.at("Constituent"))
1559
1560 // Fit lognormal distribution (only if not Box-Cox transformed)
1561 CMBTimeSeriesSet fitted_lognormal;
1562 if (arguments.at("Box-cox transformation") != "true")
1563 {
1564 fitted_lognormal = transformed_data.at(arguments.at("Source/Target group"))
1565 .GetElementDistribution(arguments.at("Constituent"))
1567 }
1568
1569 // Create CDF comparisons for normal
1570 CMBTimeSeriesSet observed_fitted_normal_cdf = transformed_data.at(arguments.at("Source/Target group"))
1571 .GetElementDistribution(arguments.at("Constituent"))
1573
1574 // Create CDF comparisons for lognormal (only if not Box-Cox transformed)
1575 CMBTimeSeriesSet observed_fitted_lognormal_cdf;
1576 if (arguments.at("Box-cox transformation") != "true")
1577 {
1578 observed_fitted_lognormal_cdf = transformed_data.at(arguments.at("Source/Target group"))
1579 .GetElementDistribution(arguments.at("Constituent"))
1581 }
1582
1583 // Build PDF result
1585 pdf->append(fitted_normal["Observed"]);
1586 pdf->append(fitted_normal["Fitted"]);
1587 if (arguments.at("Box-cox transformation") != "true")
1588 {
1589 pdf->append(fitted_lognormal["Fitted"]);
1590 }
1591 pdf->setname(0, "Samples");
1592 pdf->setname(1, "Normal");
1593 if (arguments.at("Box-cox transformation") != "true")
1594 {
1595 pdf->setname(2, "Log-normal");
1596 }
1597
1598 // Build CDF result
1600 cdf->append(observed_fitted_normal_cdf["Observed"]);
1601 cdf->append(observed_fitted_normal_cdf["Fitted"]);
1602 if (arguments.at("Box-cox transformation") != "true")
1603 {
1604 cdf->append(observed_fitted_lognormal_cdf["Fitted"]);
1605 }
1606 cdf->setname(0, "Observed");
1607 cdf->setname(1, "Normal");
1608 if (arguments.at("Box-cox transformation") != "true")
1609 {
1610 cdf->setname(2, "Log-normal");
1611 }
1612
1613 distribution_item.SetResult(pdf);
1614 cumulative_distribution_item.SetResult(cdf);
1615
1616 results.Append(distribution_item);
1617 results.Append(cumulative_distribution_item);
1618
1619 return true;
1620}
1621
1622bool Conductor::ExecuteBracketingAnalysis(const std::map<std::string, std::string>& arguments)
1623{
1624 results.SetName("Bracketing analysis for sample '" + arguments.at("Sample") + "'");
1625
1626 ResultItem bracketing_result_item;
1627 bracketing_result_item.SetName("Bracketing results");
1628 bracketing_result_item.SetType(result_type::vector);
1629 bracketing_result_item.SetShowTable(true);
1630 bracketing_result_item.SetShowGraph(false);
1631
1632 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
1633 bool exclude_elements = (arguments.at("Use only selected elements") == "true");
1634 bool correct_based_on_size_and_organic_matter = (arguments.at("Correct based on size and organic matter") == "true");
1635
1637 exclude_samples,
1638 exclude_elements,
1639 correct_based_on_size_and_organic_matter,
1640 arguments.at("Sample")
1641 );
1642
1643 if (!CheckNegativeElements(&transformed_data))
1644 return false;
1645
1646 CMBVector* bracketing_result = new CMBVector(
1647 transformed_data.BracketTest(arguments.at("Sample"), false)
1648 );
1649
1650 bracketing_result->SetBooleanValue(true);
1651 bracketing_result_item.SetResult(bracketing_result);
1652 results.Append(bracketing_result_item);
1653
1654 return true;
1655}
1656
1657bool Conductor::ExecuteBracketingAnalysisBatch(const std::map<std::string, std::string>& arguments)
1658{
1659 results.SetName("Bracketing analysis");
1660
1661 ResultItem bracketing_result_item;
1662 bracketing_result_item.SetName("Bracketing results");
1663 bracketing_result_item.SetType(result_type::matrix);
1664 bracketing_result_item.SetShowTable(true);
1665 bracketing_result_item.SetShowGraph(false);
1666 bracketing_result_item.SetShowAsString(false);
1667
1668 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
1669 bool exclude_elements = (arguments.at("Use only selected elements") == "true");
1670 bool correct_based_on_size_and_organic_matter = (arguments.at("Correct based on size and organic matter") == "true");
1671
1673 return false;
1674
1675 if (correct_based_on_size_and_organic_matter)
1676 {
1677 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
1678 {
1679 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
1680 return false;
1681 }
1682 }
1683
1684 CMBMatrix* bracketing_result = new CMBMatrix(
1685 Data()->BracketTest(
1686 correct_based_on_size_and_organic_matter,
1687 exclude_elements,
1688 exclude_samples
1689 )
1690 );
1691
1692 bracketing_result->SetBooleanValue(true);
1693 bracketing_result_item.SetResult(bracketing_result);
1694 results.Append(bracketing_result_item);
1695
1696 return true;
1697}
1698
1699bool Conductor::ExecuteBoxCox(const std::map<std::string, std::string>& arguments)
1700{
1701 results.SetName("Box-Cox parameter for '" + arguments.at("Source/Target group") + "'");
1702
1703 ResultItem boxcox_result_item;
1704 boxcox_result_item.SetName("Box-Cox parameters");
1705 boxcox_result_item.SetType(result_type::vector);
1706 boxcox_result_item.SetShowTable(true);
1707 boxcox_result_item.SetShowGraph(true);
1708 boxcox_result_item.SetYAxisMode(yaxis_mode::normal);
1709
1710 CMBVector* boxcox_params = new CMBVector(
1711 Data()->at(arguments.at("Source/Target group")).CalculateBoxCoxParameters()
1712 );
1713
1714 boxcox_result_item.SetResult(boxcox_params);
1715 results.Append(boxcox_result_item);
1716
1717 return true;
1718}
1719
1720bool Conductor::ExecuteOutlierAnalysis(const std::map<std::string, std::string>& arguments)
1721{
1722 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
1723 bool exclude_elements = (arguments.at("Use only selected elements") == "true");
1724
1726 exclude_samples,
1727 exclude_elements,
1728 false
1729 );
1730
1731 if (!CheckNegativeElements(&transformed_data))
1732 return false;
1733
1734 results.SetName("Outlier analysis for '" + arguments.at("Source/Target group") + "'");
1735
1736 ResultItem outlier_result_item;
1737 outlier_result_item.SetName("Outlier Analysis");
1738 outlier_result_item.SetType(result_type::matrix);
1739 outlier_result_item.SetShowAsString(false);
1740 outlier_result_item.SetShowTable(true);
1741 outlier_result_item.SetShowGraph(false);
1742
1743 double threshold = QString::fromStdString(arguments.at("Threshold")).toDouble();
1744
1745 CMBMatrix* outlier_matrix = new CMBMatrix(
1746 transformed_data.at(arguments.at("Source/Target group")).DetectOutliers(-threshold, threshold)
1747 );
1748
1749 outlier_matrix->SetLimit(_range::high, threshold);
1750 outlier_matrix->SetLimit(_range::low, -threshold);
1751
1752 outlier_result_item.SetResult(outlier_matrix);
1753 results.Append(outlier_result_item);
1754
1755 return true;
1756}
1757
1758bool Conductor::ExecuteEDP(const std::map<std::string, std::string>& arguments)
1759{
1760 results.SetName("Two-way element discriminant power between '" +
1761 arguments.at("Source/Target group I") + "' and '" +
1762 arguments.at("Source/Target group II") + "'");
1763
1764 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
1765
1766 SourceSinkData transformed_data;
1767
1768 if (arguments.at("OM and Size Correct based on target sample") != "")
1769 {
1770 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
1771 {
1772 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
1773 return false;
1774 }
1775 transformed_data = Data()->CreateCorrectedDataset(
1776 arguments.at("OM and Size Correct based on target sample"),
1777 true,
1778 Data()->GetElementInformation()
1779 ).CreateCorrectedAndFilteredDataset(exclude_samples, false, false);
1780 }
1781 else
1782 {
1783 transformed_data = Data()->CreateCorrectedAndFilteredDataset(exclude_samples, false, false);
1784 }
1785
1786 if (!CheckNegativeElements(&transformed_data))
1787 return false;
1788
1789 if (arguments.at("Box-cox transformation") == "true")
1790 {
1791 transformed_data = transformed_data.BoxCoxTransformed(true);
1792 }
1793
1794 // Discriminant difference to standard deviation ratio
1795 ResultItem edp_result_std;
1796 edp_result_std.SetName("Discreminant difference to standard deviation ratio");
1798 edp_result_std.SetShowAsString(false);
1799 edp_result_std.SetShowTable(true);
1800 edp_result_std.SetShowGraph(true);
1801
1802 Elemental_Profile* edp_profile_set = new Elemental_Profile(
1803 transformed_data.DifferentiationPower(
1804 arguments.at("Source/Target group I"),
1805 arguments.at("Source/Target group II"),
1806 false
1807 )
1808 );
1809
1810 edp_result_std.SetYAxisMode(yaxis_mode::normal);
1811 edp_result_std.setYAxisTitle("Discrimination power");
1812 edp_result_std.SetResult(edp_profile_set);
1813 edp_result_std.setXAxisTitle("Element");
1814 edp_result_std.setYAxisTitle("Standard deviation to mean ratio");
1815 results.Append(edp_result_std);
1816
1817 // Discriminant fraction
1818 ResultItem edp_result_percent;
1819 edp_result_percent.SetName("Discriminat fraction");
1821 edp_result_percent.SetShowAsString(false);
1822 edp_result_percent.setYAxisTitle("Percentage discriminated");
1823 edp_result_percent.SetShowTable(true);
1824 edp_result_percent.SetShowGraph(true);
1825
1826 Elemental_Profile* edp_profile_set_percent = new Elemental_Profile(
1827 transformed_data.DifferentiationPower_Percentage(
1828 arguments.at("Source/Target group I"),
1829 arguments.at("Source/Target group II")
1830 )
1831 );
1832
1833 edp_result_percent.SetYAxisMode(yaxis_mode::normal);
1834 edp_result_percent.SetYLimit(_range::high, 1);
1835 edp_result_percent.SetResult(edp_profile_set_percent);
1836 edp_result_percent.setXAxisTitle("Element");
1837 edp_result_percent.setYAxisTitle("Discriminant fraction");
1838 results.Append(edp_result_percent);
1839
1840 // Discriminant p-value
1841 ResultItem edp_result_p_value;
1842 edp_result_p_value.SetName("Discriminat p-value");
1844 edp_result_p_value.SetShowAsString(false);
1845 edp_result_p_value.setYAxisTitle("p-Value");
1846 edp_result_p_value.SetShowTable(true);
1847 edp_result_p_value.SetShowGraph(true);
1848
1849 Elemental_Profile* edp_profile_set_p_value = new Elemental_Profile(
1850 transformed_data.t_TestPValue(
1851 arguments.at("Source/Target group I"),
1852 arguments.at("Source/Target group II"),
1853 false
1854 )
1855 );
1856
1857 edp_result_p_value.SetYAxisMode(yaxis_mode::normal);
1858 edp_result_p_value.SetYLimit(_range::high, 1);
1859 edp_result_p_value.SetResult(edp_profile_set_p_value);
1860 edp_profile_set_p_value->SetLimit(_range::high, aquiutils::atof(arguments.at("P-value threshold")));
1861 edp_profile_set_p_value->SetLimit(_range::low, 0);
1862 edp_result_p_value.setXAxisTitle("Element");
1863 edp_result_p_value.setYAxisTitle("Discriminant fraction");
1864 results.Append(edp_result_p_value);
1865
1866 return true;
1867}
1868
1869bool Conductor::ExecuteEDPM(const std::map<std::string, std::string>& arguments)
1870{
1871 bool include_target = (arguments.at("Include target samples") == "true");
1872 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
1873
1874 SourceSinkData transformed_data;
1875
1876 if (arguments.at("OM and Size Correct based on target sample") != "")
1877 {
1878 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
1879 {
1880 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
1881 return false;
1882 }
1883 transformed_data = Data()->CreateCorrectedDataset(
1884 arguments.at("OM and Size Correct based on target sample"),
1885 true,
1886 Data()->GetElementInformation()
1887 ).CreateCorrectedAndFilteredDataset(exclude_samples, false, false);
1888 }
1889 else
1890 {
1891 transformed_data = Data()->CreateCorrectedAndFilteredDataset(exclude_samples, false, false);
1892 }
1893
1894 if (!CheckNegativeElements(&transformed_data))
1895 return false;
1896
1897 if (arguments.at("Box-cox transformation") == "true")
1898 {
1899 transformed_data = transformed_data.BoxCoxTransformed(true);
1900 }
1901
1902 results.SetName("Multi-way element discriminant power between '" +
1903 arguments.at("Source/Target group I") + "' and '" +
1904 arguments.at("Source/Target group II") + "'");
1905
1906 // Multi-way discriminant difference to standard deviation ratio
1907 ResultItem edp_result_std;
1908 edp_result_std.SetName("Multi-way discreminant difference to standard deviation ratio");
1910 edp_result_std.SetShowAsString(true);
1911 edp_result_std.SetShowTable(true);
1912 edp_result_std.SetShowGraph(true);
1913
1914 Elemental_Profile_Set* edp_profile_set = new Elemental_Profile_Set(
1915 transformed_data.DifferentiationPower(false, include_target)
1916 );
1917
1918 edp_result_std.SetYAxisMode(yaxis_mode::normal);
1919 edp_result_std.setYAxisTitle("Discrimination power");
1920 edp_result_std.SetResult(edp_profile_set);
1921 results.Append(edp_result_std);
1922
1923 // Multi-way discriminant fraction
1924 ResultItem edp_result_percent;
1925 edp_result_percent.SetName("Multi-way discriminat fraction");
1926 edp_result_percent.SetType(result_type::elemental_profile_set);
1927 edp_result_percent.SetShowAsString(true);
1928 edp_result_percent.setYAxisTitle("Percentage discriminated");
1929 edp_result_percent.SetShowTable(true);
1930 edp_result_percent.SetShowGraph(true);
1931
1932 Elemental_Profile_Set* edp_profile_set_percent = new Elemental_Profile_Set(
1933 transformed_data.DifferentiationPower_Percentage(include_target)
1934 );
1935
1936 edp_result_percent.SetYAxisMode(yaxis_mode::normal);
1937 edp_result_percent.SetYLimit(_range::high, 1);
1938 edp_result_percent.SetResult(edp_profile_set_percent);
1939 results.Append(edp_result_percent);
1940
1941 // Multi-way discriminant p-value
1942 ResultItem edp_p_value;
1943 edp_p_value.SetName("Multi-way discriminat p-value");
1945 edp_p_value.SetShowAsString(true);
1946 edp_p_value.setYAxisTitle("p-Value");
1947 edp_p_value.SetShowTable(true);
1948 edp_p_value.SetShowGraph(true);
1949
1950 Elemental_Profile_Set* edp_profile_set_p_value = new Elemental_Profile_Set(
1951 transformed_data.DifferentiationPower_P_value(include_target)
1952 );
1953
1954 edp_p_value.SetYAxisMode(yaxis_mode::normal);
1955 edp_p_value.SetYLimit(_range::high, 1);
1956 edp_p_value.SetResult(edp_profile_set_p_value);
1957 edp_profile_set_p_value->SetLimit(_range::high, aquiutils::atof(arguments.at("P-value threshold")));
1958 edp_profile_set_p_value->SetLimit(_range::low, 0);
1959 results.Append(edp_p_value);
1960
1961 return true;
1962}
1963
1964bool Conductor::ExecuteANOVA(const std::map<std::string, std::string>& arguments)
1965{
1966 bool log_transformation = (arguments.at("Log Transformation") == "true");
1967 bool exclude_samples = (arguments.at("Use only selected samples") == "true");
1968 bool exclude_elements = (arguments.at("Use only selected elements") == "true");
1969
1970 SourceSinkData transformed_data;
1971
1972 if (arguments.at("OM and Size Correct based on target sample") != "")
1973 {
1974 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
1975 {
1976 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
1977 return false;
1978 }
1979 transformed_data = Data()->CreateCorrectedDataset(
1980 arguments.at("OM and Size Correct based on target sample"),
1981 true,
1982 Data()->GetElementInformation()
1983 ).CreateCorrectedAndFilteredDataset(true, false, false);
1984 }
1985 else
1986 {
1987 transformed_data = Data()->CreateCorrectedAndFilteredDataset(true, false, false);
1988 }
1989
1990 if (!CheckNegativeElements(&transformed_data))
1991 return false;
1992
1993 if (arguments.at("Box-cox transformation") == "true")
1994 {
1995 transformed_data = transformed_data.BoxCoxTransformed(true);
1996 log_transformation = false;
1997 }
1998
1999 results.SetName("ANOVA analysis");
2000
2001 ResultItem anova_results;
2002 anova_results.SetName("ANOVA");
2003 anova_results.SetType(result_type::vector);
2004 anova_results.SetShowAsString(true);
2005 anova_results.SetShowTable(true);
2006 anova_results.SetShowGraph(true);
2007
2008 CMBVector* p_values = new CMBVector(transformed_data.ANOVA(log_transformation));
2009
2010 p_values->SetLimit(_range::high, aquiutils::atof(arguments.at("P-value threshold")));
2011 p_values->SetLimit(_range::low, 0);
2012
2013 anova_results.SetYAxisMode(yaxis_mode::normal);
2014 anova_results.SetResult(p_values);
2015 anova_results.setYAxisTitle("P-value");
2016 anova_results.setXAxisTitle("Element");
2017
2018 if (arguments.at("Modify the included elements based on the results") == "true")
2019 {
2020 std::vector<std::string> selected = p_values->ExtractWithinRange(
2021 0,
2022 aquiutils::atof(arguments.at("P-value threshold"))
2023 ).Labels();
2025 }
2026
2027 results.Append(anova_results);
2028
2029 return true;
2030}
2031
2032bool Conductor::ExecuteErrorAnalysis(const std::map<std::string, std::string>& arguments)
2033{
2034 results.SetName("Error Analysis");
2035
2037
2038 bool organic_size_correction;
2039 if (arguments.at("Apply size and organic matter correction") == "true")
2040 {
2041 organic_size_correction = true;
2042 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
2043 {
2044 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
2045 return false;
2046 }
2047 }
2048 else
2049 {
2050 organic_size_correction = false;
2051 }
2052
2053 rtw->Start();
2054
2055 SourceSinkData corrected_data = Data()->CreateCorrectedDataset(
2056 arguments.at("Sample"),
2057 organic_size_correction,
2058 Data()->GetElementInformation()
2059 );
2060
2061 corrected_data.SetProgressReporter(rtw);
2062
2063 if (!CheckNegativeElements(&corrected_data))
2064 return false;
2065
2066 bool softmax = (arguments.at("Softmax transformation") == "true");
2067
2068 corrected_data.InitializeParametersAndObservations(arguments.at("Sample"));
2069
2070 bool outcome = corrected_data.BootStrap(
2071 &results,
2072 aquiutils::atof(arguments.at("Pecentage eliminated")),
2073 aquiutils::atoi(arguments.at("Number of realizations")),
2074 arguments.at("Sample"),
2075 softmax
2076 );
2077
2078 return outcome;
2079}
2080
2081bool Conductor::ExecuteSourceVerify(const std::map<std::string, std::string>& arguments)
2082{
2083 results.SetName("Source Verification");
2084
2086
2087 bool organic_size_correction;
2088 if (arguments.at("Apply size and organic matter correction") == "true")
2089 {
2090 organic_size_correction = true;
2091 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
2092 {
2093 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
2094 return false;
2095 }
2096 }
2097 else
2098 {
2099 organic_size_correction = false;
2100 }
2101
2102 rtw->Start();
2103
2104 SourceSinkData corrected_data = *Data();
2105 corrected_data.SetProgressReporter(rtw);
2106
2107 if (!CheckNegativeElements(&corrected_data))
2108 return false;
2109
2110 bool softmax = (arguments.at("Softmax transformation") == "true");
2111
2112 CMBTimeSeriesSet* contributions = new CMBTimeSeriesSet(
2113 corrected_data.VerifySource(
2114 arguments.at("Source Group"),
2115 softmax,
2116 organic_size_correction
2117 )
2118 );
2119
2120 ResultItem contributions_result_item;
2121 results.SetName("Source verification for source'" + arguments.at("Source Group") + "'");
2122
2123 contributions->GetOptions().X_suffix = "";
2124 contributions->GetOptions().Y_suffix = "";
2125 contributions->SetOption(options_key::single_column_x, true);
2126
2127 contributions_result_item.SetName("Source Verification");
2128 contributions_result_item.SetResult(contributions);
2129 contributions_result_item.SetType(result_type::stacked_bar_chart);
2130 contributions_result_item.SetShowAsString(true);
2131 contributions_result_item.SetShowTable(true);
2132 contributions_result_item.SetShowGraph(true);
2133 contributions_result_item.SetYLimit(_range::high, 1);
2134 contributions_result_item.SetXAxisMode(xaxis_mode::counter);
2135 contributions_result_item.setYAxisTitle("Contribution");
2136 contributions_result_item.setXAxisTitle("Source Sample");
2137 contributions_result_item.SetYLimit(_range::low, 0);
2138
2139 results.Append(contributions_result_item);
2140
2141 rtw->SetProgress(1);
2142
2143 return true;
2144}
2145
2146bool Conductor::ExecuteAutoSelect(const std::map<std::string, std::string>& arguments)
2147{
2148 results.SetName("Auto-select elements");
2149
2150 SourceSinkData transformed_data;
2151
2152 if (arguments.at("OM and Size Correct based on target sample") != "")
2153 {
2154 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
2155 {
2156 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
2157 return false;
2158 }
2159 transformed_data = Data()->CreateCorrectedDataset(
2160 arguments.at("OM and Size Correct based on target sample"),
2161 true,
2162 Data()->GetElementInformation()
2163 ).CreateCorrectedAndFilteredDataset(true, false, false);
2164 }
2165 else
2166 {
2167 transformed_data = Data()->CreateCorrectedAndFilteredDataset(true, false, false);
2168 }
2169
2170 if (!CheckNegativeElements(&transformed_data))
2171 return false;
2172
2173 bool isotopes = (arguments.at("Include Isotopes") == "true");
2174
2175 transformed_data = transformed_data.ExtractChemicalElements(isotopes);
2176
2177 // Multi-way discriminant p-value result
2178 ResultItem edp_p_value;
2179 edp_p_value.SetName("Multi-way discriminat p-value");
2181 edp_p_value.SetShowAsString(true);
2182 edp_p_value.setYAxisTitle("p-Value");
2183 edp_p_value.SetShowTable(true);
2184 edp_p_value.SetShowGraph(true);
2185
2186 Elemental_Profile_Set* edp_profile_set_p_value = new Elemental_Profile_Set(
2187 transformed_data.DifferentiationPower_P_value(false)
2188 );
2189
2190 edp_p_value.SetYAxisMode(yaxis_mode::normal);
2191 edp_p_value.SetYLimit(_range::high, 1);
2192 edp_p_value.SetResult(edp_profile_set_p_value);
2193 results.Append(edp_p_value);
2194
2195 // Selected elements result
2196 Elemental_Profile* selected = new Elemental_Profile(
2197 edp_profile_set_p_value->SelectTopElementsAggregate(
2198 aquiutils::atoi(arguments.at("Number of elements from each pair"))
2199 )
2200 );
2201
2202 ResultItem selected_elements;
2203 selected_elements.SetResult(selected);
2204 selected_elements.SetName("Selected Elements");
2206 selected_elements.SetShowAsString(true);
2207 selected_elements.setYAxisTitle("p-Value");
2208 selected_elements.SetShowTable(true);
2209 selected_elements.SetShowGraph(true);
2210 results.Append(selected_elements);
2211
2212 if (arguments.at("Modify the included elements based on the results") == "true")
2213 {
2215 }
2216
2217 return true;
2218}
2219
2220bool Conductor::ExecuteCMBBayesian(const std::map<std::string, std::string>& arguments)
2221{
2222 if (arguments.at("Apply size and organic matter correction") == "true")
2223 {
2224 if (Data()->OMandSizeConstituents()[0] == "" && Data()->OMandSizeConstituents()[1] == "")
2225 {
2226 host->ShowWarning("Perform Organic Matter and Size Correction first!\n");
2227 return false;
2228 }
2229 }
2230
2231 // Initialize MCMC object
2232 MCMC = std::make_unique<CMCMC<SourceSinkData>>();
2233
2234 // Create progress window with 3 charts for monitoring
2236 rtw->SetTitle("Acceptance Rate", 0);
2237 rtw->SetTitle("Purturbation Factor", 1);
2238 rtw->SetTitle("Log posterior value", 2);
2239 rtw->SetYAxisTitle("Acceptance Rate", 0);
2240 rtw->SetYAxisTitle("Purturbation Factor", 1);
2241 rtw->SetYAxisTitle("Log posterior value", 2);
2242 rtw->Start();
2243
2244 // Execute MCMC sampling
2245 results = Data()->MCMC(
2246 arguments.at("Sample"),
2247 arguments,
2248 MCMC.get(),
2249 rtw,
2250 workingfolder.toStdString()
2251 );
2252
2253 // Check for errors during execution
2254 if (results.Error() != "")
2255 {
2257 return false;
2258 }
2259
2260 rtw->SetProgress(1);
2261
2262 return true;
2263}
Abstract environment that an analysis runs inside.
virtual void ShowWarning(const std::string &message)=0
Reports a condition that prevented an analysis from running.
Matrix class with labeled rows and columns for Chemical Mass Balance analysis.
Definition cmbmatrix.h:19
void SetBooleanValue(bool val)
Sets boolean display mode for table widget.
Definition cmbmatrix.h:183
Collection of time series with labels and observed values.
Collection of named CMBVectorSet objects for hierarchical data organization.
Collection of named CMBVector objects for multi-variable analysis.
Vector class with string labels for Chemical Mass Balance analysis.
Definition cmbvector.h:17
CMBVector ExtractWithinRange(const double &lowval, const double &highval) const
Extracts elements with values within specified range.
void SetBooleanValue(bool val)
Sets boolean display mode for table widget.
Definition cmbvector.h:161
CMBVector ExtractUpToMinimum() const
Extracts elements up to first minimum value.
void append(const string &label, const double &val)
Appends a labeled element to the vector.
double valueAt(int i) const
Gets value at specified index.
vector< string > Labels() const
Gets all element labels.
Definition cmbvector.h:138
Markov Chain Monte Carlo sampler for Bayesian parameter estimation.
Definition MCMC.h:326
bool SetProperty(const string &varname, const string &value)
Set MCMC properties from string key-value pairs.
Definition MCMC.hpp:71
bool step(int k, int chain_counter)
Perform single MCMC step for one chain.
Definition MCMC.hpp:340
T * Model
Pointer to the model object being calibrated.
Definition MCMC.h:334
void initialize(CMBTimeSeriesSet *results, bool random=false)
Initialize MCMC chains with starting parameter values.
Definition MCMC.hpp:203
CMBTimeSeriesSet CreateCDFComparison(distribution_type dist_type) const
Create comparison of empirical vs fitted CDF.
CMBTimeSeriesSet CreateFittedDistribution(distribution_type dist_type) const
Create fitted distribution visualization.
bool ExecuteOutlierAnalysis(const std::map< std::string, std::string > &arguments)
Executes outlier detection analysis for a source/target group.
bool ExecuteTestCMBBayesian(const std::map< std::string, std::string > &arguments)
Executes MCMC test with a simple analytical model.
bool ExecuteCMBBayesian(const std::map< std::string, std::string > &arguments)
Executes Bayesian Chemical Mass Balance using MCMC sampling.
bool ExecuteDFAM(const std::map< std::string, std::string > &arguments)
Executes multi-way Discriminant Function Analysis across all groups.
bool ExecuteDFA(const std::map< std::string, std::string > &arguments)
Executes Discriminant Function Analysis between two groups.
bool ExecuteSDFAM(const std::map< std::string, std::string > &arguments)
Executes multi-way Stepwise Discriminant Function Analysis across all groups.
bool ExecuteBoxCox(const std::map< std::string, std::string > &arguments)
Calculates optimal Box-Cox transformation parameters.
bool ExecuteKolmogorovSmirnovIndividual(const std::map< std::string, std::string > &arguments)
Executes Kolmogorov-Smirnov test for a single constituent in a group.
bool CheckNegativeElements(SourceSinkData *data=nullptr)
Validates that all element concentrations are non-negative.
bool ExecuteCMBBayesianBatch(const std::map< std::string, std::string > &arguments)
Executes Bayesian Chemical Mass Balance across all target samples.
bool ExecuteAutoSelect(const std::map< std::string, std::string > &arguments)
Executes automatic element selection based on discriminant power.
bool ExecuteSDFA(const std::map< std::string, std::string > &arguments)
Executes Stepwise Discriminant Function Analysis between two groups.
bool ExecuteBracketingAnalysisBatch(const std::map< std::string, std::string > &arguments)
Executes bracketing analysis across all target samples.
bool ExecuteANOVA(const std::map< std::string, std::string > &arguments)
Executes Analysis of Variance (ANOVA) for element discrimination.
AnalysisHost * host
Non-owning pointer to the running environment.
Definition conductor.h:145
QString workingfolder
Output directory path.
Definition conductor.h:144
std::unique_ptr< CGA< SourceSinkData > > GA
Genetic Algorithm optimizer (owned)
Definition conductor.h:141
bool ExecuteGA_NoTargets(const std::map< std::string, std::string > &arguments)
Executes Genetic Algorithm disregarding target constraints.
bool ExecuteGA(const std::map< std::string, std::string > &arguments)
Executes Genetic Algorithm optimization.
bool ExecuteSourceVerify(const std::map< std::string, std::string > &arguments)
Executes source verification analysis.
bool ExecuteGA_FixedProfile(const std::map< std::string, std::string > &arguments)
Executes Genetic Algorithm with fixed elemental profiles.
bool ExecuteMLR(const std::map< std::string, std::string > &arguments)
Executes multiple linear regression versus organic matter and particle size.
Conductor(AnalysisHost *host)
Constructs a Conductor that reports through host.
Definition conductor.cpp:11
bool ExecuteDistributionFitting(const std::map< std::string, std::string > &arguments)
Executes distribution fitting analysis for a constituent.
bool ExecuteLevenbergMarquardtBatch(const std::map< std::string, std::string > &arguments)
Executes Levenberg-Marquardt optimization across all target samples.
bool ExecuteKolmogorovSmirnov(const std::map< std::string, std::string > &arguments)
Executes Kolmogorov-Smirnov goodness-of-fit test for a source/target group.
bool ExecuteErrorAnalysis(const std::map< std::string, std::string > &arguments)
Executes bootstrap error analysis for uncertainty quantification.
SourceSinkData * Data()
Returns pointer to the current SourceSinkData.
Definition conductor.h:76
SourceSinkData * data
Non-owning pointer to analysis data.
Definition conductor.h:140
bool ExecuteSDFAOnevsRest(const std::map< std::string, std::string > &arguments)
Executes Stepwise Discriminant Function Analysis for one group versus all others.
bool Execute(const std::string &command, std::map< std::string, std::string > arguments)
Executes a specified analysis command with given parameters.
Definition conductor.cpp:17
bool ExecuteBracketingAnalysis(const std::map< std::string, std::string > &arguments)
Executes bracketing analysis for a single target sample.
bool ExecuteDFAOnevsRest(const std::map< std::string, std::string > &arguments)
Executes Discriminant Function Analysis for one group versus all others.
bool ExecuteCovarianceMatrix(const std::map< std::string, std::string > &arguments)
Calculates covariance matrix for a source or target group.
Results results
Current analysis results (cleared each Execute)
Definition conductor.h:143
bool ExecuteOMSizeCorrect(const std::map< std::string, std::string > &arguments)
Executes organic matter and particle size correction.
bool ExecuteLevenbergMarquardt(const std::map< std::string, std::string > &arguments)
Executes Levenberg-Marquardt nonlinear optimization.
bool ExecuteEDP(const std::map< std::string, std::string > &arguments)
Calculates two-way element discriminant power between two groups.
bool ExecuteEDPM(const std::map< std::string, std::string > &arguments)
Calculates multi-way element discriminant power across all groups.
bool ExecuteCorrelationMatrix(const std::map< std::string, std::string > &arguments)
Calculates correlation matrix for a source or target group.
std::unique_ptr< CMCMC< SourceSinkData > > MCMC
MCMC sampler (owned)
Definition conductor.h:142
Manages a collection of elemental profiles (samples) for source fingerprinting analysis.
Elemental_Profile SelectTopElementsAggregate(int n) const
Select top N elements across all samples (aggregate minimum)
Container for elemental concentration data of a single sediment sample.
vector< string > GetElementNames() const
Get list of all element names.
options & GetOptions()
Get reference to the options structure.
Definition interface.h:275
void SetOption(options_key opt, bool val)
Set a configuration option.
Definition interface.h:250
void SetLimit(_range lowhigh, const double &value)
Set upper or lower limit for value highlighting.
Definition interface.h:233
virtual void Start()
Makes the reporter visible or otherwise begins reporting.
virtual void SetYAxisTitle(const QString &title, int chart=0)=0
Sets the vertical axis title of a chart.
virtual void SetProgress(const double &prog)=0
Sets the primary progress fraction.
virtual void SetTitle(const QString &title, int chart=0)=0
Sets the title of a chart.
void SetAbsoluteValue(bool val)
Definition resultitem.h:57
void SetShowGraph(bool state)
Definition resultitem.h:80
void setYAxisTitle(const string &title)
Definition resultitem.h:39
void SetXAxisMode(xaxis_mode mode)
Definition resultitem.h:26
void SetYLimit(_range highlow, const double &value)
Definition resultitem.h:66
void setTableTitle(const string &Title)
Definition resultitem.h:47
void SetName(const string &_name)
Definition resultitem.h:21
void SetResult(Interface *_result)
Definition resultitem.h:18
void SetShowTable(bool state)
Definition resultitem.h:78
void setXAxisTitle(const string &title)
Definition resultitem.h:31
void SetYAxisMode(yaxis_mode mode)
Definition resultitem.h:25
void SetShowAsString(bool value)
Definition resultitem.h:29
void SetType(const result_type &_type)
Definition resultitem.h:23
void Append(const ResultItem &)
Definition results.cpp:25
string Error()
Definition results.h:27
void SetName(const string &_name)
Definition results.h:21
Holds a progress reporter for the duration of one analysis.
bool InitializeParametersAndObservations(const string &targetsamplename, estimation_mode est_mode=estimation_mode::elemental_profile_and_contribution)
Initialize parameters and observations for MCMC optimization.
bool PerformRegressionVsOMAndSize(const string &om, const string &particle_size, regression_form form, const double &p_value_threshold=0.05)
Performs multiple linear regression of elements vs OM and particle size.
Elemental_Profile_Set DifferentiationPower_Percentage(bool include_target)
Computes rank-based differentiation percentage for all source pairs.
CMBTimeSeriesSet BootStrap(const double &percentage, unsigned int num_iterations, string target_sample, bool use_softmax)
Performs bootstrap uncertainty analysis on source contributions.
SourceSinkData ExtractChemicalElements(bool isotopes) const
Extract only chemical elements (and optionally isotopes)
CMBVector ANOVA(bool use_log)
Performs one-way ANOVA for all elements across source groups.
bool SolveLevenberg_Marquardt(transformation trans=transformation::linear)
Solves for optimal source contributions using the Levenberg-Marquardt algorithm.
vector< CMBVector > StepwiseDiscriminantFunctionAnalysis(const string &source1, const string &source2)
Performs stepwise discriminant analysis between two specific sources.
ConcentrationSet * GetElementDistribution(const string &element_name)
Retrieves pointer to element distribution at dataset level.
SourceSinkData BoxCoxTransformed(bool calculate_optimal_lambda=false)
Applies Box-Cox transformation to all source groups for normalization.
void SetParameterEstimationMode(estimation_mode est_mode)
Sets the estimation mode for parameter optimization.
Elemental_Profile t_TestPValue(const string &source1, const string &source2, bool use_log)
Computes t-test p-values for element-wise differences between two sources.
vector< ResultItem > GetMLRResults()
Retrieves multiple linear regression results for all sample groups.
CMBVector BracketTest(const string &target_sample, bool correct_based_on_om_n_size)
Performs bracket test to check if target concentrations fall within source ranges.
void IncludeExcludeElementsBasedOn(const vector< string > &elements)
Sets element inclusion based on a specified list.
ResultItem GetPredictedElementalProfile(parameter_mode param_mode=parameter_mode::based_on_fitted_distribution)
Generates predicted elemental concentrations for the target sample.
void SetOMandSizeConstituents(const string &_omconstituent, const string &_sizeconsituent)
Sets the names of OM and particle size constituents.
SourceSinkData CreateCorrectedAndFilteredDataset(bool exclude_samples, bool exclude_elements, bool omnsizecorrect, const string &target="") const
Create a corrected and filtered copy of the dataset.
vector< string > NegativeValueCheck()
Checks for zero or negative concentration values across all sources.
CMBTimeSeriesSet VerifySource(const string &source_group, bool use_softmax, bool apply_om_size_correction)
Performs leave-one-out validation on a source group.
bool SetSelectedTargetSample(const string &sample_name)
Sets the currently selected target sample for analysis.
void AddtoToolsUsed(const string &tool)
Adds a tool name to the list of tools used in analysis.
DFA_result DiscriminantFunctionAnalysis()
Performs discriminant function analysis for all source groups.
vector< ResultItem > GetSourceProfiles()
Retrieves elemental profiles for all source groups.
Results MCMC(const string &target_sample, map< string, string > arguments, CMCMC< SourceSinkData > *mcmc, ProgressReporter *progress_window, const string &working_folder)
Performs Markov Chain Monte Carlo analysis for Bayesian source apportionment.
Elemental_Profile_Set DifferentiationPower(bool use_log, bool include_target)
Computes differentiation power for all source pairs.
SourceSinkData CreateCorrectedDataset(const string &target, bool omnsizecorrect, map< string, element_information > *elementinfo)
Create a corrected copy of the dataset for a specific target sample.
ResultItem GetObservedvsModeledElementalProfile(parameter_mode param_mode=parameter_mode::based_on_fitted_distribution)
Creates a comparison of observed vs modeled elemental profiles.
string GetTargetGroup() const
Retrieves the name of the target group.
Elemental_Profile_Set DifferentiationPower_P_value(bool include_target)
Computes t-test p-values for all source pairs.
ResultItem GetContribution()
Packages source contributions into a ResultItem for output.
ResultItem GetObservedvsModeledElementalProfile_Isotope(parameter_mode param_mode=parameter_mode::based_on_fitted_distribution)
Creates a comparison of observed vs modeled isotope delta values.
vector< string > OMandSizeConstituents()
Retrieves the names of OM and particle size constituents.
void SetProgressReporter(ProgressReporter *_rtw)
Sets the progress window for displaying optimization progress.
void InitializeParametersObservations(const vector< double > &mins, const vector< double > &maxs)
Definition testmcmc.cpp:8
@ direct
Use empirical statistics from data.
distribution_type
Enumeration of probability distribution types supported in SedSat3.
@ lognormal
Lognormal distribution: ln(x) ~ N(μ, σ²), for strictly positive variables.
@ normal
Normal (Gaussian) distribution: p(x) = N(μ, σ²)
@ single_column_x
Enable single-column mode for X-axis data representation.
@ low
Lower bound of the parameter range.
@ high
Upper bound of the parameter range.
@ predicted_concentration
@ elemental_profile_set
@ timeseries_set_first_symbol
@ source_elemental_profiles_based_on_source_data
CMBVectorSet projected
CMBVector p_values
CMBVectorSet eigen_vectors
CMBVector F_test_P_value
CMBVectorSetSet multi_projected
QString X_suffix
Suffix appended to X-axis field names in serialization.
Definition interface.h:33
QString Y_suffix
Suffix appended to Y-axis field names in serialization.
Definition interface.h:34