Skip to content

Commit 7e670d5

Browse files
Merge pull request #302 from PauloCarvalhoRJ/next_release
Contact analysis
2 parents 6080836 + cf6ea63 commit 7e670d5

37 files changed

+1802
-50
lines changed

GammaRay.pro

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ win32 {
3535

3636
SOURCES += main.cpp\
3737
dialogs/choosevariabledialog.cpp \
38+
dialogs/contactanalysisdialog.cpp \
3839
dialogs/faciestransitionmatrixoptionsdialog.cpp \
3940
dialogs/gridrepositiondialog.cpp \
4041
dialogs/listbuilderdialog.cpp \
@@ -49,7 +50,13 @@ SOURCES += main.cpp\
4950
geometry/intersectionfinder.cpp \
5051
geometry/quadrilateral.cpp \
5152
geometry/triangle.cpp \
53+
geostats/contactanalysis.cpp \
5254
geostats/mcmcdataimputation.cpp \
55+
geostats/searchannulus.cpp \
56+
geostats/searchannulusstratigraphic.cpp \
57+
geostats/searchsphericalshell.cpp \
58+
geostats/searchverticaldumbbell.cpp \
59+
geostats/searchwasher.cpp \
5360
gslib/gslibparams/gslibpardir.cpp \
5461
gslib/gslibparams/widgets/widgetgslibpardir.cpp \
5562
mainwindow.cpp \
@@ -308,6 +315,7 @@ SOURCES += main.cpp\
308315

309316
HEADERS += mainwindow.h \
310317
dialogs/choosevariabledialog.h \
318+
dialogs/contactanalysisdialog.h \
311319
dialogs/faciestransitionmatrixoptionsdialog.h \
312320
dialogs/gridrepositiondialog.h \
313321
dialogs/listbuilderdialog.h \
@@ -327,7 +335,13 @@ HEADERS += mainwindow.h \
327335
geometry/intersectionfinder.h \
328336
geometry/quadrilateral.h \
329337
geometry/triangle.h \
338+
geostats/contactanalysis.h \
330339
geostats/mcmcdataimputation.h \
340+
geostats/searchannulus.h \
341+
geostats/searchannulusstratigraphic.h \
342+
geostats/searchsphericalshell.h \
343+
geostats/searchverticaldumbbell.h \
344+
geostats/searchwasher.h \
331345
gslib/gslibparams/gslibpardir.h \
332346
gslib/gslibparams/widgets/widgetgslibpardir.h \
333347
util.h \
@@ -589,6 +603,7 @@ HEADERS += mainwindow.h \
589603

590604
FORMS += mainwindow.ui \
591605
dialogs/choosevariabledialog.ui \
606+
dialogs/contactanalysisdialog.ui \
592607
dialogs/faciestransitionmatrixoptionsdialog.ui \
593608
dialogs/gridrepositiondialog.ui \
594609
dialogs/listbuilderdialog.ui \
@@ -853,7 +868,7 @@ win32 {
853868
# The application version
854869
# Don't forget to update the Util::importSettingsFromPreviousVersion() method to
855870
# enable the import of registry/user settings of previous versions.
856-
VERSION = 6.18
871+
VERSION = 6.20
857872

858873
# Define a preprocessor macro so we can get the application version in application code.
859874
DEFINES += APP_VERSION=\\\"$$VERSION\\\"

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ If you enjoyed this project, you might also enjoy GeostatsPy: https://github.com
1515
Python script to convert Eclipse grids to Paraview-compatible VTU format: https://github.com/BinWang0213/PyGRDECL
1616

1717
VERSION HISTORY:<br>
18+
&nbsp;&nbsp;&nbsp;Version 6.20 - Contact Analysis.<br>
1819
&nbsp;&nbsp;&nbsp;Version 6.18 - MCRFSim execution in batch/unattended mode; dependencies upgrades (VTK, ITK, Boost, C++14, ...).<br>
1920
&nbsp;&nbsp;&nbsp;Version 6.17 - Transiography and MCRFSim for Bayesian approach; some fixes and improvements.<br>
2021
&nbsp;&nbsp;&nbsp;Version 6.16 - Upgrade of VTK to 9.1 and other years-old dependencies; some fixes.<br>

dialogs/contactanalysisdialog.cpp

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#include "contactanalysisdialog.h"
2+
#include "ui_contactanalysisdialog.h"
3+
4+
#include "domain/attribute.h"
5+
#include "domain/datafile.h"
6+
#include "domain/application.h"
7+
#include "domain/categorydefinition.h"
8+
#include "geostats/contactanalysis.h"
9+
#include "widgets/categoryselector.h"
10+
#include "widgets/linechartwidget.h"
11+
#include "dialogs/emptydialog.h"
12+
13+
#include <QMessageBox>
14+
#include <algorithm>
15+
16+
ContactAnalysisDialog::ContactAnalysisDialog(Attribute *attributeGrade,
17+
Attribute *attributeDomains,
18+
QWidget *parent) :
19+
QDialog(parent),
20+
ui(new Ui::ContactAnalysisDialog),
21+
m_attributeGrade(attributeGrade),
22+
m_attributeDomains(attributeDomains)
23+
{
24+
ui->setupUi(this);
25+
26+
//deletes dialog from memory upon user closing it
27+
this->setAttribute(Qt::WA_DeleteOnClose);
28+
29+
//set dialog title
30+
setWindowTitle( "Contact Analysis" );
31+
32+
//update the suffix of the lag size spin box with the length unit symbol.
33+
onLengthUnitSymbolChanged( ui->txtLengthUnitSymbol->text() );
34+
35+
//get the pointer to the variables' parent data file and set caption of the dialog's label
36+
m_dataFile = dynamic_cast<DataFile*>( attributeGrade->getContainingFile() );
37+
DataFile* dataFileOfDomain = dynamic_cast<DataFile*>( attributeDomains->getContainingFile() );
38+
if( ! m_dataFile || ! dataFileOfDomain || (dataFileOfDomain != m_dataFile ) ) { //sanity check
39+
Application::instance()->logError( "ContactAnalysisDialog::ContactAnalysisDialog(): "
40+
"Container file object of the grade and/or domains attributes is not a data file or "
41+
"their parent files are different, which is not allowed for contact anaysis. ", true );
42+
} else {
43+
//enable/disable certain dialog widgets depending on whether the data set is 3D or is gridded.
44+
ui->lblDataFile->setText( ui->lblDataFile->text() + "<b>" + m_dataFile->getName() + "</b>" );
45+
if( m_dataFile->isGridded() || !m_dataFile->isTridimensional() ){
46+
ui->lblZTolerance->setEnabled( false );
47+
ui->dblSpinZTolerance->setEnabled( false );
48+
}
49+
if( ! m_dataFile->isTridimensional() ) {
50+
ui->radioVertical->setEnabled( false );
51+
ui->radioOmni3D->setEnabled( false );
52+
}
53+
}
54+
55+
//display the variables' names
56+
ui->lblGradeAttribute->setText( ui->lblGradeAttribute->text() + "<b>" + attributeGrade->getName() + "</b>" );
57+
ui->lblDomainsAttribute->setText( ui->lblDomainsAttribute->text() + "<b>" + attributeDomains->getName() + "</b>" );
58+
59+
//get the domains variable's category definition
60+
CategoryDefinition* cd = m_dataFile->getCategoryDefinition( attributeDomains );
61+
if( ! cd ){ //sanity check
62+
Application::instance()->logError( "ContactAnalysisDialog::ContactAnalysisDialog(): "
63+
"Category definition of domains variable is null. ", true );
64+
}
65+
66+
//create the category selector widgets so the user can select both domains for the contact analysis
67+
m_selectorDomain1 = new CategorySelector( cd );
68+
m_selectorDomain2 = new CategorySelector( cd );
69+
ui->frmDomain1->layout()->addWidget( m_selectorDomain1 ); //Qt takes ownership of the widget object with this
70+
ui->frmDomain2->layout()->addWidget( m_selectorDomain2 ); //Qt takes ownership of the widget oject with this
71+
}
72+
73+
ContactAnalysisDialog::~ContactAnalysisDialog()
74+
{
75+
delete ui;
76+
}
77+
78+
void ContactAnalysisDialog::onLengthUnitSymbolChanged(QString lengthUnitSymbol)
79+
{
80+
ui->dblSpinLagSize->setSuffix( lengthUnitSymbol );
81+
}
82+
83+
void ContactAnalysisDialog::onProceed()
84+
{
85+
ContactAnalysis contactAnalysis;
86+
if( ui->radioLateral->isChecked() )
87+
contactAnalysis.setMode( ContactAnalysisMode::LATERAL );
88+
else
89+
contactAnalysis.setMode( ContactAnalysisMode::VERTICAL );
90+
contactAnalysis.setLagSize( ui->dblSpinLagSize->value() );
91+
contactAnalysis.setZtolerance( ui->dblSpinZTolerance->value() );
92+
contactAnalysis.setDomain1_code( static_cast<uint16_t>(m_selectorDomain1->getSelectedCategoryCode()) );
93+
contactAnalysis.setDomain2_code( static_cast<uint16_t>(m_selectorDomain2->getSelectedCategoryCode()) );
94+
contactAnalysis.setNumberOfLags( static_cast<uint16_t>(ui->spinNumberOfLags->value()) );
95+
contactAnalysis.setInputDataFile( m_dataFile );
96+
contactAnalysis.setAttributeGrade( m_attributeGrade );
97+
contactAnalysis.setAttributeDomains( m_attributeDomains );
98+
contactAnalysis.setMaxNumberOfSamples( static_cast<uint16_t>(ui->spinMaxNumberOfSamples->value()) );
99+
contactAnalysis.setMinNumberOfSamples( static_cast<uint16_t>(ui->spinMinNumberOfSamples->value()) );
100+
101+
if( ! contactAnalysis.run() ) {
102+
103+
Application::instance()->logError("ContactAnalysisDialog::onProceed(): failed execution:");
104+
Application::instance()->logError(" " + contactAnalysis.getLastError());
105+
QMessageBox::critical( this, "Error", "Contact analysis failed. Further details in the message panel." );
106+
107+
} else { //if the contact analysis completed successfully
108+
109+
//shortcut for the STL's not-a-number value.
110+
const double NaN = std::numeric_limits<double>::quiet_NaN();
111+
112+
//get the contact analysis results
113+
std::vector<
114+
std::pair<
115+
ContactAnalysis::Lag,
116+
ContactAnalysis::MeanGradesBothDomains
117+
>
118+
> results = contactAnalysis.getResults();
119+
120+
//prepare data points for chart plotting
121+
//outer vector: the series of multivariate data
122+
//inner vectors: each multivariate datum (each element is a X, Y1, Y2,... value).
123+
std::vector< std::vector<double> > chartData;
124+
125+
//traverse the results to fill the chart data
126+
//the desired effect is to have two different curves sharing a mirrored X-axis befitting a
127+
//contact analysis chart (NaN causes the line chart widget to not render the curve at the given point).
128+
for( const std::pair< ContactAnalysis::Lag, ContactAnalysis::MeanGradesBothDomains >& result : results ){
129+
// lag values grades of domain 1 grades of domain 2
130+
//indexes in the inner vectors: 0 1 2
131+
chartData.push_back( { -result.first, result.second.first, NaN } );
132+
}
133+
std::reverse( chartData.begin(), chartData.end() );
134+
for( const std::pair< ContactAnalysis::Lag, ContactAnalysis::MeanGradesBothDomains >& result : results ){
135+
// lag values grades of domain 1 grades of domain 2
136+
//indexes in the inner vectors: 0 1 2
137+
chartData.push_back( { result.first, NaN, result.second.second } );
138+
}
139+
140+
//get some properties of the domain categories relevant to make
141+
//the chart informative
142+
QColor colorDomain1, colorDomain2;
143+
QString nameDomain1, nameDomain2;
144+
{
145+
CategoryDefinition* cd = m_dataFile->getCategoryDefinition( m_attributeDomains );
146+
colorDomain1 = cd->getCustomColor( cd->getCategoryIndex( contactAnalysis.getDomain1_code() ));
147+
colorDomain2 = cd->getCustomColor( cd->getCategoryIndex( contactAnalysis.getDomain2_code() ));
148+
nameDomain1 = cd->getCategoryNameByCode( contactAnalysis.getDomain1_code() );
149+
nameDomain2 = cd->getCategoryNameByCode( contactAnalysis.getDomain2_code() );
150+
}
151+
152+
//display the results
153+
LineChartWidget* lcw = new LineChartWidget(this);
154+
lcw->setSharedYaxis( true );
155+
lcw->setChartTitle( "Contact analysis of " + m_dataFile->getName() );
156+
lcw->setData( chartData, 0,
157+
{{1, nameDomain1 + " (Domain 1)"}, {2, nameDomain2 + " (Domain 2)"}},
158+
{{2, "mean " + m_attributeGrade->getName() }}, // shared y-axis is enabled, set only the last one
159+
{{1, colorDomain1} , {2, colorDomain2}} );
160+
lcw->setXaxisCaption( "lag (" + ui->txtLengthUnitSymbol->text() + ")" );
161+
EmptyDialog* ed = new EmptyDialog( this );
162+
ed->addWidget( lcw );
163+
ed->setWindowTitle( "Contact analysis results" );
164+
ed->show();
165+
166+
}
167+
}

dialogs/contactanalysisdialog.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#ifndef CONTACTANALYSISDIALOG_H
2+
#define CONTACTANALYSISDIALOG_H
3+
4+
#include <QDialog>
5+
6+
namespace Ui {
7+
class ContactAnalysisDialog;
8+
}
9+
10+
class Attribute;
11+
class DataFile;
12+
class CategorySelector;
13+
14+
class ContactAnalysisDialog : public QDialog
15+
{
16+
Q_OBJECT
17+
18+
public:
19+
explicit ContactAnalysisDialog(Attribute* attributeGrade,
20+
Attribute* attributeDomains,
21+
QWidget *parent = nullptr);
22+
~ContactAnalysisDialog();
23+
24+
private:
25+
Ui::ContactAnalysisDialog *ui;
26+
27+
private Q_SLOTS:
28+
void onLengthUnitSymbolChanged( QString lengthUnitSymbol );
29+
void onProceed();
30+
31+
private:
32+
Attribute* m_attributeGrade;
33+
Attribute* m_attributeDomains;
34+
DataFile* m_dataFile;
35+
CategorySelector* m_selectorDomain1;
36+
CategorySelector* m_selectorDomain2;
37+
};
38+
39+
#endif // CONTACTANALYSISDIALOG_H

0 commit comments

Comments
 (0)